lets say you have a Type (T) that implements an interface (I1)
T : I1
and I1 is implementing an other interface I2
I1 : I2
1. If your are implementing a Type that implements Interface I1 than runsharp
is not checking for the proper implementation of the methods of I2 AND does not
call tb.DefineMethodOverride in any situation which makes it impossible to
implement them. (You get a TypeLoadException at type completion)
2. If you are using a variable (Operand) with type of I1 you can't use the
methods of I2
3. You can't create nested Delegates
4. You can't create Explicit Event implementations
I needed all of those features so i added them myself (i added the changed
files as attachments, they should work with 0.1.2, but maybe i changed other
things as well!):
Fix for Issue 1+2:
Add the following methods to TypeInfo.cs
private static IEnumerable<Type> SearchableTypes(Type t)
{
if (t.IsInterface)
{
foreach (Type @interface in SearchInterfaces(t))
{
yield return @interface;
}
}
else
{
foreach (Type baseType in SearchBaseTypes(t))
{
yield return baseType;
}
}
}
private static IEnumerable<Type> SearchBaseTypes(Type t)
{
yield return t;
t = t.BaseType;
if (t != null)
{
foreach (Type baseType in SearchBaseTypes(t))
{
yield return baseType;
}
}
}
public static IEnumerable<Type> SearchInterfaces(Type t)
{
yield return t;
foreach (Type @interface in t.GetInterfaces())
{
foreach (Type baseInterface in SearchInterfaces(@interface))
{
yield return baseInterface;
}
}
}
in the Find* (FindField,FindProperty,FindEvent,FindMethod) Methods change the
following lines
for (; t != null; t = t.BaseType)
to
foreach (Type type in SearchableTypes(t))
In TypeGen.cs change the ScanMethodsToImplement method to
void ScanMethodsToImplement(Type[] interfaces)
{
if (interfaces == null)
return;
foreach (Type t in interfaces)
{
foreach (Type @interface in TypeInfo.SearchInterfaces(t))
{
foreach (IMemberInfo mi in TypeInfo.GetMethods(@interface))
implementations.Add(new InterfaceImplEntry(mi));
}
}
}
Fix for Issue 3:
Add this method to TypeGen.cs
public DelegateGen Delegate(Type returnType, string name)
{
DelegateGen dg = new DelegateGen(this, name, returnType, (typeVis | typeVirt | typeFlags | TypeAttributes.Class | TypeAttributes.Sealed) ^ TypeAttributes.BeforeFieldInit);
ResetAttrs();
return dg;
}
Add this field to DelegateGen.cs
TypeGen owner2;
Add this constructor to DelegateGen.cs
public DelegateGen(TypeGen typeGen, string name, Type returnType, TypeAttributes typeAttributes)
: base(returnType)
{
this.owner2 = typeGen;
this.name = name;
this.attrs = typeAttributes;
}
Change the first Lines in ImplementDelegate() (DelegateGen.cs)
from
TypeGen tg = new TypeGen(owner, name, attrs, typeof(MulticastDelegate), Type.EmptyTypes);
to
TypeGen tg;
if (owner == null)
{
tg = new TypeGen(owner2, name, attrs, typeof(MulticastDelegate), Type.EmptyTypes);
}
else
{
tg = new TypeGen(owner, name, attrs, typeof(MulticastDelegate), Type.EmptyTypes);
}
Fix for issue 4:
Add the following method to TypeGen.cs
public EventGen EventImplementation(Type interfaceType, Type eventHandlerType, string name)
{
if (tb.IsInterface)
throw new InvalidOperationException(Properties.Messages.ErrInterfaceNoExplicitImpl);
EventGen eg = new EventGen(this, name, eventHandlerType,
MethodAttributes.Private | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final);
eg.ImplementedInterface = interfaceType;
return eg;
}
Add the following to EventGen.cs
private Type interfaceType;
void LockSignature()
{
if (eb == null)
{
eb = owner.TypeBuilder.DefineEvent(interfaceType == null ? name : interfaceType.FullName + "." + name, EventAttributes.None, type);
owner.RegisterForCompletion(this);
}
}
internal Type ImplementedInterface
{
get { return interfaceType; }
set { interfaceType = value; }
}
Change the EventGen constructor to:
internal EventGen(TypeGen owner, string name, Type type, MethodAttributes mthAttr)
{
this.owner = owner;
this.name = name;
this.type = type;
this.attrs = mthAttr;
}
And the EventGen.AddMethod(string) and EventGen.RemoveMethod(string) to
public MethodGen AddMethod(string parameterName)
{
if (adder == null)
{
LockSignature();
adder = new MethodGen(owner, "add_" + name, attrs | MethodAttributes.SpecialName, typeof(void), 0);
adder.ImplementedInterface = interfaceType;
adder.Parameter(type, parameterName);
eb.SetAddOnMethod(adder.GetMethodBuilder());
}
return adder;
}
public MethodGen RemoveMethod(string parameterName)
{
if (remover == null)
{
LockSignature();
remover = new MethodGen(owner, "remove_" + name, attrs | MethodAttributes.SpecialName, typeof(void), 0);
remover.ImplementedInterface = interfaceType;
remover.Parameter(type, parameterName);
eb.SetRemoveOnMethod(remover.GetMethodBuilder());
}
return remover;
}
I hope these changes are fitting in your library and do not break something ;).
They are working for me at least.
And i hope someone saves some time with this post, instead of investigating the
issues.
I really want to thank you for this amazing library ... If i had not found your
library i think i would code exactly the same thing :)
You saved me really a lot of time (except for this issues it was not always
easy to track them down, and find the right solution ;) )
If somebody can see a breaking change or something like this please feel free
to post here.
Original issue reported on code.google.com by matth...@googlemail.com on 25 Sep 2010 at 1:41
Original issue reported on code.google.com by
matth...@googlemail.com
on 25 Sep 2010 at 1:41Attachments: