Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

a constructor as a delegate - is it possible in C#?

I have a class like below:

class Foo {   public Foo(int x) { ... } } 

and I need to pass to a certain method a delegate like this:

delegate Foo FooGenerator(int x); 

Is it possible to pass the constructor directly as a FooGenerator value, without having to type:

delegate(int x) { return new Foo(x); } 

?

EDIT: For my personal use, the question refers to .NET 2.0, but hints/responses for 3.0+ are welcome as well.

like image 489
akavel Avatar asked Oct 21 '09 13:10

akavel


1 Answers

I'm assuming you would normally do something like this as part of a factory implementation, where the actual types aren't known at compile-time...

First, note that an easier approach may be a post-create init step, then you can use generics:

static T Create<T>({args}) where T : class, ISomeInitInterface, new() {     T t = new T();     t.Init(args);     return t; } 

You can then use MakeGenericMethod and/or CreateDelegate.


Otherwise; you can do this with on the fly with Expression (3.5) or DynamicMethod (2.0).

The Expression approach is easier to code:

    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 

or (using 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 
like image 196
Marc Gravell Avatar answered Oct 02 '22 16:10

Marc Gravell