我使用表达式树在运行时构建委托:
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:请原谅我的英语不好......答案 0 :(得分:2)
我仍然不完全清楚这是你想要的,但我认为你需要的只是一个演员:你的表达式将有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()));
答案 1 :(得分:0)
根据您的评论,您希望得到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... );