五月天青色头像情侣网名,国产亚洲av片在线观看18女人,黑人巨茎大战俄罗斯美女,扒下她的小内裤打屁股

歡迎光臨散文網(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ó)家法律
乐至县| 运城市| 碌曲县| 慈溪市| 东宁县| 原阳县| 祁连县| 瓦房店市| 化德县| 观塘区| 澄迈县| 璧山县| 汕头市| 海城市| 北辰区| 江津市| 博乐市| 菏泽市| 蒲城县| 卓资县| 昌乐县| 茂名市| 玉田县| 安达市| 稷山县| 柘荣县| 偏关县| 垫江县| 宜州市| 芦溪县| 安徽省| 芷江| 徐水县| 申扎县| 当阳市| 文成县| 新密市| 新民市| 鄂温| 绥芬河市| 盈江县|