具有动态参数的表达式树 [英] Expression Trees with dynamic parameter

查看:68
本文介绍了具有动态参数的表达式树的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要转换为:

Func<dynamic, object> myFunc = t => return t.Name + " " + t.Surname;

进入表达式树。

什么我想出的是这样的:

What I have came up with, is this:

ParameterExpression target = ExpressionParameter(typeof(dynamic), "target");
ParameterExpression result = ExpressionParameter(typeof(object), "result");
BlockExpression block = Expression.Block(
     new [] { result },
     Expression.Assign(
           result,
           Expression.Add(
                 Expression.Add(
                      Expression.Property(target, "Name"),
                      Expression.Constant(" ", typeof(string))
                 ),
                 Expression.Property(target, "Surname")
           )
     )
);
Func<dynamic, object> myFunc = Expression.Lambda<dynamic, object>>(block, target).Compile();

但是,编译器不喜欢 typeof(dynamic),我有点理解。 动态不是类型,本质上是对象

However, the compiler doesn't like typeof(dynamic), and I kind of get it. dynamic isn't a type, it is an object in essence.

所以我继续更改 ParameterExpression

ParameterExpression target = ExpressionParameter(typeof(object), "target");

代码现在可以编译了,但是在运行时出现了问题。

The code now compiles, but there is a problem at runtime.

我正在尝试获取目标的属性名称的值感觉对象是否是动态

I am trying to get the value of the property Name of target, which may have sense if the object was dynamic.

但是由于目标被认为是对象类型 ,表达式引发错误,告诉我名称作为属性不存在。

But since target is considered of type object, the Expression throws an error telling me Name doesn't exist as a property.

是否存在用于获取动态属性的表达式?

Is there an Expression for fetching a dynamic property?

推荐答案

那些对解决方案感兴趣的人:

For those who are or were interested in a solution:

ParameterExpression target = Expression.Parameter(typeof(object), "target");
ParameterExpression result = Expression.Parameter(typeof(object), "result");

CallSiteBinder getName = Binder.GetMember(
   CSharpBinderFlags.None, "Name", typeof(Program),
   new CSharpArgumentInfo[] {
       CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
   }
);

CallSiteBinder getSurname= Binder.GetMember(
   CSharpBinderFlags.None, "Surname", typeof(Program),
   new CSharpArgumentInfo[] {
       CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
   }
);

BlockExpression block = Expression.Block(
    new[] { result },
    Expression.Assign(
        result,
        Expression.Call(typeof(string).GetMethod("Concat", new Type[] { typeof(object[]) }),
                        Expression.NewArrayInit(typeof(object),
                             Expression.Dynamic(getName, typeof(object), target),
                             Expression.Constant(" ", typeof(object)),
                             Expression.Dynamic(getSurname, typeof(object), target)
                        )
       )
    )
);

Func<dynamic, object> myFunc = Expression.Lambda<Func<dynamic, object>>(block, target).Compile();

这正是我在做什么:


  1. 创建一个 CallSiteBinder 来获取动态对象的动态属性 Name 的值作为参数传递

  2. 创建了一个 CallSiteBinder ,该值获得了动态属性 Surname 作为参数传递的动态对象

  3. 调用方法 string.Concat(params object [] args)。为此,我需要将参数作为 object 的数组发送。我正在使用 getName getSurname

  1. Created a CallSiteBinder that obtains the value of the dynamic property Name of the dynamic object passed as argument
  2. Created a CallSiteBinder that obtains the value of the dynamic property Surname of the dynamic object passed as argument
  3. Invoked the method string.Concat(params object[] args). For that, I need to send my arguments as an array of object. I'm creating the array with the values of getName, " ", and getSurname.

我使用以下答案作为指导和参考:

I used the following answer as a guide and reference:

表达式树中的C#4动态

使用上述方法,可以执行以下操作:

With the above approach, one could do something like this:

dynamic person = new ExpandoObject();
person.Name = "Matt";
person.Surname = "Smith";

object value = myFunc(person);
Console.WriteLine(value); //Will print out "Matt Smith"

//Internally it just calls:
//string.Concat(new object[] { person.Name, " ", person.Surname });

这篇关于具有动态参数的表达式树的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