Reputation: 1387
I use expression trees to build delegates at runtime :
Type type = GetType();
ParameterExpression parameterType = Expression.Parameter(type);
...
Delegate delegate = Expression.Lambda(*something*, parameterType).Compile();
I don't know at compile time the type returned by the method GetType(). Is it possible to invoke my delegate without using the expensive DynamicInvoke() method ?
Edit :
In my application I have a base abstract class :
public abstract class Frame
{
public string RawContent { get; set; }
// ...
}
At runtime the application will use some objects which inherits Frame; the type of these objects is not known at compile time, because they will be loaded with MEF (plug-ins). The goal of the application is to filter the objects with erroneous data : for example, if the program must process some objects of a class like this one :
public class Frame01 : Frame
{
public int Counter6hours { get; set; }
public int DeltaCounter6hours { get; set; }
}
I would like my users to be able to write, in the configuration file of the application, something like this :
<filtersSection>
<filters>
<filter class="Frame01" expression="Counter6hours < 0" />
<filter class="Frame01" expression="DeltaCounter6hours > 2500" />
</filters>
<filtersSection>
I manage to create an expression tree and compile it into a delegate for each filter. But I can't cast it into Func because I don't know the type Frame01 at compile time... So, for the moment, I use the method DynamicInvoke() of my delegates, which invokes in a late-bound way the underlying methods. The application will have to handle a large amount of objects, and I fear performance issues... So, in this example, I'm trying to build programmatically a Func object, but I'm not sure it's possible.
PS : Excuse me for my poor English...
Upvotes: 4
Views: 1571
Reputation: 244837
It's still not completely clear to me this is what you want, but I think all you need is a cast: your expression will have a parameter of type Frame
, cast it to Frame01
and then run your filters on that.
In code:
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();
With that, the following tests pass:
Assert.IsTrue(result(new Frame01 { Counter6hours = -1 }));
Assert.IsFalse(result(new Frame01 { Counter6hours = 1 }));
Assert.Throws<InvalidCastException>(() => result(new Frame02()));
Upvotes: 4
Reputation: 24383
From your comments, you want to end up with a Func<object, bool>
So, you have to build your expression tree taking a parameter of type object
Something like this will work:
var p = Expression.Parameter(typeof(object));
var c = Expression.Constant(true);
var lambda = Expression.Lambda(c,p);
var fn = ( Func<object, bool> ) lambda.Compile();
Then:
bool b = fn( ...some object... );
Upvotes: 0