AssemblyOne:
[assembly: AllowPartiallyTrustedCallers]public class TypeOne{ public TypeOne(TypeTwo typeTwoFIEld) { this.TypeTwoFIEld = typeTwoFIEld; } public TypeTwo TypeTwoFIEld { get; }}
AssemblyTwo:
[assembly: AllowPartiallyTrustedCallers]public class TypeTwo{ public TypeTwo(int i) { this.Int = i; } public int Int { get; }}
主要:
using System;using System.Reflection;using System.Reflection.Emit;using AssemblyOne;using AssemblyTwo;namespace Main{ class Program { public class MyType { public MyType(TypeOne typeOneFIEld) { this.TypeOneFIEld = typeOneFIEld; } public TypeOne TypeOneFIEld { get; } } static voID Main(string[] args) { var fIEldInfo = typeof(TypeOne) .GetTypeInfo() .GetFIEld( "<TypeTwoFIEld>k__backingFIEld",BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); var setter = (Action<TypeOne,TypeTwo>) GetReferenceSetter(fIEldInfo); var myType = new MyType(new TypeOne(new TypeTwo(1))); // Throws VerificationException setter(myType.TypeOneFIEld,new TypeTwo(2)); } public static Delegate GetReferenceSetter(FIEldInfo fIEld) { var delegateType = typeof(Action<,>) .MakeGenericType(fIEld.DeclaringType,fIEld.FIEldType); var method = new Dynamicmethod( fIEld.name + "Set",null,new[] {fIEld.DeclaringType,fIEld.FIEldType},fIEld.DeclaringType,skipVisibility: true); var emitter = method.GetILGenerator(); emitter.Emit(OpCodes.Ldarg_0); emitter.Emit(OpCodes.Ldarg_1); emitter.Emit(OpCodes.Stfld,fIEld); emitter.Emit(OpCodes.Ret); return method.CreateDelegate(delegateType); } }}
所以MyType有一个TypeOne,它有一个只读的TypeTwo.在这种情况下,Dynamicmethod在运行时抛出VerificationException.
是否有可能创建一个适用于您抛出的任何声明类型字段类型的委托?如果是这样,怎么样?
我意识到在构造之后永远不会设置只读字段,但是这样做的目的是用于反序列化&深拷贝.
解决方法 动态方法在修改其安全性方面非常有限.我怀疑使用AssemblyBuilder可能会绕过安全检查,但我没有尝试过.相反,可以实现此目的的是使用其他方法来访问TypedReference类型中的字段.
public static unsafe voID SetValue<T>(object inst,FIEldInfo fi,T val){ var mi = typeof(TypedReference).getmethod("InternalMakeTypedReference",BindingFlags.NonPublic | BindingFlags.Static); var sig = MethodSignature.FromMethodInfo(mi); var del = ReflectionTools.NewCustomDelegateType(sig.ReturnType,sig.ParameterTypes); var inv = mi.CreateDelegate(del); TypedReference tr; var ptr = Pointer.Box(&tr,typeof(voID*)); inv.DynamicInvoke(ptr,inst,new[]{fi.FIEldHandle.Value},fi.FIEldType); __refvalue(tr,T) = val;}
FromMethodInfo和NewCustomDelegateType来自SharpUtils,需要调用InternalMakeTypedReference,它能够获得对任何字段的引用.它的签名如下:
private unsafe static extern voID InternalMakeTypedReference(voID* result,object target,IntPtr[] flds,RuntimeType lastFIEldType);
您可以用自己的库替换库方法,只需要构建适当的委托类型(由于指针而无法使用Action).由于内部RuntimeType,您无法直接创建委托类型.令人惊讶的是,DynamicInvoke在委托上工作,并创建了类型引用.
但是,要使用这个伏都教,我不得不降低组件中的安全检查,所以我不确定它是否也适用于你的装配系统:
[assembly: System.Security.SecurityRules(System.Security.SecurityRuleSet.Level1,SkipVerificationInFullTrust=true)]
另请注意,此代码使用了大量未记录的功能,并且可能随时停止工作.使用风险自负.
总结以上是内存溢出为你收集整理的c# – 创建DynamicMethod以在任何类型上设置只读字段全部内容,希望文章能够帮你解决c# – 创建DynamicMethod以在任何类型上设置只读字段所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)