Skip to content

Commit

Permalink
feat: [TypeWrapping]イベントに対応
Browse files Browse the repository at this point in the history
  • Loading branch information
automatic9045 committed Jun 27, 2023
1 parent f5931cc commit 2f59b87
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 2 deletions.
10 changes: 10 additions & 0 deletions Libs/TypeWrapping/Loader/MemberParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ internal class MemberParser

private readonly Dictionary<string, FieldInfo> FieldCache = new Dictionary<string, FieldInfo>();
private readonly Dictionary<string, PropertyInfo> PropertyCache = new Dictionary<string, PropertyInfo>();
private readonly Dictionary<string, EventInfo> EventCache = new Dictionary<string, EventInfo>();
private readonly Dictionary<(string Name, Type[] Types), MethodInfo> MethodCache = new Dictionary<(string Name, Type[] Types), MethodInfo>();

public MemberParser(Type source)
Expand All @@ -38,6 +39,15 @@ public PropertyInfo GetProperty(string name, bool isNonPublic, bool isStatic)
return property;
}

public EventInfo GetEvent(string name, bool isNonPublic, bool isStatic)
{
if (EventCache.TryGetValue(name, out EventInfo @event)) return @event;

@event = Source.GetEvent(name, CreateBindingAttribute(isNonPublic, isStatic));
EventCache.Add(name, @event);
return @event;
}

public MethodInfo GetMethod(string name, Type[] types, bool isNonPublic, bool isStatic)
{
if (MethodCache.TryGetValue((name, types), out MethodInfo method)) return method;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ private class ResourceSet
[ResourceStringHolder(nameof(Localizer))] public Resource<string> OriginalFieldNotFound { get; private set; }
[ResourceStringHolder(nameof(Localizer))] public Resource<string> WrapperPropertyNotFound { get; private set; }
[ResourceStringHolder(nameof(Localizer))] public Resource<string> FieldWrapperPropertyNotFound { get; private set; }
[ResourceStringHolder(nameof(Localizer))] public Resource<string> WrapperEventNotFound { get; private set; }
[ResourceStringHolder(nameof(Localizer))] public Resource<string> WrapperMethodNotFound { get; private set; }
[ResourceStringHolder(nameof(Localizer))] public Resource<string> OriginalMethodNotFound { get; private set; }
[ResourceStringHolder(nameof(Localizer))] public Resource<string> NonPublic { get; private set; }
Expand Down Expand Up @@ -90,6 +91,46 @@ public PropertyInfo GetFieldWrapperProperty(XElement source)
GetAccessibilityDescription(isNonPublic, isStatic), name, WrapperType.Name));
}

public EventInfo GetWrapperEvent(XElement source)
{
(string name, bool isNonPublic, bool isStatic) = GetWrapperInfo(source);
EventInfo @event = WrapperMemberParser.GetEvent(name, isNonPublic, isStatic);

return @event ?? throw new KeyNotFoundException(
string.Format(Resources.Value.WrapperEventNotFound.Value,
GetAccessibilityDescription(isNonPublic, isStatic), name, WrapperType.Name));
}

public MethodInfo GetEventOriginalAddAccessor(XElement source, Type type)
{
(string name, bool isNonPublic, bool isStatic) = GetInfo(source, "OriginalAddAccessor", "IsOriginalAccessorNonPublic", "IsOriginalStatic");
MethodInfo method = OriginalMemberParser.GetMethod(name, new Type[] { type }, isNonPublic, isStatic);

return method ?? throw new KeyNotFoundException(
string.Format(Resources.Value.OriginalMethodNotFound.Value,
type, GetAccessibilityDescription(isNonPublic, isStatic), name, WrapperType.Name, OriginalType.Name));
}

public MethodInfo GetEventOriginalRemoveAccessor(XElement source, Type type)
{
(string name, bool isNonPublic, bool isStatic) = GetInfo(source, "OriginalRemoveAccessor", "IsOriginalAccessorNonPublic", "IsOriginalStatic");
MethodInfo method = OriginalMemberParser.GetMethod(name, new Type[] { type }, isNonPublic, isStatic);

return method ?? throw new KeyNotFoundException(
string.Format(Resources.Value.OriginalMethodNotFound.Value,
type, GetAccessibilityDescription(isNonPublic, isStatic), name, WrapperType.Name, OriginalType.Name));
}

