通过Invoke反射类的private方法

本文介绍了一种使用C#反射机制来调用类中的私有(private)方法的技术。通过设置BindingFlags标志,可以获取到私有方法的信息并利用Invoke方法执行。文章提供了完整的示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

通过Invoke反射类的private方法

前些时间需要写个方法来handle一个类的所有private方法,晚上查了一大片都没有找到,有些无聊的人竟然危言耸听地说不可能handle到private方法。最后还是自己写了一个出来,供有需要的人分享一下。

 





using System;

using System.Collections.Generic;

using System.Reflection;

using System.Reflection.Emit;

using System.Linq;



namespace BruceReflection

{

    class Program

    {

        static void Main(string[] args)

        {

            BruceTest.Show();

            BruceTest.TestPrivate();

            Console.Read();

        }

       

    }



    public class BruceTest

    {

        /// <summary>

        /// 测试反射private方法

        /// </summary>

        public static void TestPrivate()

        {

            Bruce b = new Bruce();

            Type t = b.GetType();

            MethodInfo [] ms;

            MethodInfo m;

            BindingFlags bf = BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic;

            ms = t.GetMethods(bf);

            m =(from p in  ms where p.Name =="PrivateMethod" select p).First () ;//如果你使用的VS版本不支持linq,则这里可以改成用循环来筛选

            //反射private方法

            m.Invoke(b, new object[] {"Bruce Lee" });

        }



        public static void Show()

        {

            Bruce b = new Bruce();

            Type t = b.GetType();

            MethodInfo [] ms;

            BindingFlags bf;



            //遍历所有实例化的方法

            foreach (BindingFlags f in Enum.GetValues(typeof(BindingFlags)))

            {

                bf = BindingFlags.InvokeMethod| BindingFlags.Instance  ;

                bf |= f;

                ms = t.GetMethods(bf);

                if (ms != null && ms.Length > 0)

                {

                    Console.WriteLine("BindingFlag is " + bf.ToString());

                    ShowMethodInfo(ms);

                }

            }



            //遍历所有静态方法

            foreach (BindingFlags f in Enum.GetValues(typeof(BindingFlags)))

            {

                bf = BindingFlags.InvokeMethod | BindingFlags.Static ;

                bf |= f;

                ms = t.GetMethods(bf);

                if (ms != null && ms.Length > 0)

                {

                    Console.WriteLine("BindingFlag is " + bf.ToString());

                    ShowMethodInfo(ms);

                }

            }

        }



        public static void ShowMethodInfo(MethodInfo[] ms)

        {

            foreach (MethodInfo m in ms)

            {

                Console.WriteLine("-------------------------------------------------------------");

                Console.WriteLine("/tMethod name : {0} /n/treturn type : {1} ",m.Name, m.ReturnType);

                ShowParameterInfo(m.GetParameters());

            }

            Console.WriteLine("*************************************************************/n");

        }



        public static void ShowParameterInfo(ParameterInfo [] ps)

        {

            foreach (ParameterInfo p in ps)

            {

                Console.WriteLine("/t/tParam name : {0}, type : {1}", p.Name, p.ParameterType );

            }

        }

    }



    public class Bruce

    {

        private string _PrivateAttribute="This is a private attribute";



        public string PublicAttribute="This is a public attribute";



        private void PrivateMethod(string arg)

        {

            Console.Write("This is a private method! arg is " + arg);

        }



        public void PublicMethod(string arg1,int arg2)

        {

            Console.Write("This is a public method! arg1 is {0},arg2 is {1}. " , arg1,arg2 );

        }



        private static string static_private_Method(string arg)

        {

            return ("This is a static and private method! arg is " + arg);

        }



        public  static string Static_Public_Method(string arg)

        {

           return ("This is a static and public method! arg is " + arg);

        }



        protected string protected_Method(string arg)

        {

            return ("This is a protected! arg is " + arg);

        }

    }

}

<think>好的,我现在需要详细解释Java反射中的`invoke`方法。首先,我得回忆反射的基本概念。反射允许程序在运行时检查、接口、字段和方法,并且可以动态调用方法。`invoke`方法是`Method`的一个关键方法,用于执行方法调用。 接下来,我需要确认`invoke`方法的定义。根据Java文档,`Method.invoke(Object obj, Object... args)`接受一个对象实例和参数数组,然后调用该方法。如果是静态方法,第一个参数可以是null。这可能会引发异常,比如IllegalAccessException或InvocationTargetException,需要处理这些异常。 然后,我需要思考`invoke`的使用场景。动态代理、框架设计(如Spring)、测试框架中的模拟对象等都会用到。比如,JUnit可能会用反射来运行测试方法,特别是带有特定注解的方法。 参数传递方面,需要注意基本型的自动装箱和拆箱。例如,如果方法参数是int型,传递Integer对象时会自动处理。但必须确保参数型和数量与方法声明一致,否则会抛出IllegalArgumentException。 访问权限也是一个重要点。即使方法是私有的,通过`setAccessible(true)`也可以绕过访问检查,调用私有方法。但这样做可能会破坏封装性,应当谨慎使用。 性能方面,反射调用通常比直接调用慢,因为JVM无法优化反射调用。但在现代JVM中,这个差距有所缩小,频繁调用时可能需要考虑缓存Method对象以提高性能。 异常处理方面,`InvocationTargetException`包裹了目标方法抛出的异常,需要通过`getCause()`获取原始异常。调用者需要处理或重新抛出这些异常。 最后,可能需要举几个例子来说明不同情况下的使用,比如调用实例方法、静态方法、带参数的方法以及处理返回值的情况。同时,对比直接调用和反射调用的代码差异,帮助理解其动态特性。 总结时,要强调`invoke`方法的灵活性和潜在风险,正确使用反射可以提高代码的灵活性,但滥用可能导致性能问题和维护困难。需要在实际应用中权衡利弊。</think>### 反射中 `Method.invoke()` 方法详解 #### 一、方法定义与核心作用 ```java public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException ``` - **作用**:动态执行指定对象的方法 - **参数说明**: - `obj`: 方法所属对象实例(静态方法传`null`) - `args`: 可变参数数组,需与方法参数列表严格匹配 - **返回值**:方法执行结果(void方法返回`null`) #### 二、关键特性对比 | 特性 | 直接调用 | 反射调用 | |---------------------|--------------------------|--------------------------| | 编译时型检查 | ✅ 强型安全 | ❌ 运行时可能抛出异常 | | 访问权限控制 | 遵守private/protected规则 | 可突破访问限制 | | 执行速度 | 快(JIT优化) | 慢(约慢2-10倍) | | 代码可读性 | 直观 | 需配合异常处理 | | 动态性 | 固定代码逻辑 | 可配置化执行任意方法 | #### 三、典型使用场景 1. **框架级方法调用**(Spring IOC容器) ```java // Spring中Controller方法调用示例 Method handlerMethod = controller.getClass().getMethod("handleRequest"); handlerMethod.invoke
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值