在 C# 中,可以使用不同的方法调用内部或私有方法。下面分别介绍通过反射、MethodInfo.CreateDelegate、表达式(树)、动态方法(call)、动态方法(calli)这五种方法。

1. 通过反射方法

使用反射可以访问和调用内部或私有方法。

using System;
using System.Reflection; public class MyClass
{
private void MyPrivateMethod()
{
Console.WriteLine("调用了私有方法");
}
} class Program
{
static void Main()
{
MyClass myObject = new MyClass(); // 通过反射获取私有方法
MethodInfo methodInfo = typeof(MyClass).GetMethod("MyPrivateMethod", BindingFlags.NonPublic | BindingFlags.Instance); // 调用私有方法
methodInfo.Invoke(myObject, null);
}
}

2. 使用 MethodInfo.CreateDelegate 方法

通过 MethodInfo.CreateDelegate 方法可以创建委托,然后调用私有方法。

using System;
using System.Reflection; public class MyClass
{
private void MyPrivateMethod()
{
Console.WriteLine("调用了私有方法");
}
} class Program
{
static void Main()
{
MyClass myObject = new MyClass(); // 通过反射获取私有方法
MethodInfo methodInfo = typeof(MyClass).GetMethod("MyPrivateMethod", BindingFlags.NonPublic | BindingFlags.Instance); // 创建委托
Action action = (Action)Delegate.CreateDelegate(typeof(Action), myObject, methodInfo); // 调用私有方法
action();
}
}

3. 使用表达式(树)方法

通过表达式(树)可以创建动态方法,然后调用私有方法。

using System;
using System.Linq.Expressions; public class MyClass
{
private void MyPrivateMethod()
{
Console.WriteLine("调用了私有方法");
}
} class Program
{
static void Main()
{
MyClass myObject = new MyClass(); // 使用表达式创建动态方法
Action action = CreateDelegate<Action>(myObject, "MyPrivateMethod"); // 调用私有方法
action();
} // 使用表达式创建动态方法的通用方法
static TDelegate CreateDelegate<TDelegate>(object target, string methodName)
{
var methodInfo = target.GetType().GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);
var parameter = Expression.Parameter(typeof(object), "instance");
var call = Expression.Call(Expression.Convert(parameter, target.GetType()), methodInfo);
var lambda = Expression.Lambda<TDelegate>(call, parameter);
return lambda.Compile();
}
}

4. 使用动态方法(call)方法

使用动态方法可以调用私有方法。

using System;
using System.Reflection;
using System.Reflection.Emit; public class MyClass
{
private void MyPrivateMethod()
{
Console.WriteLine("调用了私有方法");
}
} class Program
{
static void Main()
{
MyClass myObject = new MyClass(); // 使用动态方法调用私有方法
CallPrivateMethod(myObject, "MyPrivateMethod");
} // 使用动态方法调用私有方法的通用方法
static void CallPrivateMethod(object target, string methodName)
{
var methodInfo = target.GetType().GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance); // 使用动态方法
var dynamicMethod = new DynamicMethod("CallMethod", null, new[] { typeof(object) }, target.GetType());
var ilGenerator = dynamicMethod.GetILGenerator();
ilGenerator.Emit(OpCodes.Ldarg_0); // 加载第一个参数,即目标实例
ilGenerator.EmitCall(OpCodes.Call, methodInfo, null); // 调用私有方法
ilGenerator.Emit(OpCodes.Ret); // 返回
var action = (Action<object>)dynamicMethod.CreateDelegate(typeof(Action<object>)); // 调用私有方法
action(target);
}
}

5. 使用动态方法(calli)方法

使用动态方法(calli)可以调用私有方法。

using System;
using System.Reflection.Emit; public class MyClass
{
private void MyPrivateMethod()
{
Console.WriteLine("调用了私有方法");
}
} class Program
{
static void Main()
{
MyClass myObject = new MyClass(); // 使用动态方法(calli)调用私有方法
CallPrivateMethod(myObject, "MyPrivateMethod");
} // 使用动态方法(calli)调用私有方法的通用方法
static void CallPrivateMethod(object target, string methodName)
{
var methodInfo = target.GetType().GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance); // 使用动态方法(calli)
var dynamicMethod = new DynamicMethod("CallMethod", typeof(void), new[] { typeof(object) }, target.GetType());
var ilGenerator = dynamicMethod.GetILGenerator();
ilGenerator.Emit(OpCodes.Ldarg_0); // 加载第一个参数,即目标实例
ilGenerator.EmitCalli(OpCodes.Call, methodInfo.CallingConvention, methodInfo.ReturnType, methodInfo.GetParameters().Select(p => p.ParameterType).ToArray(), null); // 调用私有方法
ilGenerator.Emit(OpCodes.Ret); // 返回
var action = (Action<object>)dynamicMethod.CreateDelegate(typeof(Action<object>)); // 调用私有方法
action(target);
}
}

以上五种方法都可以用于调用内部或私有方法,具体使用哪种方法取决于具体的场景和需求。

