最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(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ó)家法律
北辰区| 彭州市| 杨浦区| 化隆| 门源| 浪卡子县| 定边县| 开阳县| 齐河县| 英德市| 博乐市| 常德市| 丹棱县| 福贡县| 台南市| 收藏| 霞浦县| 英德市| 文成县| 邹城市| 贵阳市| 即墨市| 荥阳市| 屏南县| 彭泽县| 龙海市| 武平县| 湖南省| 远安县| 安丘市| 石台县| 三明市| 德令哈市| 玛纳斯县| 林周县| 宁安市| 喜德县| 武强县| 五华县| 延津县| 繁昌县|