2010-07-05 1 views
2

Ok premier à expliquer les règles:Comment obtenir des informations d'exécution argument de tableau de paramètres arbre extression

je besoin d'une fonction qui construit un délégué correspondant à tout type de délégué qui encapsule un corps qui invoque un délégué de type (Object) (Object [] args) avec 'args' contenant tous les arguments passés au délégué d'origine lors de l'invocation.

Mon travail à ce jour:

delegate void TestDelegate(int x, int y); 
    delegate object TestDelegate2(object[] args); 

    static void Main(string[] sargs) 
    { 
     TestDelegate d = (TestDelegate)CreateAnonymousFromType(typeof(TestDelegate)); 
     object ret = d.DynamicInvoke(2, 6); 

     if (ret != null) { Console.WriteLine(ret); } 

     Console.ReadKey(); 
    } 

    static void SpecialInvoke(int x, int y) 
    { 
     Console.WriteLine("x: {0}\r\ny: {1}", x, y); 
    } 

    static Delegate CreateAnonymousFromType(Type type) 
    { 
     MethodInfo method = type.GetMethod("Invoke"); 

     TestDelegate2 _delegate = new TestDelegate2(
      delegate(object[] args) 
      { 
       Console.WriteLine("x: {0}\r\ny: {1}", args[0], args[1]); 
       return "This is the return"; 
      }); 


     var typeargs = CreateArgs(method.GetParameters()); 
     var argindex = -1; 

     var tmp = Expression.Parameter(typeof(Object), "tmp"); 
     var index = Expression.Parameter(typeof(int), "index"); 

     var length = Expression.Constant(typeargs.Length); 

     var _break = Expression.Label("breakto"); 

     var delegateargs = Expression.Parameter(typeof(object[]), "args"); 

     return Expression.Lambda(
      type, 
      Expression.Block(
       new[] { tmp, index, delegateargs }, 
       Expression.Assign(index, Expression.Constant(0)), 
       Expression.Assign(delegateargs, Expression.NewArrayBounds(typeof(Object), length)), 
       Expression.Loop(
        Expression.IfThenElse(Expression.LessThan(index, length), 
         Expression.Block(
          Expression.Assign(tmp, Expression.Convert(typeargs[++argindex], typeof(Object))), 
          Expression.Assign(Expression.ArrayAccess(delegateargs, index), tmp), 
          Expression.PostIncrementAssign(index) 
         ), 
         Expression.Break(_break) 
        ), 
        _break 
       ), 
       Expression.Call(_delegate.Method, delegateargs) 
      ), 
      typeargs 
     ).Compile(); 
    } 

    static ParameterExpression[] CreateArgs(ParameterInfo[] _params) 
    { 
     ParameterExpression[] ret = new ParameterExpression[_params.Length]; 

     for (int i = 0; i < ret.Length; i++) 
      ret[i] = Expression.Parameter(_params[i].ParameterType, _params[i].Name); 

     return ret; 
    } 

Maintenant cela fonctionne SORTA ... Je ne reçois la valeur de typeargs [0] transmis au délégué "TestDelegate2" pour les deux paramètres x et y, les « args 'paramètre à l'exécution est object [] {2, 2} et je ne peux pas pour la vie de moi trouver un moyen d'incrémenter "argindex" dans la portée de l'argument itération ... nombre de paramètres à la compilation est indéfini. Quelqu'un sait comment je peux résoudre ce problème?

J'ai essayé simplement de copier le tableau d'arguments en utilisant Expression.NewArrayInit (typeof (Object), typeargs), mais qui ne dit qu'il ne peut pas utiliser Int32 pour initialiser un tableau d'objet

J'ai aussi essayé ceci: var arguments = Expression.Constant (typeargs);

Et en accédant à la valeur de "arguments" à "index", cependant, cela produit les chaînes "x" et "y" .. apparemment les noms des arguments et non leurs valeurs.

Ceci est honnêtement ma première tentative majeure d'utiliser des arbres d'expression pour toute aide .. peu importe le peu. Serait apprécié.

Merci.

Répondre

2

Je pense que vous étiez sur la bonne voie avec Expression.NewArrayInit. Vous pouvez fixer la « Une expression de type « System.Int32 » ne peut pas être utilisé pour initialiser un tableau de type « System.Object » » erreur en utilisant Expression.Convert pour insérer une conversion pour chaque paramètre:

var typeargs = CreateArgs(method.GetParameters()); 
return Expression.Lambda(
    type, 
    Expression.Call(_delegate.Method, Expression.NewArrayInit(typeof(object), 
     typeargs.Select(arg => Expression.Convert(arg, typeof(object))) 
     )), 
    typeargs 
).Compile(); 
+0

Doux !! Je savais qu'il devait y avoir une solution quelque part ... il est facile de trouver des informations sur la création d'arbres d'expression de base mais très peu sur les expressions qui prennent des paramètres et comment utiliser les paramètres dans les blocs d'expression suivants. Cela a fonctionné parfait! Et le code est beaucoup plus court. Bravo à ça! =) – SilverX

Questions connexes