Expression.Bind() - 它实际上是做什么的?

17

我最近一直在尝试动态构建表达式树,发现了这个看起来有点奇怪的方法。一开始我以为“哦,很棒,这正是我需要的”,因为我经常编写类似下面的代码:

var left = member is FieldInfo ? Expression.Field(instance, (FieldInfo)member) : Expression.Property(instance, (PropertyInfo)member);
var right = ...
var assign = Expression.Assign(left, right);

是的,我知道有Expression.PropertyOrField()调用,但它会往返反射以通过名称查找成员,而通常我已经拥有MemberInfo实例。

总之,我认为Expression.Bind()对我很有用,但它做了一些我不太理解的事情。给定以下代码:

void Main()
{
    var m = typeof(Foo).GetField("Bar");
    Expression.Bind(m, Expression.Constant("")).Dump();
}

public class Foo
{
    public string Bar;
}

它生成了 MemberAssignment 表达式 Bar = ""。但是没有实例和静态引用。我怎样才能将此表达式应用于 Foo 的实例呢?我找不到使用此方法的任何示例。

1个回答

15

对象初始化表达式.

假设你有以下代码:

public class Foo
{
    public int Property { get; set; }
}

那么你可以这样做:

var parameter = Expression.Parameter(typeof(int), "i");
var newExpr = Expression.New(typeof(Foo));
var bindExprs = new[]
    {
        Expression.Bind(typeof(Foo).GetProperty("Property"), parameter)
        // You can bind more properties here if you like.
    };

var body = Expression.MemberInit(newExpr, bindExprs);
var lambda = Expression.Lambda<Func<int, Foo>>(body, parameter);

这类技术大致如下:

i => new Foo { Property = i } 

New:

我无法帮助您解决您想要解决的“性能问题”(使用Expression.PropertyOrField是否真的会在您的应用程序中引入瓶颈?我有些怀疑。您应该在过早优化之前确定这一点)(编辑:对于错误地假设这是一个性能优化而道歉,正如您自己发现的那样,Expression.MakeMemberAccess才是您需要的),但我可以告诉您Expression.Bind有什么用。


3
哦...我本来以为那就是它的用法,但我期望 Expression.New() 会有一个重载方法来接收它。我没想到可能是完全不同的调用方式。 - Ilia G
关于不使用 PropertyOrField:那并不是真正的优化,更像是为了我的心理健康。 - Ilia G
啊,如果是这样的话,为什么不写一个小助手来接收MemberInfo并根据需要进行分支呢? - Ani
我有...只是它似乎是一个非常常见的操作,应该有一个标准的实现。 - Ilia G
好的,很公正;对我过早下结论感到抱歉! - Ani
顺便说一下...显然有这个东西Expression.MakeMemberAccess,它恰好做我需要的事情... 羞愧地低下头 - Ilia G

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接