public FieldInfo GetEventOriginalDelegate(XElement source)
{
(string name, _, bool isStatic) = GetInfo(source, "OriginalDelegateField", "_", "IsOriginalStatic");
FieldInfo field = OriginalMemberParser.GetField(name, true, isStatic);

return field ?? throw new KeyNotFoundException(
string.Format(Resources.Value.OriginalFieldNotFound.Value,
GetAccessibilityDescription(true, isStatic), name, WrapperType.Name, OriginalType.Name));
}

public MethodInfo GetWrapperMethod(XElement source, Type[] types)
{
(string name, bool isNonPublic, bool isStatic) = GetWrapperInfo(source);
Expand Down
18 changes: 17 additions & 1 deletion Libs/TypeWrapping/Loader/WrapTypesXmlLoader.MemberLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ protected override void LoadClasses(IEnumerable<XElement> classElements, IEnumer
Dictionary<string, FastMethod> propertyGetters = new Dictionary<string, FastMethod>();
Dictionary<string, FastMethod> propertySetters = new Dictionary<string, FastMethod>();
Dictionary<string, FastField> fields = new Dictionary<string, FastField>();
Dictionary<string, FastEvent> events = new Dictionary<string, FastEvent>();
Dictionary<Type[], FastConstructor> constructors = new Dictionary<Type[], FastConstructor>();
Dictionary<(string, Type[]), FastMethod> methods = new Dictionary<(string, Type[]), FastMethod>();

Expand Down Expand Up @@ -105,6 +106,21 @@ protected override void LoadClasses(IEnumerable<XElement> classElements, IEnumer
}
}

{
IEnumerable<XElement> eventElements = classElement.Elements(TargetNamespace + "Event");
foreach (XElement eventElement in eventElements)
{
EventInfo wrapperEvent = elementParser.GetWrapperEvent(eventElement);

MethodInfo originalAddAccessor = elementParser.GetEventOriginalAddAccessor(eventElement, Resolver.GetOriginal(wrapperEvent.EventHandlerType));
MethodInfo originalRemoveAccessor = elementParser.GetEventOriginalRemoveAccessor(eventElement, Resolver.GetOriginal(wrapperEvent.EventHandlerType));

FieldInfo originalDelegate = elementParser.GetEventOriginalDelegate(eventElement);

events.Add(wrapperEvent.Name, new FastEvent(originalAddAccessor, originalRemoveAccessor, originalDelegate));
}
}

bool isStruct = originalType.IsValueType && !originalType.IsPrimitive && !originalType.IsEnum;
if (!isStruct && !originalType.IsAbstract)
{
Expand Down Expand Up @@ -149,7 +165,7 @@ protected override void LoadClasses(IEnumerable<XElement> classElements, IEnumer
}
}

ClassMemberSet members = new ClassMemberSet(wrapperType, originalType, propertyGetters, propertySetters, fields, constructors, methods);
ClassMemberSet members = new ClassMemberSet(wrapperType, originalType, propertyGetters, propertySetters, fields, events, constructors, methods);
return members;
});

Expand Down
3 changes: 3 additions & 0 deletions Libs/TypeWrapping/Resources/ClassMemberSet.ja.resx
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@
<data name="OriginalConstructorNotFound" xml:space="preserve">
<value>オリジナルコンストラクタが見つかりませんでした。{0} '{1}' は無効なキーです。</value>
</data>
<data name="OriginalEventNotFound" xml:space="preserve">
<value>オリジナルイベントが見つかりませんでした。{0} '{1}' は無効なキーです。</value>
</data>
<data name="OriginalFieldNotFound" xml:space="preserve">
<value>オリジナルフィールドが見つかりませんでした。{0} '{1}' は無効なキーです。</value>
</data>
Expand Down
3 changes: 3 additions & 0 deletions Libs/TypeWrapping/Resources/ClassMemberSet.resx
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@
<data name="OriginalConstructorNotFound" xml:space="preserve">
<value>オリジナルコンストラクタが見つかりませんでした。{0} '{1}' は無効なキーです。</value>
</data>
<data name="OriginalEventNotFound" xml:space="preserve">
<value>オリジナルイベントが見つかりませんでした。{0} '{1}' は無効なキーです。</value>
</data>
<data name="OriginalFieldNotFound" xml:space="preserve">
<value>オリジナルフィールドが見つかりませんでした。{0} '{1}' は無効なキーです。</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@
<data name="Static" xml:space="preserve">
<value>静的</value>
</data>
<data name="WrapperEventNotFound" xml:space="preserve">
<value>{0}イベント '{1}' はラッパー型 '{2}' に存在しません。</value>
</data>
<data name="WrapperMethodNotFound" xml:space="preserve">
<value>パラメータ '{0}' をもつ{1}メソッド '{2}' はラッパー型 '{3}' に存在しません。</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@
<data name="Static" xml:space="preserve">
<value>static</value>
</data>
<data name="WrapperEventNotFound" xml:space="preserve">
<value>A {0} event '{1}' does not exist in the wrapper type '{2}.'</value>
</data>
<data name="WrapperMethodNotFound" xml:space="preserve">
<value>A {1} method named '{2}' with parameter(s) '{0}' does not exist int the wrapper type '{3}.'</value>
</data>
Expand Down
12 changes: 11 additions & 1 deletion Libs/TypeWrapping/TypeMemberSet/ClassMemberSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ private class ResourceSet

