问题描述
这个问题与另外两个问题非常相似,参见:first,second。然而,至少可以说这些已经过时了,我希望 .Net 5 的情况有所改变。
现在首先让我澄清这个问题。用一个简单的例子来尝试获取 List<int>.
var method = new DynamicMethod("GetUnderlyingArray",typeof(int[]),new[] { typeof(List<int>) },typeof(List<int>),true);
var ilGenerator = method.GetILGenerator();
ilGenerator.Emit(OpCodes.Ldarg_0);
ilGenerator.Emit(OpCodes.Ldfld,typeof(List<int>).GetField("_items",BindingFlags.NonPublic | BindingFlags.Instance));
ilGenerator.Emit(OpCodes.Ret);
var arrayGetter = (Func<List<int>,int[]>)method.CreateDelegate(typeof(Func<List<int>,int[]>));
这工作得很好,因为我可以告诉 DynamicMethod
跳过可见性检查(即使它也工作,当 DynamicMethod
构造函数 true
的最后一个参数是已删除)。
但是,当我尝试对下面的示例执行相同操作时,它会抛出 FieldAccessException
。
var assemblyName = new AssemblyName("Example");
var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName,AssemblyBuilderAccess.Run);
var dynamicModule = assemblyBuilder.DefineDynamicModule(assemblyName.Name + ".dll");
var type = dynamicModule.DefineType("GetUnderlyingArrayClass");
var method = type.DefineMethod("GetUnderlyingArray",MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Static,new[] { typeof(List<int>) });
var ilGenerator = method.GetILGenerator();
ilGenerator.Emit(OpCodes.Ldarg_0);
ilGenerator.Emit(OpCodes.Ldfld,BindingFlags.NonPublic | BindingFlags.Instance));
ilGenerator.Emit(OpCodes.Ret);
type.CreateType();
var arrayGetter = (Func<List<int>,int[]>)type.GetMethod("GetUnderlyingArray").CreateDelegate(typeof(Func<List<int>,int[]>));
System.FieldAccessException: 尝试通过方法 'GetUnderlyingArrayClass.GetUnderlyingArray(System.Collections.Generic.List'1)' 访问字段 'System.Collections.Generic.List'1
Here is a .Net fiddle link with the code shown above.
现在,我提到的问题之一指向以下属性 ReflectionPermissionAttribute
。但是,正如它在文档 Code Access Security is not supported or honored by the runtime.
中所述。据我了解,这基本上意味着 .Net Core/.Net 5 do not support CAS.
这就是我感到困惑的地方。将 skipVisibility
参数设置为 true
或 false
实际上并不重要。我认为这是因为我在 .Net 5 环境中运行代码。但是,如果 .Net 5 不支持 CAS,为什么我仍然可以读出私有字段?
目标显然是使用 DefineType
/DefineMethod
API 从动态生成的方法访问私有字段/方法。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)