一个构造函数作为代表 – 它可能在C#中?

我有一个类如下:

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

我需要传递给某个方法一个委托像这样:

 delegate Foo FooGenerator(int x); 

是否有可能作为FooGenerator值直接传递构造函数,而不必键入:

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

编辑:对于我个人的使用,这个问题是指.NET 2.0,但3.0 +提示/响应也是受欢迎的。

不,CLR不允许绑定委托给ConstructorInfo

但是,您可以创build自己的:

 static T Make<T>(Action<T> init) where T : new() { var t = new T(); init(t); return t; } 

用法

 var t = Make<Foo>( x => { x.Bar = "bar"; x.Baz = 1; }); 

我假设你通常会做这样的工厂实现的一部分,实际types不知道在编译时…

首先,请注意,更简单的方法可能是创build后的init步骤,那么您可以使用generics:

 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 

我认为就像你将要得到的那样简洁(不用移植到一个工厂模式)将会是一些匿名方法,例如:

 delegate Foo FooGenerator(int x); ... void DoStuff() { YourDelegateConsumer(x => new Foo(x)); } 

这不是严格按照你所要求的(因为你将一个委托传递给一个返回一个新实例的匿名方法,而不是直接委托给构造函数),但是我不认为你在问什么是严格可行的。

当然,这是假设你使用3.5+

这听起来像你可能想要使用类工厂模式。

工厂方法模式

不幸的是,构造函数与方法不太一样,所以你不能创build一个指向它们的委托。 尽pipe这是一个有趣的想法,也许有了更多的信息,我们可以devise一些类似于句法的解决方法。

马克·格雷维尔(Marc Gravell)的回答启发了我以下非常简单的解决方

 static void Main() { Pet a = _MakeObject(typeof(Dog)); Pet b = _MakeObject(typeof(Cat)); } private static Pet _MakeObject(Type type) { ConstructorInfo info = type.GetConstructor(new Type[0]); return (Pet)info?.Invoke(null); } 

几乎相同的事情,如果你的构造函数有参数(在这个例子中:1参数typesint):

 static void Main() { Pet a = _MakeObject(typeof(Dog), 5); Pet b = _MakeObject(typeof(Cat), 7); } private static Pet _MakeObject(Type type, int age) { ConstructorInfo info = type.GetConstructor(new [] { typeof(int) }); return (Pet)info?.Invoke(new object[] { age }); } 

我的猜测是,这是不可能的,因为你会传递一个尚未创build的对象的方法。