具有动态参数的表达式树 [英] Expression Trees with dynamic parameter
问题描述
我要转换为:
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();
这正是我在做什么:
- 创建一个
CallSiteBinder
来获取动态对象的动态属性Name
的值作为参数传递 - 创建了一个
CallSiteBinder
,该值获得了动态属性Surname $ c $的值c>作为参数传递的动态对象
- 调用方法
string.Concat(params object [] args)
。为此,我需要将参数作为object
的数组发送。我正在使用getName
,getSurname
。
- Created a
CallSiteBinder
that obtains the value of the dynamic propertyName
of the dynamic object passed as argument - Created a
CallSiteBinder
that obtains the value of the dynamic propertySurname
of the dynamic object passed as argument - Invoked the method
string.Concat(params object[] args)
. For that, I need to send my arguments as an array ofobject
. I'm creating the array with the values ofgetName
," "
, andgetSurname
.
我使用以下答案作为指导和参考:
I used the following answer as a guide and reference:
使用上述方法,可以执行以下操作:
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屋!