想象一下,我们有一个可变结构
(是的,不启动):
公共结构MutableStruct
{
公众诠释富{获得;组; }
公共重写字符串的ToString()
{
返回Foo.ToString();
}
}
使用反射,我们可以利用这个被包装实例结构
和其变异箱子里面:
//这基本上就是我们要效仿
obj对象=新MutableStruct {美孚= 123};
。obj.GetType()的getProperty(富)的SetValue(OBJ,456)。
的System.Console.WriteLine(OBJ); //456
我会的喜欢的要做的就是写一些白细胞介素,可以做与此相同 - 但速度更快。我是一个元编程迷; P
这是微不足道的拆箱,任何的价值和使用常规白细胞介素变异的价值 - 但你不能只是叫事后箱,因为这将创建一个不同的框。我的猜测的是什么,我们需要做的,是复制它在现有的框。我已经调查 ldobj
/ stobj
,但这些似乎并没有做的工作(除非我失去了一些东西)。
所以:做一个机制来做到这一点存在吗?或者,我必须限制自己的反射进行就地更新盒装结构
S'
或者换句话说:什么? ...邪在这儿... ...
VAR方法=新的DynamicMethod的(神雕侠侣,空,
新的[] {typeof运算(对象)的typeof(对象)});
变种IL = method.GetILGenerator();
// ...邪在这儿... ...
il.Emit(欧普codes.Ret);
动作<对象,对象>行动=(动作<对象,对象>)
method.CreateDelegate(typeof运算(动作<对象,对象>));
行动(OBJ,789);
的System.Console.WriteLine(OBJ); //789
解决方案
嗯,这很有意思。
使用 Ldflda
和 Stind _ *
似乎工作。
其实,这主要是拆箱(见< A HREF =http://stackoverflow.com/revisions/18938444/2>历史版本与 Ldflda作品
和 Stind _ *
)。
下面是我砍死在一起 LinqPad 来证明这一点了。
公共结构MutableStruct
{
公众诠释富{获得;组; }
公共重写字符串的ToString()
{
返回Foo.ToString();
}
}
无效的主要()
{
无功富= typeof运算(MutableStruct).GetProperty(富);
VAR setFoo = foo.SetMethod;
VAR dynMtd =新的DynamicMethod的(恶的typeof(无效),新的[] {typeof运算(对象)的typeof(INT)});
变种IL = dynMtd.GetILGenerator();
il.Emit(欧普codes.Ldarg_0); // 目的
il.Emit(欧普codes.Unbox的typeof(MutableStruct)); // MutableStruct和放大器;
il.Emit(欧普codes.Ldarg_1); // MutableStruct和放大器; INT
il.Emit(欧普codes.Call,setFoo); // --empty--
il.Emit(欧普codes.Ret); // --empty--
VAR德尔=(动作&LT;对象,INT&GT;)dynMtd.CreateDelegate(typeof运算(动作&LT;对象,INT&GT;));
VAR MUT =新MutableStruct {美孚= 123};
VAR盒装=(对象)MUT;
德尔(盒装,456);
VAR拆箱=(MutableStruct)盒装;
// unboxed.Foo = 456,mut.Foo = 123
}
Imagine we have a mutable struct
(yes, don't start):
public struct MutableStruct
{
public int Foo { get; set; }
public override string ToString()
{
return Foo.ToString();
}
}
Using reflection, we can take a boxed instance of this struct
and mutate it inside the box:
// this is basically what we want to emulate
object obj = new MutableStruct { Foo = 123 };
obj.GetType().GetProperty("Foo").SetValue(obj, 456);
System.Console.WriteLine(obj); // "456"
What I would like to do is to write some IL that can do the same as this - but faster. I'm a meta-programming junkie ;p
It is trivial to unbox-any the value and mutate the value using regular IL - but you can't just call box it afterwards because that will create a different box. I'm guessing that what we would need to do here is copy it over the existing box. I have investigated ldobj
/ stobj
, but those don't seem to do the job (unless I'm missing something).
So: does a mechanism to do this exist? Or must I limit myself to reflection to perform in-place updates of boxed struct
s ?
Or in other words: what ... evil goes here...
?
var method = new DynamicMethod("evil", null,
new[] { typeof(object), typeof(object) });
var il = method.GetILGenerator();
// ... evil goes here...
il.Emit(OpCodes.Ret);
Action<object, object> action = (Action<object, object>)
method.CreateDelegate(typeof(Action<object, object>));
action(obj, 789);
System.Console.WriteLine(obj); // "789"
解决方案
Well, that was fun.
Using Ldflda
and Stind_*
seems to work.
Actually, it's mostly Unbox (see history for version that works with Ldflda
and Stind_*
).
Here's what I hacked together in LinqPad to prove it out.
public struct MutableStruct
{
public int Foo { get; set; }
public override string ToString()
{
return Foo.ToString();
}
}
void Main()
{
var foo = typeof(MutableStruct).GetProperty("Foo");
var setFoo = foo.SetMethod;
var dynMtd = new DynamicMethod("Evil", typeof(void), new [] { typeof(object), typeof(int) });
var il = dynMtd.GetILGenerator();
il.Emit(OpCodes.Ldarg_0); // object
il.Emit(OpCodes.Unbox, typeof(MutableStruct)); // MutableStruct&
il.Emit(OpCodes.Ldarg_1); // MutableStruct& int
il.Emit(OpCodes.Call, setFoo); // --empty--
il.Emit(OpCodes.Ret); // --empty--
var del = (Action<object, int>)dynMtd.CreateDelegate(typeof(Action<object, int>));
var mut = new MutableStruct { Foo = 123 };
var boxed= (object)mut;
del(boxed, 456);
var unboxed = (MutableStruct)boxed;
// unboxed.Foo = 456, mut.Foo = 123
}
相关推荐
最新文章