在 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. 【Qt6】列表模型——抽象基类

    列表模型(Item Model),老周没有翻译为"项目模型",因为 Project 和 Item 都可以翻译为"项目",容易出现歧义.干脆叫列表模型.这个模型也 ...

  2. MutationObserver监听dom元素结构及属性变化

    工作中埋码需求,当某些动态插入的元素出现时触发埋码事件,因此需要对插入元素的父节点进行监听,子节点发生变化时触发相应埋码逻辑. 方法一 监听页面结构及子元素变化: (function () { //事 ...

  3. web应用及微信小程序版本更新检测方案实践

    背景: 随着项目体量越来越大,用户群体越来越多,用户的声音也越来越明显:关于应用发版之后用户无感知,导致用户用的是仍然还是老版本功能,除非用户手动刷新,否则体验不到最新的功能:这样的体验非常不好,于是 ...

  4. Springboot 实现QQ登录(界面跳转)

    Springboot 实现QQ登录(界面跳转) 现在第三方登录已经变成主流app的登录方式了 今天记录一下如何给自己的网站实现第三方登录(这里以QQ登录为例) 准备工作 首先确保你准备好你自己网站的域 ...

  5. C#使用iKvm黑科技无缝接入JVM生态

    前言 时间过得飞快,一转眼国庆假期也要过去了,再不更新博客就太咸鱼了-- 最近在开发AIHub的时候想找个C#能用的命名实体识别库,但一直没找到,AI生态方面C#确实不太丰富,这块还是得Python, ...

  6. Go with Protobuf

    原文在这里. 本教程为 Go 程序员提供了使用Protocol buffer的基本介绍. 本教程使用proto3向 Go 程序员介绍如何使用 protobuf.通过创建一个简单的示例应用程序,它向你展 ...

  7. grafana 配置自定义dashboard

    本文为博主原创,转载请注明出处: 1.配置数据源 配置完成后,点击Save And Test,如果配置正确,页面则显示如下: 2.配置dashboard                    点击 A ...

  8. 源码搭建zabbix平台

    1.基于lnmp部署zabbix监控平台; zabbix优点: 1.支持自动发现服务器和网络设备: 2.分布式的监控体系和集中式的WEB管理: 3.支持主动监控和被动监控模式: 4.基于SNMP.IP ...

  9. AT通讯总结(56K猫调制解调器Modem)型号I-56EM

    1.关闭流控RTS与DTR AT&D0&K0\r\n 2.保存到非易失性存储 AT&W\r\n 3.向800001音频拨号 ATDT800001\r\n 4.接听 ATA\r\ ...

  10. xxl-job安装部署文档

    xxl-job安装部署文档 注意:替换yaml文件中的mysql地址 安装方式 kubectl apply -f xxl-job.yaml -n xxxx 安装配置文件 xxl-job.yaml ## ...