Dan*_*şar 11 c# reflection reflection.emit ilgenerator
我需要动态创建一个类.大多数工作正常,但我坚持生成构造函数.
AssemblyBuilder _assemblyBuilder =
AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("MyBuilder"), AssemblyBuilderAccess.Run);
ModuleBuilder _moduleBuilder = _assemblyBuilder.DefineDynamicModule("MyModule");
public static object GetInstance<TSource, TEventArgs>(this TSource source, string eventName)
where TSource : class
{
var typeName = "MyTypeName";
var typeBuilder = _moduleBuilder.DefineType(typeName, TypeAttributes.Class | TypeAttributes.Public);
// create type like class MyClass : GenericType<MyClass, TSource, TEventArgs>
var baseNotGenericType = typeof(GenericType<,,>);
var baseType = baseNotGenericType.MakeGenericType(typeBuilder, typeof(TSource), typeof(TEventArgs));
typeBuilder.SetParent(baseType);
// the base class contains one constructor with string as param
var baseCtor = baseNotGenericType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(string) }, null);
var ctor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard | CallingConventions.HasThis, new Type[0]);
var ilGenerator = ctor.GetILGenerator();
// i want to call the constructor of the baseclass with eventName as param
ilGenerator.Emit(OpCodes.Ldarg_0); // push "this"
ilGenerator.Emit(OpCodes.Ldstr, eventName); // push the param
ilGenerator.Emit(OpCodes.Call, baseCtor);
ilGenerator.Emit(OpCodes.Ret);
var type = typeBuilder.CreateType();
// return ...
}
Run Code Online (Sandbox Code Playgroud)
在调用构造函数时,我得到一个BadImageFormatException.我究竟做错了什么?
按照要求:
BaseClass看起来像这样:
public abstract class GenericType<GT, TEventSource, TEventArgs> : BaseClass
where GT: GenericType<GT, TEventSource, TEventArgs>, new()
where TEventArgs : EventArgs
where TEventSource : class
{
protected GenericType(string eventName)
{
_eventName = eventName;
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
我想在运行时得到什么:
public class MyType : BaseClass<MyType, ConcreteSourceType, ConcreteEventArgsType>
{
protected MyType() : base("SomeName")
{
}
}
Run Code Online (Sandbox Code Playgroud)
svi*_*ick 11
我认为问题是你试图调用open泛型类型的构造函数GenericType<GT, TEventSource, TEventArgs>,但是你需要调用closed类型的构造函数BaseClass<MyType, ConcreteSourceType, ConcreteEventArgsType>.解决方案似乎很简单:
var baseCtor = baseType.GetConstructor(
BindingFlags.NonPublic | BindingFlags.Instance, null,
new[] { typeof(string) }, null);
Run Code Online (Sandbox Code Playgroud)
问题是这不起作用并抛出NotSupportedException.所以,它似乎得到了泛型类型的构造函数,其中一个参数是一个TypeBuilder坚果支持.
因此,我认为使用Reflection.Emit是不可能的,除非有一些黑客可以解决这个问题.
编辑: A-HA!我不得不深入研究Reflector中的Reflection.Emit (虽然在文档中查找正确的位置也会有效),但我发现它:有一种特殊的方法:静态TypeBuilder.GetConstructor().所以这应该工作:
var baseNonGenericCtor = baseNotGenericType.GetConstructor(
BindingFlags.NonPublic | BindingFlags.Instance, null,
new[] { typeof(string) }, null);
var baseCtor = TypeBuilder.GetConstructor(baseType, baseNonGenericCtor);
Run Code Online (Sandbox Code Playgroud)
最简单的方法是将抽象类和派生类编译成一个简单的程序集,然后使用“Reflection.Emit”语言在 Reflector 中打开它们:
http://reflectoraddins.codeplex.com/

是的,这听起来很酷:)