无码av一区二区三区无码,在线观看老湿视频福利,日韩经典三级片,成 人色 网 站 欧美大片在线观看

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

調(diào)用私有方法的N種方法

2023-07-13 16:39 作者:吳小敏63  | 我要投稿

非公開(kāi)的類型或者方法被“隱藏”在程序集內(nèi)部,本就不希望從外部訪問(wèn),但是有時(shí)候調(diào)用一個(gè)內(nèi)部或者私有方法可能是唯一的“救命稻草”,這篇文章列出了幾種具體的實(shí)現(xiàn)方式。以如下這個(gè)Foobar類型為例,它具有一個(gè)內(nèi)部屬性InternalValue,我們來(lái)看看有多少種方式可以從外部獲取一個(gè)Foobar對(duì)象的InternalValue屬性值。

public class Foobar { ? ?internal int InternalValue => 123; }

一、反射

對(duì)于大部分人來(lái)說(shuō),最先想到的自然是“反射”,具體實(shí)現(xiàn)體現(xiàn)再如下所示的InternalValueAccessor類型的GetInternalValue方法中。但是我們都知道反射是一種并不高效的方式,對(duì)于需要頻繁調(diào)用,我們一般不推薦使用。

var foobar = new Foobar(); Debug.Assert(InternalValueAccessor.GetInternalValue(foobar) == 123);public static class InternalValueAccessor { ? ?public static int GetInternalValue(Foobar foobar) ? ?{ ? ? ? ?var propertyInfo = typeof(Foobar).GetProperty("InternalValue", BindingFlags.Instance | BindingFlags.NonPublic)!; ? ? ? ?return (int)propertyInfo.GetValue(foobar)!; ? ?} }

二、MethodInfo.CreateDelegate方法

要獲得Foobar對(duì)象的InternalValue屬性值(int類型),實(shí)際上需要一個(gè)Func<Foobar,int>類型的委托。由于返回值實(shí)際上是通過(guò)InternalValue屬性的Get方法獲得的,而表示方法的MethodInfo類型具有一個(gè)CreateDelegate<TDelegate>方法,我們可以采用如下的方式利用InternalValue屬性的Get方法來(lái)創(chuàng)建所需的Func<Foobar,int>委托。

var foobar = new Foobar(); Debug.Assert(InternalValueAccessor.GetInternalValue(foobar) == 123);public static class InternalValueAccessor { ? ?private static Func<Foobar, int>? _getInternalValue; ? ?public static int GetInternalValue(Foobar foobar)=> (_getInternalValue??= CreateDelegate())(foobar); ? ?private static Func<Foobar, int> CreateDelegate() ? ?{ ? ? ? ?var methodInfo = typeof(Foobar).GetProperty("InternalValue", BindingFlags.Instance | BindingFlags.NonPublic)!.GetMethod!; ? ? ? ?return methodInfo.CreateDelegate<Func<Foobar, int>>(); ? ?} }

三、表達(dá)式(樹(shù))

一般來(lái)說(shuō),所有的反射解決方案都可以轉(zhuǎn)換成基于表達(dá)式(樹(shù))的解決方案。我們需要的Func<Foobar,int>委托可以按照如下的方式,利用構(gòu)建的表達(dá)式編譯生成。

public static class InternalValueAccessor { ? ?private static Func<Foobar, int>? _getInternalValue; ? ?public static int GetInternalValue(Foobar foobar)=> (_getInternalValue??= CreateDelegate())(foobar); ? ?private static Func<Foobar, int> CreateDelegate() ? ?{ ? ? ? ?var methodInfo = typeof(Foobar).GetProperty("InternalValue", BindingFlags.Instance | BindingFlags.NonPublic)!.GetMethod!; ? ? ? ?var foobar = Expression.Parameter(typeof(Foobar), "foobar"); ? ? ? ?var getValue = Expression.Call(foobar, methodInfo); ? ? ? ?return Expression.Lambda<Func<Foobar, int>>(getValue, foobar).Compile(); ? ?} }

