Arbre d'expression: éviter DynamicInvoke

c# delegates expression-trees

Question

J'utilise des arbres d'expression pour générer des délégués lors de l'exécution:

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

Je ne sais pas au moment de la compilation le type renvoyé par la méthode GetType (). Est-il possible d'appeler mon délégué sans utiliser la méthode coûteuse DynamicInvoke ()?

Modifier :

Dans mon application, j'ai une classe abstraite de base:

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

Au moment de l'exécution, l'application utilisera des objets qui héritent de Frame; le type de ces objets n'est pas connu au moment de la compilation, car ils seront chargés avec MEF (plug-ins). Le but de l'application est de filtrer les objets avec des données erronées: par exemple, si le programme doit traiter des objets d'une classe comme celle-ci:

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

J'aimerais que mes utilisateurs puissent écrire, dans le fichier de configuration de l'application, quelque chose comme ceci:

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

Je parviens à créer un arbre d'expression et à le compiler en délégué pour chaque filtre. Mais je ne peux pas le transformer en Func car je ne connais pas le type Frame01 au moment de la compilation ... Donc, pour le moment, j'utilise la méthode DynamicInvoke () de mes délégués, qui appelle de manière tardive le méthodes sous-jacentes. L'application devra gérer une grande quantité d'objets et je crains des problèmes de performances ... Dans cet exemple, j'essaie de créer par programme un objet Func, mais je ne suis pas sûr que ce soit possible.

PS: Excusez-moi pour mon pauvre anglais ...

Réponse acceptée

Pour moi, ce n’est pas encore tout à fait clair, c’est ce que vous voulez, mais je pense que tout ce dont vous avez besoin est un transtypage: votre expression aura un paramètre de type Frame , Frame01 en Frame01 , puis utilisez vos filtres.

Dans du 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();

Avec cela, les tests suivants réussissent:

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

Réponse populaire

De vos commentaires, vous voulez vous retrouver avec un Func<object, bool>

Donc, vous devez construire votre arbre d'expression en prenant un paramètre de type object

Quelque chose comme ça va marcher:

var p = Expression.Parameter(typeof(object));
var c = Expression.Constant(true);
var lambda = Expression.Lambda(c,p);
var fn = ( Func<object, bool> ) lambda.Compile();

Alors:

var p = Expression.Parameter(typeof(object));
var c = Expression.Constant(true);
var lambda = Expression.Lambda(c,p);
var fn = ( Func<object, bool> ) lambda.Compile();



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi