2017-01-23 44 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