四、動(dòng)態(tài)方法(call)

實(shí)際上表達(dá)式(樹(shù))是對(duì)IL代碼的抽象表達(dá),所以既然這樣的問(wèn)題自然可以利用IL Emit來(lái)解決。在如下的代碼中,我們創(chuàng)建了一個(gè)DynamicMethod類型表示的動(dòng)態(tài)方法,以IL Emit的方式利用IL指令Call完成了針對(duì)InternalValue屬性的Get方法的調(diào)用。我們所需的Func<Foobar,int>委托最終由這個(gè)DynamicMethod對(duì)象創(chuàng)建而成。

public static class InternalValueAccessor { ? ?private static Func<Foobar, int>? _getInternalValue; ? ?public static int GetInternalValue(Foobar foobar) => (_getInternalValue ??= CreateDelegate())(foobar); ? ?private static Func<Foobar, int> CreateDelegate() ? ?{ ? ? ? ?var methodInfo = typeof(Foobar).GetProperty("InternalValue", BindingFlags.Instance | BindingFlags.NonPublic)!.GetMethod!; ? ? ? ?var method = new DynamicMethod("GetInternalValue", typeof(int), new Type[] { typeof(Foobar) }); ? ? ? ?var il = method.GetILGenerator(); ? ? ? ?il.Emit(OpCodes.Ldarg_0); ? ? ? ?il.EmitCall(OpCodes.Call, methodInfo, null); ? ? ? ?il.Emit(OpCodes.Ret); ? ? ? ?return method.CreateDelegate<Func<Foobar, int>>(); ? ?} }

五、動(dòng)態(tài)方法(calli)

了解IL的朋友應(yīng)該知道,方法調(diào)用涉及的IL治理有三個(gè)(Call、Callvir和Calli)。如果使用Calli指令,在完成針對(duì)參數(shù)的壓棧之后,我們還需要執(zhí)行Ldftn指令將方法指針壓入棧中,最終執(zhí)行Calli指令完成方法的執(zhí)行。

public static class InternalValueAccessor { ? ?private static Func<Foobar, int>? _getInternalValue; ? ?public static int GetInternalValue(Foobar foobar) => (_getInternalValue ??= CreateDelegate())(foobar); ? ?private static Func<Foobar, int> CreateDelegate() ? ?{ ? ? ? ?var methodInfo = typeof(Foobar).GetProperty("InternalValue", BindingFlags.Instance | BindingFlags.NonPublic)!.GetMethod!; ? ? ? ?var method = new DynamicMethod("GetInternalValue", typeof(int), new Type[] { typeof(Foobar) }); ? ? ? ?var il = method.GetILGenerator(); ? ? ? ?il.Emit(OpCodes.Ldarg_0); ? ? ? ?il.Emit(OpCodes.Ldftn, methodInfo); ? ? ? ?il.EmitCalli(OpCodes.Calli, CallingConventions.Standard, typeof(int), new Type[] { typeof(Foobar) }, null); ? ? ? ?il.Emit(OpCodes.Ret); ? ? ? ?return method.CreateDelegate<Func<Foobar, int>>(); ? ?} }

分類:?[02] 編程技巧


調(diào)用私有方法的N種方法的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
淮安市| 赤峰市| 荣昌县| 莎车县| 丰台区| 大连市| 云林县| 从江县| 南安市| 方山县| 安阳市| 海林市| 渭南市| 炎陵县| 新和县| 丹阳市| 汶上县| 西乌珠穆沁旗| 五寨县| 瓮安县| 上虞市| 泰顺县| 文昌市| 二连浩特市| 罗江县| 灵宝市| 永善县| 南开区| 泗洪县| 友谊县| 当阳市| 揭阳市| 新田县| 百色市| 阿克陶县| 高要市| 黄陵县| 华亭县| 镇宁| 甘谷县| 松桃|