Expression tree : avoid DynamicInvoke

c# delegates expression-trees

Question

In order to create delegates at runtime, I utilize expression trees:

Type type = GetType();
ParameterExpression parameterType = Expression.Parameter(type);
...
Delegate delegate = Expression.Lambda(*something*, parameterType).Compile();

The type returned by the procedure GetType is unknown to me at build time (). Can my delegate be called without utilizing the pricey DynamicInvoke() method?

Edit :

I have a basic abstract class in my program:

public abstract class Frame
{
    public string RawContent { get; set; }

    // ...
}

Although the nature of these objects is unknown at build time since they will be loaded using MEF, the application will utilize certain objects that derive from Frame during runtime (plug-ins). The application's objective is to filter out items with inaccurate data. For instance, suppose the program has to handle certain objects from the following class:

public class Frame01 : Frame
{
    public int Counter6hours { get; set; }

    public int DeltaCounter6hours { get; set; }
}

I want my users to be able to enter information in the application's configuration file that looks something like this:

<filtersSection>
    <filters>
            <filter class="Frame01" expression="Counter6hours < 0" />
            <filter class="Frame01" expression="DeltaCounter6hours > 2500" />
    </filters>
<filtersSection>

For each filter, I succeed in building an expression tree and compiling it into a delegate. But because I don't know the type of Frame01 at compilation time, I can't cast it into Func. Therefore, I now utilize the DynamicInvoke() function of my delegates, which late-boundly activates the underlying methods. There will be a lot of items for the program to process, and I worry about performance difficulties. So I'm attempting to generate a Func object programmatically in this example, but I'm not sure whether that's really doable.

Please excuse my terrible English.

1
3
12/13/2012 9:37:48 AM

Accepted Answer

Although I'm still not quite sure this is what you want, I believe all you need is a cast since your expression will contain a parameter of typeFrame , throw it toFrame01 and then run your filters on that.

With 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();

Thus, the following tests are successful:

Assert.IsTrue(result(new Frame01 { Counter6hours = -1 }));
Assert.IsFalse(result(new Frame01 { Counter6hours = 1 }));
Assert.Throws<InvalidCastException>(() => result(new Frame02()));
2
12/13/2012 1:00:03 PM

Popular Answer

You hope to come to a conclusion based on your remarks.Func<object, bool>

Therefore, you must construct your expression tree using a kind of parameter.object

This sort of thing will function:

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... );


Related Questions





Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow