Я предполагаю, что вы обычно делаете что-то подобное в рамках фабричной реализации, где фактические типы не известны во время компиляции ...
Во-первых, обратите внимание, что более простым подходом может быть этап инициализации после создания, затем вы можете использовать обобщенные значения:
static T Create<T>({args}) where T : class, ISomeInitInterface, new() {
T t = new T();
t.Init(args);
return t;
}
Затем вы можете использовать MakeGenericMethod
и / или CreateDelegate
.
В противном случае; Вы можете сделать это на лету с помощью Expression
(3.5) или DynamicMethod
(2.0).
Подход Expression
легче кодировать:
var param = Expression.Parameter(typeof(int), "val");
var ctor = typeof(Foo).GetConstructor(new[] { typeof(int) });
var lambda = Expression.Lambda<Func<int, Foo>>(
Expression.New(ctor, param), param);
var func = lambda.Compile();
Foo foo = func(123);
string s = foo.ToString(); // proof
или (используя DynamicMethod
):
ConstructorInfo ctor = typeof(Foo).GetConstructor(new[] { typeof(int) });
DynamicMethod dm = new DynamicMethod("Create", typeof(Foo),
new Type[] { typeof(int) }, typeof(Foo), true);
ILGenerator il = dm.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Newobj, ctor);
il.Emit(OpCodes.Ret);
Converter<int, Foo> func = (Converter<int, Foo>)
dm.CreateDelegate(typeof(Converter<int, Foo>));
Foo foo = func(123);
string s = foo.ToString(); // proof