aka*_*vel 57 c# constructor delegates
我有一个类如下:
class Foo
{
public Foo(int x) { ... }
}
Run Code Online (Sandbox Code Playgroud)
我需要传递一个像这样的委托的方法:
delegate Foo FooGenerator(int x);
Run Code Online (Sandbox Code Playgroud)
是否可以直接将构造函数作为FooGenerator值传递,而无需键入:
delegate(int x) { return new Foo(x); }
Run Code Online (Sandbox Code Playgroud)
?
编辑:对于我个人使用,问题涉及.NET 2.0,但欢迎3.0 +的提示/响应.
Mar*_*ell 55
我假设你通常会做这样的事情作为工厂实现的一部分,其中实际的类型在编译时是不知道的...
首先,请注意,更简单的方法可能是创建后的初始化步骤,然后您可以使用泛型:
static T Create<T>({args}) where T : class, ISomeInitInterface, new() {
T t = new T();
t.Init(args);
return t;
}
Run Code Online (Sandbox Code Playgroud)
然后你可以使用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
Run Code Online (Sandbox Code Playgroud)
或(使用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
Run Code Online (Sandbox Code Playgroud)
lep*_*pie 29
不,CLR不允许绑定代理ConstructorInfo.
但是,您可以创建自己的:
static T Make<T>(Action<T> init) where T : new()
{
var t = new T();
init(t);
return t;
}
Run Code Online (Sandbox Code Playgroud)
用法
var t = Make<Foo>( x => { x.Bar = "bar"; x.Baz = 1; });
Run Code Online (Sandbox Code Playgroud)
我认为你将得到的简洁(没有转向工厂模式)将是匿名方法,如下所示:
delegate Foo FooGenerator(int x);
...
void DoStuff()
{
YourDelegateConsumer(x => new Foo(x));
}
Run Code Online (Sandbox Code Playgroud)
这并没有严格按照你的要求进行(因为你将委托传递给一个返回新实例的匿名方法,而不是直接委托给构造函数),但我不认为你要求的是什么是严格可能的.
当然,这是假设您使用3.5+