服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - 探秘C#中的秘密通道:五种引人注目的方法调用内部或私有方法

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

2024-03-07 13:53架构师老卢 C#

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

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

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);
    }
}

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

原文地址:https://www.toutiao.com/article/7303704914658820646/

延伸 · 阅读

精彩推荐
  • C#C# 添加对System.Configuration.dll文件的引用操作

    C# 添加对System.Configuration.dll文件的引用操作

    这篇文章主要介绍了C# 添加对System.Configuration.dll文件的引用操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    锋璠8022022-10-28
  • C#C#递归算法之分而治之策略

    C#递归算法之分而治之策略

    分而治之的策略主要是将大量复杂的问题分成多个子问题,解决各个子问题,从而解决原问题,下面就让我们看看具体如何实现。...

    张玉彬11862021-11-25
  • C#详解C#编程中构造函数的使用

    详解C#编程中构造函数的使用

    这篇文章主要介绍了详解C#编程中构造函数的使用,是C#入门学习中的基础知识,需要的朋友可以参考下...

    C#教程网10992021-11-09
  • C#Unity幸运转盘实战项目

    Unity幸运转盘实战项目

    这篇文章主要为大家详细介绍了Unity幸运转盘实战项目,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    CC_childe6492022-07-20
  • C#详解C#实现MD5加密的示例代码

    详解C#实现MD5加密的示例代码

    本篇文章主要介绍了C#实现MD5加密的示例代码,详细的介绍了几种方法,具有一定的参考价值,有兴趣的可以了解一下。...

    shenghui1884632021-12-16
  • C#c# 使用Task实现非阻塞式的I/O操作

    c# 使用Task实现非阻塞式的I/O操作

    这篇文章主要介绍了c# 使用Task实现非阻塞式的I/O操作,帮助大家更好的理解和学习c# 编程语言,感兴趣的朋友可以了解下...

    一只独行的猿7122022-10-14
  • C#Unity实现领取奖励特效

    Unity实现领取奖励特效

    这篇文章主要为大家详细介绍了Unity实现领取奖励特效,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    LLLLL__4222022-10-12
  • C#c#删除指定文件夹中今天之前的文件

    c#删除指定文件夹中今天之前的文件

    本文主要介绍了c#删除指定文件夹中今天之前文件的方法,具有很好的参考价值,下面跟着小编一起来看下吧...

    冷战10702021-12-27