跳过不带DynamicMethod的动态生成方法的可见性检查



这个问题和另外两个问题很相似见:第一,第二。然而,这些都已经过时了,我希望在。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, typeof(int[]), new[] { typeof(List<int>) });
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);
type.CreateType();
var arrayGetter = (Func<List<int>, int[]>)type.GetMethod("GetUnderlyingArray").CreateDelegate(typeof(Func<List<int>, int[]>));

系统。FieldAccessException:尝试使用方法'GetUnderlyingArrayClass.GetUnderlyingArray(System.Collections.Generic.List'1)'访问字段'System.Collections.Generic.List'1。_items"失败了。+ GetUnderlyingArrayClass.GetUnderlyingArray(列表)

这是一个. net fiddle链接,上面显示了代码。

现在,我提到的一个问题指向以下属性ReflectionPermissionAttribute。然而,正如文档Code Access Security is not supported or honored by the runtime.所述。从我的理解来看,这基本上意味着。net Core/。Net 5不支持CAS

这就是我感到困惑的地方。将skipVisibility参数设置为truefalse实际上并不重要。我认为这是因为我是在。net 5环境中运行代码的。但是,如果。net 5不支持CAS,为什么我仍然能够读出私有字段?

目标显然是使用DefineType/DefineMethodAPI从动态生成的方法中访问私有字段/方法。

我仍然无法解释为什么将skipVisibility参数设置为true/false并不重要,但是PathogenDavid在GitHub上从csharp运行时讨论存储库向我展示了一个比预期更容易的解决方案。

// Add IgnoresAccessChecksTo attribute
var ignoresAccessChecksTo = new CustomAttributeBuilder
(
typeof(IgnoresAccessChecksToAttribute).GetConstructor(new Type[] { typeof(string) }),
new object[] { typeof(List<>).Assembly.GetName().Name }
);
assemblyBuilder.SetCustomAttribute(ignoresAccessChecksTo);

查看这个。net Fiddle的工作示例。

正如他所说,IgnoresAccessChecksTo属性是用来绕过检查的。

运行时理解该属性,但它没有在BCL中定义,因此您必须自己定义它。

相关内容

  • 没有找到相关文章

最新更新