2017-01-23 45 views
2

我有以下类(我无法改变他们,他们是不是在我的控制):如何使用反射创建基于lambda的委托?

public abstract class BusinessBase { } 
public class A : BusinessBase { } 
public class B : BusinessBase { } 

public class FooOne 
{ 
    public void Foo<T>(FooDelegates.Func<T> func) where T : BusinessBase { ... } 
} 

public class FooTwo 
{ 
    public void Foo<T>(FooDelegates.Func<T> func) where T : BusinessBase { ... } 
} 

public static class FooDelegates 
{ 
    public delegate TResult Func<TResult>(); 
} 

创建委托和调用方法很简单:

var f1 = new FooOne(); 
f1.Foo(() => new A()); 

然而,试图用反射来做到这一点证明是有点复杂。我有以下功能似乎我不能完成:

public class GenericHelper 
{ 
    // Parent can be A or B or etc... 
    // Child is FooOne or FooTwo or etc... 
    public void Relate(object parent, object child) 
    { 
     var mi = child.GetType().GetMethod("Foo"); 
     var gmi = mi.MakeGenericMethod(parent.GetType()); 

     // This next part obviously won't compile... 
     var del = typeof(FooDelegates.Func<>).MakeGenericType(parent.GetType()); 
     FooDelegates.Func<parent.GetType()> del =() => parent; 
     gmi.Invoke(child, new object[] { del }); 
    } 
} 

如何正确生成一个FooDelegates.Func<T>其中T是父类,我有一个匿名方法的分配方法?

+0

您需要创建和编译'()'表达式树 – SLaks

回答

1

您可以使用表达式树在运行时编译的新功能:

Expression.Lambda(del, Expression.Constant(parent)).Compile() 
+0

'del'是'Type'的委托类型。您需要从'Compile()'传递已编译的委托_value_。 – SLaks

+0

经过修正和调整后,它非常接近。虽然我得到了一个不同的错误:'System.ArgumentException:类型'Expression'1的对象不能被转换为[...]'。 – michael

+0

听起来像你没有调用'Compile()'。 – SLaks