schglurps
schglurps

Reputation: 1387

Expression tree : avoid DynamicInvoke

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

Answers (2)

svick
svick

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

Nick Butler
Nick Butler

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

Related Questions