我使用表達式樹在運行時構建委託:
Type type = GetType();
ParameterExpression parameterType = Expression.Parameter(type);
...
Delegate delegate = Expression.Lambda(*something*, parameterType).Compile();
我不知道在編譯時GetType()方法返回的類型。是否可以在不使用昂貴的DynamicInvoke()方法的情況下調用我的委託?
編輯:
在我的應用程序中,我有一個基本的抽像類:
public abstract class Frame
{
public string RawContent { get; set; }
// ...
}
在運行時,應用程序將使用一些繼承Frame的對象;這些對象的類型在編譯時是未知的,因為它們將加載MEF(插件)。該應用程序的目標是使用錯誤數據過濾對象:例如,如果程序必須處理類似這樣的類的某些對象:
public class Frame01 : Frame
{
public int Counter6hours { get; set; }
public int DeltaCounter6hours { get; set; }
}
我希望我的用戶能夠在應用程序的配置文件中編寫如下內容:
<filtersSection>
<filters>
<filter class="Frame01" expression="Counter6hours < 0" />
<filter class="Frame01" expression="DeltaCounter6hours > 2500" />
</filters>
<filtersSection>
我設法創建一個表達式樹並將其編譯為每個過濾器的委託。但我無法將其轉換為Func,因為我在編譯時不知道Frame01的類型...所以,目前,我使用我的委託的方法DynamicInvoke(),它以後期方式調用基本方法。應用程序將不得不處理大量的對象,我擔心性能問題......所以,在這個例子中,我試圖以編程方式構建一個Func對象,但我不確定它是否可行。
PS:對不起我的英語不好......
我仍然不完全清楚這是你想要的,但我認為你需要的只是一個演員:你的表達式將有一個Frame
類型的參數,將它轉換為Frame01
,然後運行你的過濾器。
在代碼中:
var type = typeof(Frame01);
var param = Expression.Parameter(typeof(Frame));
var casted = Expression.Convert(param, type);
// this part will be dynamic in your actual code
var condition = Expression.LessThan(
Expression.Property(casted, "Counter6hours"), Expression.Constant(0));
var result = Expression.Lambda<Func<Frame, bool>>(condition, param)
.Compile();
有了這個,以下測試通過:
Assert.IsTrue(result(new Frame01 { Counter6hours = -1 }));
Assert.IsFalse(result(new Frame01 { Counter6hours = 1 }));
Assert.Throws<InvalidCastException>(() => result(new Frame02()));
從你的評論中,你想得到一個Func<object, bool>
因此,您必須使用object
類型的參數構建表達式樹
這樣的東西會起作用:
var p = Expression.Parameter(typeof(object));
var c = Expression.Constant(true);
var lambda = Expression.Lambda(c,p);
var fn = ( Func<object, bool> ) lambda.Compile();
然後:
bool b = fn( ...some object... );