我正在使用MethodCallExpression来记录方法调用。
public void RegisterInvocation<TSource>
(TSource target, Expression<Action<TSource>> selector)
{
...
}
稍后我会执行这样的表达式:
selector.Compile().Invoke();
在这里我有一个奇怪的效果(也许我误解了方法调用表达式)。
如果我使用普通变量或常量参数注册方法调用,则使用正确的参数调用方法:
string item = "sometext";
instance.RegisterInvocation<ITarget>(this, p => p.Add(item));
但是如果我使用实例变量参数注册方法调用,则在执行时而不是在注册时使用实例变量的参数值调用该方法:
public class Target : ITarget
{
string item;
public void DoSomething()
{
this.item = "sometext";
instance.RegisterInvocation<ITarget>(this, p => p.Add(this.item));
this.item = "anothertext";
instance.CallRegisteredInvocation();
}
public void Add(string item)
{
// "somestring" expected, but item is = "anotherstring"
}
}
有没有办法在注册时使用参数调用方法调用表达式?
答案 0 :(得分:2)
您看到此行为的原因是因为lambda表达式
p => p.Add(this.item)
“捕获”字段item
(而不是其值)。当表达式树被编译成lambda时,它仍将包含对该字段的引用,而不是它当时的值。如果您想确保在注册时拥有该值,您可以复制该值:
public void DoSomething()
{
this.item = "sometext";
var itemCopy = item;
instance.RegisterInvocation<ITarget>(this, p => p.Add(itemCopy));
this.item = "anothertext";
instance.CallRegisteredInvocation();
}
答案 1 :(得分:0)
这是因为您改变了捕获的变量(item
)。