【发布时间】:2012-04-03 15:41:57
【问题描述】:
我知道Activator.CreateInstance() 可以创建object 的新实例。但我正在寻找一种通过IL 和Expression 创建实例的方法。我想我可以创建一个动态 lambda 来创建一个类型的实例,并缓存 lambda 以加快对象初始化。我对吗?你能帮帮我吗?
【问题讨论】:
标签: c# delegates lambda expression il
我知道Activator.CreateInstance() 可以创建object 的新实例。但我正在寻找一种通过IL 和Expression 创建实例的方法。我想我可以创建一个动态 lambda 来创建一个类型的实例,并缓存 lambda 以加快对象初始化。我对吗?你能帮帮我吗?
【问题讨论】:
标签: c# delegates lambda expression il
您可以使用Expression.New() 表示对象的创建。您可以将具有无参数构造函数的Type 或ConstructorInfo 以及代表构造函数参数的Expressions 传递给它。如果您想返回 object 并且希望它也适用于值类型,则还需要添加 Expression.Convert()。
把它们放在一起,相当于Activator.CreateInstance() 可能看起来像这样:
object CreateInstance(Type type)
{
return Expression.Lambda<Func<object>>(
Expression.Convert(Expression.New(type), typeof(object)))
.Compile()();
}
如果你想在 IL 中做同样的事情,你需要使用 the newobj instruction 作为引用类型。如果你想对值类型做同样的事情,你可以创建一个该类型的局部变量,将其装箱并返回:
object CreateInstance(Type type)
{
var method = new DynamicMethod("", typeof(object), Type.EmptyTypes);
var il = method.GetILGenerator();
if (type.IsValueType)
{
var local = il.DeclareLocal(type);
// method.InitLocals == true, so we don't have to use initobj here
il.Emit(OpCodes.Ldloc, local);
il.Emit(OpCodes.Box, type);
il.Emit(OpCodes.Ret);
}
else
{
var ctor = type.GetConstructor(Type.EmptyTypes);
il.Emit(OpCodes.Newobj, ctor);
il.Emit(OpCodes.Ret);
}
return method.Invoke(null, null);
}
【讨论】:
Expression?你在哪里学的?提前致谢
Expression。就像我说的,你可以为构造函数提供参数作为New()方法的参数,可能使用Expression.Constant()。