gpt4 book ai didi

c# - 为什么用动态方法设置只读字段会导致此类错误?

转载 作者:太空狗 更新时间:2023-10-29 19:45:10 24 4
gpt4 key购买 nike

可以使用 strfld 存储在类的只读字段中如果它的所有者设置为该类并且关闭了 JIT 检查,则动态方法中的操作代码。一个例子是 here .然而,这种方法无法处理来自 F# 的类,即 FSharpOption。 .请分析下面的例子:

using Microsoft.FSharp.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;

#if true
using MyType = Microsoft.FSharp.Core.FSharpOption<string>;
#else
using MyType = System.Tuple<string>;
#endif

namespace ConsoleApplication27
{
class Program
{
static void Main(string[] args)
{
var something = new MyType("test");

var dynMethod = new DynamicMethod("ChangeField", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, typeof(void), new [] { typeof(MyType) }, typeof(MyType), true);
var generator = dynMethod.GetILGenerator();
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldstr, "success");
generator.Emit(OpCodes.Stfld, typeof(MyType).GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public)[0]);
generator.Emit(OpCodes.Ret);

var method = (Action<MyType>) dynMethod.CreateDelegate(typeof(Action<MyType>));
method(something);
Console.WriteLine(typeof(MyType).GetProperties()[0].GetGetMethod().Invoke(something, new object[0]));
}
}
}

首先,您必须引用 FSharp.Core 库才能运行它。然后,通过更改 #if true#if false您可以在编写只读字段 fo Tuple 之间切换和 FSharpOption .对于前者,即使两者具有相似的结构,它也能完美运行,这是一个可通过属性访问的单个只读字段。对于后者,它会导致验证失败。为什么会这样?

最佳答案

非常非常晚的回复。这很奇怪。通过将 MyType 替换为字段类型的模块。一切都开始工作

var dynMethod = new DynamicMethod("ChangeField", MethodAttributes.Public | MethodAttributes.Static,
CallingConventions.Standard, typeof(void), new[] {typeof(MyType)}, typeof(MyType), true);

变成:

var dynMethod = new DynamicMethod("ChangeField", MethodAttributes.Public | MethodAttributes.Static,
CallingConventions.Standard, typeof(void), new[] {typeof(MyType)}, typeof(string).Module, true);

即:

 typeof(MyType), true);

成为

 typeof(string).Module, true);

要设置的字段类型是string 所以我们采用它的模块。我很想听听关于原因的更好解释。

情节变厚了

事实证明,typeof(string).module 使其适用于任何类型。即使我这样定义自己的类型:

using System;
using System.Reflection;
using System.Reflection.Emit;
#if true
using MyType = Microsoft.FSharp.Core.FSharpOption<string>;
#else
using MyType = System.Tuple<ConsoleApplication27.Poco>;
#endif

namespace ConsoleApplication27
{
public class Poco
{

}
class Program
{
static void Main(string[] args)
{
var something = new MyType(null);

var dynMethod = new DynamicMethod("ChangeField", MethodAttributes.Public | MethodAttributes.Static,
CallingConventions.Standard, typeof(void), new[] {typeof(MyType)}, typeof(string).Module, true);
var generator = dynMethod.GetILGenerator();
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldnull);
generator.Emit(OpCodes.Stfld,
typeof(MyType).GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public)[0]);
generator.Emit(OpCodes.Ret);

var method = (Action<MyType>) dynMethod.CreateDelegate(typeof(Action<MyType>));
method(something);
Console.WriteLine(typeof(MyType).GetProperties()[0].GetGetMethod().Invoke(something, new object[0]));
}
}
}

现在没有任何意义。 FSharpOption 类型存在于 F# 模块中。Poco 类存在于我的程序模块中。当传递的模块是 corelib 模块时,它仍然可以正常工作。但是,如果我通过了两个(以上)中的任何一个,那将是有意义的..

关于c# - 为什么用动态方法设置只读字段会导致此类错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31990025/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com