Вы можете представить создание объекта, используя Expression.New()
. Вы можете передать ему либо Type
, который имеет конструктор без параметров, либо ConstructorInfo
вместе с Expression
s, представляющими параметры конструктора. Если вы хотите вернуть object
и хотите, чтобы он работал и для типов значений, вам также необходимо добавить Expression.Convert()
.
Если сложить все вместе, эквивалент Activator.CreateInstance()
может выглядеть так:
object CreateInstance(Type type)
{
return Expression.Lambda<Func<object>>(
Expression.Convert(Expression.New(type), typeof(object)))
.Compile()();
}
Если вы хотите сделать то же самое в IL, вам нужно использовать инструкцию newobj
для ссылочных типов. Если вы хотите сделать то же самое для типов значений, вы можете создать локальную переменную этого типа, поставить ее в рамку и вернуть:
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);
}