探秘C#中的秘密通道:五种引人注目的方法调用内部或私有方法的更多相关文章

  1. js中声明Number的五种方式

    转载自:http://www.jb51.net/article/34191.htm <!DOCTYPE html> <html> <head> <meta c ...

  2. 五种I/O 模式,select、epoll方法的理解,BIO、NIO、AIO理解 相关文章

    一.io方式 Linux网络编程 五种I/O 模式及select.epoll方法的理解 web优化必须了解的原理之I/o的五种模型和web的三种工作模式 五种I/O 模式——阻塞(默认IO模式),非阻 ...

  3. 面试中常问的五种IO模型和BIO,NIO,AIO

    一,五种IO模型: 一个IO操作可以分为两个步骤:发起IO请求和实际的IO操作例如:1.操作系统的一次写操作分为两步:第一步,将数据从用户空间拷贝到系统空间:第二步,从系统空间往网卡写.2.一次读操作 ...

  4. iOS开发中数组常用的五种遍历方式

    随着iOS的不断发展,apple也不断推出性能更高的数组遍历方式,下面将对熟悉的五种遍历方式进行列举. 首先定义一个数组,并获取数组长度 NSArray *array=@[",]; NSIn ...

  5. JavaScript中常见的十五种设计模式

    在程序设计中有很多实用的设计模式,而其中大部分语言的实现都是基于“类”. 在JavaScript中并没有类这种概念,JS中的函数属于一等对象,在JS中定义一个对象非常简单(var obj = {}), ...

  6. webpack中,require的五种用法

    a.js: module.exports = function(x){ console.log(x); } 一,commonjs同步: var b = require('./a');b('你好')// ...

  7. Redis学习二 C#中如何进行这五种数据类型的操作

    我在网上找了好久,就是没有找到Redis和C#结合的书,都是和别的编程语言在一起鬼混. 简单的用C#实现向Redis中插入那我中类型的数据 首先需要到NuGet 里面下载 Redis IDatabas ...

  8. Redis 中可以存储的五种基本类型

    具体介绍 数字还是字符? String(字符串) 二进制安全 可以包含任何数据,比如jpg图片或者序列化的对象,一个键最大能存储512M --- Hash(字典) 键值对集合,即编程语言中的Map类型 ...

  9. Java程序栈信息文件中的秘密(五)

    最近发现在使用jstack工具在导出Java应用的线程栈时有一个小小的窍门,比如Linux环境上有一个用户为appuser,假如以这个用户启动了一个Java进程B,如果想要导出进程B的线程栈,则必须切 ...

  10. NSNotification,NSNotificationCenter的使用、iOS中五种对象间传值的方式

    学习内容 NSNitification与NotificationCenter(通知与通知中心) 通知的使用 [[NSNotificationCenter defaultCenter]addObserv ...

随机推荐

  1. 详细讲解js实现电梯导航

    场景 对于某一个页面内容繁多, 如果我们滚动的时间较长,为了增加用户体验. 我们需要实现点击某一个按钮,然后滚动到对应的区域. 滚动的时候,右侧对应的分类实现高亮 其实,这个功能就2个步骤: 1.点击 ...

  2. 如何通过API接口获取淘宝的店铺所有商品详情

    在电子商务领域中,淘宝是亚洲最大的在线交易平台之一,拥有海量的商品资源和消费者.如果你是一名开发者,想要在自己的网站或者APP中嵌入淘宝商品资源,那么你就需要通过淘宝开放平台提供的API接口来获取这些 ...

  3. 如何使用API接口获取Lazada商品详情数据

    随着电商市场的不断发展壮大,越来越多的人开始选择在网上购买商品.其中,东南亚地区的Lazada电商平台备受欢迎.如果您是一名电商从业者,或者打算在Lazada上开店,那么获取商品详情信息将是一个非常重 ...

  4. Java读取某个文件夹下的所有文件(支持多级文件夹)

    源码如下: package com.vocy.water.batch; import java.io.FileNotFoundException; import java.io.IOException ...

  5. Note -「Maths」Euler 筛筛积性函数

    Part. 1 Preface 这个东西是我在做 JZPTAB 的时候 LYC 给我讲的. 然后发现这是个通法,就写一写. 本文除了例题所有代码均未经过编译,仅作为参考. Part. 2 Untitl ...

  6. SSM-Mybatis笔记

    目录 Mybatis-9.28 1.简介 1.1.什么是Mybatis 1.2.持久化 1.3.持久层 1.4 为什么需要Mybatis? 2.第一个Mybatis程序 2.1.搭建环境 2.2.创建 ...

  7. C++的动态分派在HotSpot VM中的重要应用

    众所周知,多态是面向对象编程语言的重要特性,它允许基类的指针或引用指向派生类的对象,而在具体访问时实现方法的动态绑定.C++ 和 Java 作为当前最为流行的两种面向对象编程语言,其内部对于多态的支持 ...

  8. JDK对于Java的作用

    JDK是Java Development Kit的缩写,是Java的开发工具包(SDK).JDK 是整个 Java 的核心,包括 Java 运行环境(Java Runtime Envirnment,简 ...

  9. tunm, 一种对标JSON的二进制数据协议

    Tunm simple binary proto 一种对标JSON的二进制数据协议 支持的数据类型 基本支持的类型 "u8", "i8", "u16& ...

  10. Android dumpsys介绍

    目录 一.需求 二.环境 三.相关概念 3.1 dumpsys 3.2 Binder 3.3 管道 四.dumpsys指令的使用 4.1 dumpsys使用 4.2 dumpsys指令语法 五.详细设 ...