[ResourceStringHolder(nameof(Localizer))] public Resource<string> OriginalPropertyNotFound { get; private set; }
[ResourceStringHolder(nameof(Localizer))] public Resource<string> OriginalFieldNotFound { get; private set; }
[ResourceStringHolder(nameof(Localizer))] public Resource<string> OriginalEventNotFound { get; private set; }
[ResourceStringHolder(nameof(Localizer))] public Resource<string> OriginalConstructorNotFound { get; private set; }
[ResourceStringHolder(nameof(Localizer))] public Resource<string> OriginalMethodNotFound { get; private set; }

Expand All @@ -39,19 +40,21 @@ static ClassMemberSet()
private readonly IReadOnlyDictionary<string, FastMethod> PropertyGetters;
private readonly IReadOnlyDictionary<string, FastMethod> PropertySetters;
private readonly IReadOnlyDictionary<string, FastField> Fields;
private readonly IReadOnlyDictionary<string, FastEvent> Events;
private readonly IReadOnlyDictionary<Type[], FastConstructor> Constructors;
private readonly IReadOnlyDictionary<(string Name, Type[] Parameters), FastMethod> Methods;

internal ClassMemberSet(Type wrapperType, Type originalType,
IReadOnlyDictionary<string, FastMethod> propertyGetters, IReadOnlyDictionary<string, FastMethod> propertySetters, IReadOnlyDictionary<string, FastField> fields,
IReadOnlyDictionary<Type[], FastConstructor> constructors, IReadOnlyDictionary<(string, Type[]), FastMethod> methods)
IReadOnlyDictionary<string, FastEvent> events, IReadOnlyDictionary<Type[], FastConstructor> constructors, IReadOnlyDictionary<(string, Type[]), FastMethod> methods)
: base(wrapperType, originalType)
{
Constructors = constructors;

PropertyGetters = propertyGetters;
PropertySetters = propertySetters;
Fields = fields;
Events = events;
Methods = methods;
}

Expand All @@ -76,6 +79,13 @@ public FastField GetSourceFieldOf(string wrapperName)
: throw new KeyNotFoundException(string.Format(Resources.Value.OriginalFieldNotFound.Value, nameof(wrapperName), wrapperName));
}

public FastEvent GetSourceEventOf(string wrapperName)
{
return Events.TryGetValue(wrapperName, out FastEvent @event)
? @event
: throw new KeyNotFoundException(string.Format(Resources.Value.OriginalEventNotFound.Value, nameof(wrapperName), wrapperName));
}

public FastConstructor GetSourceConstructor(Type[] parameters = null)
{
FastConstructor matchConstructor = Constructors.FirstOrDefault(x => parameters is null || x.Key.SequenceEqual(parameters)).Value;
Expand Down
13 changes: 13 additions & 0 deletions Libs/TypeWrapping/WrapTypesXmlSchema.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,19 @@
</xs:complexType>
</xs:element>

<xs:element name="Event" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="Wrapper" type="DotNetName" use="required" />
<xs:attribute name="IsWrapperNonPublic" type="xs:boolean" default="false" />
<xs:attribute name="IsWrapperStatic" type="xs:boolean" default="false" />
<xs:attribute name="OriginalAddAccessor" type="DotNetName" use="required" />
<xs:attribute name="OriginalRemoveAccessor" type="DotNetName" use="required" />
<xs:attribute name="OriginalDelegateField" type="DotNetName" use="required" />
<xs:attribute name="IsOriginalAccessorNonPublic" type="xs:boolean" default="false" />
<xs:attribute name="IsOriginalStatic" type="xs:boolean" default="false" />
</xs:complexType>
</xs:element>

<xs:element name="Method" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="Wrapper" type="DotNetName" use="required" />
Expand Down

0 comments on commit 2f59b87

Please sign in to comment.