2010-03-12 91 views
2

我不知道C#(或底层的.NET框架)是否支持某种“通用委托实例”:这是一个委托实例,它仍然有一个未解析的类型参数,在代理被解析时被调用(不是在创建委托时)。我怀疑这是不可能的,但我仍然要求它...通用委托实例

这是我想要做的一个例子,用一些“???”插入C#语法似乎不可用的地方。 (显然这个代码不能编译)

class Foo { 
    public T Factory<T>(string name) { 
    // implementation omitted 
    } 
} 

class Test { 
    public void TestMethod() 
    { 
    Foo foo = new Foo(); 
    ??? magic = foo.Factory; // No type argument given here yet to Factory! 
          // What would the '???' be here (other than 'var' :))? 
    string aString = magic<string>("name 1"); // type provided on call 
    int anInt = magic<int>("name 2"); // another type provided on another call 

    // Note the underlying calls work perfectly fine, these work, but i'd like to expose 
    // the generic method as a delegate. 
    string aString2 = foo.Factory<string>("name 1"); 
    int anInt2 = foo.Factory<int>("name 2"); 
    } 
} 

有没有一种方法可以在C#中实际执行此类操作?如果没有,这是语言的限制,还是在.NET框架?

编辑: 我想问的原因是因为我想委托传递给函数在其他组件,并且不希望要求不必引用任何特定类型的其他组件(以下简称“富“在我的例子中的类)。我希望以某种方式弯曲标准Func <>委托,以适应“???”部分。

+0

C#也知道这个词var和将得到的构建类型。 – Younes 2010-03-12 10:44:11

+0

你知道你可以foo.Factory (“名字1”),我想。你能否扩展你的问题来解释为什么你需要使用魔术而不是foo.Factory ? – 2010-03-12 10:48:51

+0

你也可以写'对象':)。 object magic = foo.Factory; – 2010-03-12 10:54:35

回答

7

这是无法完成的,因为您要求的是声明非封闭泛型类型的变量(magic)。

人们可以用不封闭的仿制药,但只有在类型级别的工作,如:

delegate T FactoryDelegate<T>(string name); 

var magicType = typeof (FactoryDelegate<>); 

,然后“关闭”在稍后的类型:

var stringMagic = magicType.MakeGenericType(typeof(string)); 

更新:那说,这里是一个关于如何使用上述技术来处理未封闭的方法“类型”的示例。还不如优雅的,因为这将是如果我们能够分配虽然未封闭的类型..:

public class UnclosedMethod 
    { 
     private readonly MethodInfo _method; 

     public UnclosedMethod(Type type, string method) 
     { 
      _method = type.GetMethod(method); 
     } 

     public T Invoke<T>(string name) 
     { 
      var fact = _method.MakeGenericMethod(typeof(T)); 
      return (T)fact.Invoke(this, new object[] { name }); 
     } 
    } 

然后在代码中做到这一点:

var magic = new UnclosedMethod(typeof(Foo), "Factory"); 
var x = magic.Invoke<string>("bar"); 
+0

感谢您的回答,我已经怀疑过这样的事情。 这留下了第二部分的问题:“是C#语言的限制,还是它在.NET框架中”。 – 2010-03-12 10:58:20

0

就有点像?:

Foo foo = new Foo(); 
string aString = 
    foo.GetType().GetMethod("Factory").MakeGenericMethod(string) 
     .Invoke(foo, new object[] { "name 1" }); 
int anInt = 
    foo.GetType().GetMethod("Factory").MakeGenericMethod(int) 
     .Invoke(foo, new object[] { "name 2" }); 

现在,如果你想使用代表,你可能会得到类似的结果:

public delegate T FactoryDelegate<T>(string name); 

然后,您可以作出这样一个电话:

public TestMethod1(FactoryDelegate<dynamic> factory) 
{ 
    object o = factory("name 3"); 
}