如何设置局部变量memberExpression值
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何设置局部变量memberExpression值相关的知识,希望对你有一定的参考价值。
我想获取参数原始名称并更新其值。我怎样才能做到这一点?
public void SetMember<T>(Expression<Func<T>> memberExpression)
{
var body = (MemberExpression)memberExpression.Body;
var name = body.Member.Name; //text
//can I set variable value here
}
static void Main(string[] args)
{
var text="test";
SetMember(() => text);
}
答案
是的,可以,在对象中捕获局部变量,该对象将作为常量存储在表达式树中。
您可以编译一个设置捕获字段值的新方法:
public static void SetMember<T>(Expression<Func<T>> memberExpression, T newVlaue)
{
var body = (MemberExpression)memberExpression.Body;
var name = body.Member.Name; //text
var newValueParam = Expression.Parameter(typeof(T));
var newBody = Expression.Assign(body, newValueParam);
var setter = Expression.Lambda<Action<T>>(newBody, newValueParam).Compile();
setter(newVlaue); // Set with the new value
}
或者您可以使用常量值的反射
public static void SetMember<T>(Expression<Func<T>> memberExpression, T newVlaue)
{
var body = (MemberExpression)memberExpression.Body;
var name = body.Member.Name; //text
var constant = body.Expression as ConstantExpression;
(body.Member as FieldInfo).SetValue(constant.Value, newVlaue);
}
注意只是因为你可以这样做并不意味着你应该这样做。这取决于变量捕获的内部结构,并且可能随着编译器的新实现而改变。并且不要认为它不会发生,当C#编译器切换到Roslyn时,是否有一些匿名函数被转换为静态或实例方法改变了我写的一些“聪明的代码”,所以使用你自己的危险。
更简洁的方法是使用out
/ ref
参数,如果你只想设置局部变量,nameof
,如果你因为某些原因需要变量的名称,这将更快更干净,更可靠,但需要你使用两个地方的局部变量。
public static void SetMember<T>(ref T local, T newValue, string nameOfLocal)
{
local = newValue;
// nameofLocal can be used ..
}
static void Main(string[] args)
{
var text = "test";
SetMember(ref text, "new value", nameof(text));
Console.Write(text);
}
以上是关于如何设置局部变量memberExpression值的主要内容,如果未能解决你的问题,请参考以下文章