如何调用N种内部私有方法的操作为?

摘要:非公开的类型或者方法被“隐藏”在程序集内部,本就不希望从外部访问,但是有时候调用一个内部或者私有方法可能是唯一的“救命稻草”,这篇文章列出了几种具体的实现方式。以如下这个Foobar类型为例,它具有一个内部属性InternalValue,我
非公开的类型或者方法被“隐藏”在程序集内部,本就不希望从外部访问,但是有时候调用一个内部或者私有方法可能是唯一的“救命稻草”,这篇文章列出了几种具体的实现方式。以如下这个Foobar类型为例,它具有一个内部属性InternalValue,我们来看看有多少种方式可以从外部获取一个Foobar对象的InternalValue属性值。 public class Foobar { internal int InternalValue => 123; } 一、反射对于大部分人来说,最先想到的自然是“反射”,具体实现体现再如下所示的InternalValueAccessor类型的GetInternalValue方法中。但是我们都知道反射是一种并不高效的方式,对于需要频繁调用,我们一般不推荐使用。 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对象的InternalValue属性值(int类型),实际上需要一个Func<Foobar,int>类型的委托。由于返回值实际上是通过InternalValue属性的Get方法获得的,而表示方法的MethodInfo类型具有一个CreateDelegate<TDelegate>方法,我们可以采用如下的方式利用InternalValue属性的Get方法来创建所需的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>>(); } } 三、表达式(树)一般来说,所有的反射解决方案都可以转换成基于表达式(树)的解决方案。我们需要的Func<Foobar,int>委托可以按照如下的方式,利用构建的表达式编译生成。
阅读全文