使用FieldInfo.SetValue VS LINQ EX pressions在一个结构设置字段
问题描述
我要设置使用LINQ EX pressions私人领域。我有这个code:
I want to set private fields using LINQ expressions. I have this code:
//parameter "target", the object on which to set the field `field`
ParameterExpression targetExp = Expression.Parameter(typeof(object), "target");
//parameter "value" the value to be set in the `field` on "target"
ParameterExpression valueExp = Expression.Parameter(typeof(object), "value");
//cast the target from object to its correct type
Expression castTartgetExp = Expression.Convert(targetExp, type);
//cast the value to its correct type
Expression castValueExp = Expression.Convert(valueExp, field.FieldType);
//the field `field` on "target"
MemberExpression fieldExp = Expression.Field(castTartgetExp, field);
//assign the "value" to the `field`
BinaryExpression assignExp = Expression.Assign(fieldExp, castValueExp);
//compile the whole thing
var setter = Expression.Lambda<Action<object, object>> (assignExp, targetExp, valueExp).Compile();
这编译一个委托,它接受两个对象,目标和值:
This compiles a delegate that takes two objects, the target and the value:
setter(someObject, someValue);
在键入
变量指定键入
目标,而字段
<的 code>
变量是一个
字段信息
指定要设置的字段。
的>
The type
variable specifies the Type
of the target, and the field
variable is a FieldInfo
that specifies the field to be set.
这对于引用类型的伟大工程,但如果目标是一个结构,那么这个东西会通过在目标作为副本给setter的委托,并设置值的副本,而不是设置像原始目标的价值我要。 (至少这是我觉得是怎么回事。)
This works great for reference types, but if the target is a struct, then this thing will pass the target as a copy to the setter delegate and set the value on the copy, instead of setting the value on the original target like I want. (At least that is what I think is going on.)
在另一方面,
field.SetValue(someObject, someValue);
工作得很好,即使是结构。
works just fine, even for structs.
有什么我可以做这是为了使用编译前pression设定目标的领域?
Is there anything I can do about this in order to set the field of the target using the compiled expression?
推荐答案
对于值类型,使用<一个href="https: msdn.microsoft.com en-us library system.linq.ex$p$pssions.ex$p$pssion.unbox(v="vs.110).aspx"相对=nofollow">
防爆pression.Unbox的代替的
防爆pression.Convert 。
一个href="https:>
For value types, use Expression.Unbox instead of Expression.Convert.
//cast the target from object to its correct type
Expression castTartgetExp = type.IsValueType
? Expression.Unbox(targetExp, type)
: Expression.Convert(targetExp, type);
下面是一个演示: .NET小提琴
问:二传手
方法没有一个 REF
参数。它如何更新原有的结构?
Q: The setter
method doesn't have a ref
parameter. How can it update the original struct?
答:虽然这是真的,如果没有 REF
关键字,值类型通常按值传递的,因此复制,这里的类型在目标
参数对象
。如果参数是一个盒装的结构,那么引用应用于箱传递(按价值计算)的方法。
A: Although it's true that, without the ref
keyword, value types are normally passed by value and thus copied, here the type of the target
parameter is object
. If the argument is a boxed struct, then a reference to the box is passed (by value) to the method.
现在,它采用纯C#变异装箱的结构,因为C#装箱转换总是产生装箱值的副本,是不可能的。但它的是的可能使用IL或反思:
Now, it's not possible using pure C# to mutate a boxed struct because a C# unboxing conversion always produces a copy of the boxed value. But it is possible using IL or Reflection:
public struct S { public int I; }
public void M(object o, int i)
{
// ((S)o).I = i; // DOESN'T COMPILE
typeof(S).GetField("I").SetValue(o, i);
}
public void N()
{
S s = new S();
object o = s; // create a boxed copy of s
M(o, 1); // mutate o (but not s)
Console.WriteLine(((S)o).I); // "1"
Console.WriteLine(s.I); // "0"
M(s, 2); // mutate a TEMPORARY boxed copy of s (BEWARE!)
Console.WriteLine(s.I); // "0"
}
问:为什么不二传手工作,如果在LINQ EX pression使用防爆pression.Convert
答:防爆pression.Convert编译的<一个href="https: msdn.microsoft.com en-us library system.reflection.emit.op$c$cs.unbox_any(v="vs.110).aspx"相对=nofollow">
unbox.any
IL指令,它返回的
复制的被引用的结构的
目标
。二传手然后更新这个副本(其随后被丢弃)。
一个href="https:>
A: Expression.Convert compiles to the unbox.any
IL instruction, which returns a copy of the struct referenced by target
. The setter then updates this copy (which is subsequently discarded).
问:为什么前pression.Unbox解决问题
答:防爆pression.Unbox(为Ex pression.Assign的目标使用时)编译到的 拆箱
IL指令,它返回的指针的由目标引用的结构
。设定器然后使用指针直接修改该结构
A: Expression.Unbox (when used as the target of Expression.Assign) compiles to the unbox
IL instruction, which returns a pointer to the struct referenced by target
. The setter then uses the pointer to modify that struct directly.
这篇关于使用FieldInfo.SetValue VS LINQ EX pressions在一个结构设置字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持蚂蚁编程!
2、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除下载链接并致以最深的歉意。
3、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责。
4、一经注册为本站会员,一律视为同意网站规定,本站管理员及版主有权禁止违规用户。
5、蚂蚁编程管理员有权不事先通知发贴者而删除本文。
蚂蚁编程学院 » 使用FieldInfo.SetValue VS LINQ EX pressions在一个结构设置字段