我可以使用System.Reflection.Emit为现有类型构建构造函数吗?

时间:2016-07-12 04:01:09

标签: c#

c#是否支持使用DynamicMethod构建构造函数?考虑这个课程:

public class Foo
{
    public string Bar { get; set; }

    public Foo(string bar)
    {
        Bar = bar;
    }
}

我想为Foo创建一个不带参数的新构造函数,并将其编译为Func<Foo>。例如:

DynamicMethod dyn = new DynamicMethod("NewInitializer", typeof(Foo), Type.EmptyTypes);
ILGenerator il = dyn.GetILGenerator();

LocalBuilder loc0 = il.DeclareLocal(typeof(Foo));
il.Emit(OpCodes.Ldloca_S, loc0);
il.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ret);

Func<Foo> newInitFunc = (Func<Foo>)dyn.CreateDelegate(typeof(Func<Foo>));
Foo f = newInitFunc();

注意,这只是我尝试过的一个实现。一切都最终抛出AccessViolationException

  

操作可能会使运行时不稳定

当我调用方法时。甚至可以使用DynamicMethod

创建构造函数

1 个答案:

答案 0 :(得分:0)

如果可以从这些类型继承,则可以使用Emit创建一个继承自现有类型的类,而不调用基本构造函数。

var typeToLoad = typeof(Foo);
var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Dynamic"), AssemblyBuilderAccess.Run);
var moduleBuilder = assemblyBuilder.DefineDynamicModule("Dynamic");
var typeBuilder = moduleBuilder.DefineType(typeToLoad.Name, TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AnsiClass | TypeAttributes.AutoClass, typeToLoad);
// create a constructor that doesn't call the base constructor
var constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName, CallingConventions.Standard, Type.EmptyTypes);
var ilGenerator = constructorBuilder.GetILGenerator();
ilGenerator.Emit(OpCodes.Ret);
// create a factory method so we could create a delegate for it
var methodBuilder = typeBuilder.DefineMethod("Create", MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig, typeBuilder, Type.EmptyTypes);
ilGenerator = methodBuilder.GetILGenerator();
ilGenerator.Emit(OpCodes.Newobj, constructorBuilder);
ilGenerator.Emit(OpCodes.Ret);
var generatedType = typeBuilder.CreateType();
var factory = (Func<Foo>)generatedType.GetMethod("Create", BindingFlags.Public | BindingFlags.Static).CreateDelegate(typeof(Func<Foo>));

此速度与new运算符一样快。