如何使用变异IL盒装结构

编程入门 行业动态 更新时间:2024-10-22 08:10:36
本文介绍了如何使用变异IL盒装结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

想象一下,我们有一个可变结构(是的,不启动):

公共结构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 _ * 似乎工作。 其实,这主要是拆箱(见历史版本与 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德尔=(动作<对象,INT>)dynMtd.CreateDelegate(typeof运算(动作<对象,INT>));     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 structs ?

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 }

更多推荐

如何使用变异IL盒装结构

本文发布于:2023-11-06 06:48:58,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1562980.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:如何使用   结构   IL

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!