C# 反射调用带参数的重载的泛型方法

本文介绍了如何在C#中使用反射调用带有参数的重载泛型方法,并提供了当遇到"不能对ContainsGenericParameters为True的类型或方法执行后期绑定操作"异常时的解决方法,通过示例代码详细阐述了解决过程。

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

C# 反射调用带参数的重载的泛型方法。

以及调用时抛出:不能对 ContainsGenericParameters 为 True 的类型或方法执行后期绑定操作异常的解决办法。


话不多说,上代码!

  

  class Aa
    {
        public string CreateSql<T>()
        {
            return "Aa类无参泛型方法";
        }
        public string CreateSql<T>(T t)
        {
            return "Aa类单实体方法";
        }
        public string CreateSql<T>(List<T> t)
        {
            //List有2条数据
            string str = TReflection.GetSql<T>(t, this);
            return str;
        }
    }
    class Bb
    {
        public string CreateSql<T>()
        {
            return "Bb类无参泛型方法";
        }
        public string CreateSql<T>(T t)
        {
            return "Bb类单实体方法";
        }
        public string CreateSql<T>(List<T> t)
        {
            string str = TReflection.GetSql<T>(t, this);
            return str;
        }
    }

    class TReflection
    {
        //需要调用类中的单实体方法
        public static string GetSql<T>(List<T> t, Object _class)
        {
            MethodInfo[] pa = _class.GetType().GetMethods();//反射获得所有方法

            MethodInfo pi = null;
            foreach (MethodInfo method in pa)
            {
                if (method.ToString() == "System.String CreateSql[T](T)")//简单粗暴的获取想要的方法的对象
                {
                    pi = method;
                    break;
                }
            }

            /*
             *如果没有此句代码则会抛出:“不能对 ContainsGenericParameters 为 True 的类型或方法执行后期绑定操作。”的异常。
             *原因:因为调用泛型方法,方法自身的类型参数或任何封闭类型中必须不含泛型类型定义或开放构造类型。进行这种递归确认是很困难的。
             *      为方便起见,也为了减少错误,ContainsGenericParameters 属性提供一种标准方法来区分封闭构造方法(可以调用)和开放构造方法(不能调用)。
             *      如果 ContainsGenericParameters 属性返回 true,则方法不能调用。
             *作用:用类型数组的元素代替当前泛型方法定义的类型参数,并返回表示结果构造方法的 MethodInfo 对象。
             */
            pi = pi.MakeGenericMethod(new Type[] { typeof(T) });

            StringBuilder sb = new StringBuilder();
            foreach (T item in t)
            {
                object[] parament = new object[1];//一个参数
                parament[0] = item;
                sb.Append(pi.Invoke(_class, parament)); //调用方法
            }
            return sb.ToString();
        }
    }


结果:





<think>我们正在处理一个关于C#反射调用方法的问题。用户要求一个示例,展示如何使用反射调用方法。根据提供的引用,我们可以总结出以下步骤:1.获取类(Type)信息,可以通过typeof(类名)或者实例.GetType()来获取。2.创建实例(如果方法不是静态的),可以使用Activator.CreateInstance方法。3.获取方法信息(MethodInfo),通过Type.GetMethod方法,传入方法名。4.调用方法,使用MethodInfo.Invoke方法,第一个参数是实例(如果是静态方法则传null),第二个参数方法参数数组。引用中提供了几个例子:引用[1]:MethodInfo methodInfo =type.GetMethod("MethodName"); methodInfo.Invoke(instance,null);引用[2]:展示了完整的流程,包括获取类、创建实例、获取方法调用。引用[3]:展示了一个类,其中包含实例方法、静态方法带参数和不带参数)的例子。因此,我们可以编写一个示例,包含以下三种情况:1.调用带参数的实例方法。2.调用带参数的静态方法。3.调用参数的静态方法。同时,为了清晰,我们将创建一个名为ReflectionExample的类,其中包含这些方法。然后,在Main方法中演示如何使用反射调用这些方法。注意:在调用方法时,Invoke的第二个参数是一个object数组,包含方法参数。如果方法没有参数,可以传递null或一个空数组。我们将按照以下步骤编写代码:1.定义包含不同类方法的类。2.获取该类的Type对象。3.对于实例方法,创建实例。4.获取MethodInfo对象,指定方法名和参数(如果有重载,需要指定参数数组)。5.调用Invoke方法。另外,为了处理重载的情况,GetMethod方法可能需要传递参数数组来指定具体的方法。下面我们编写示例代码。</think>### C#反射调用方法示例 在C#中通过反射调用方法主要涉及以下步骤: ```csharp using System; using System.Reflection; public class ReflectionExample { // 实例方法 public void InstanceMethod(string message) { Console.WriteLine($"实例方法: {message}"); } // 静态方法 public static void StaticMethod(int number) { Console.WriteLine($"静态方法: {number}"); } } class Program { static void Main() { // 1. 获取类信息 Type type = typeof(ReflectionExample); // 2. 创建实例(非静态方法需要) object instance = Activator.CreateInstance(type); // 3. 调用实例方法 MethodInfo instanceMethod = type.GetMethod("InstanceMethod"); instanceMethod.Invoke(instance, new object[] { "Hello Reflection" }); // 4. 调用静态方法 MethodInfo staticMethod = type.GetMethod("StaticMethod"); staticMethod.Invoke(null, new object[] { 42 }); // 静态方法实例参数为null // 5. 调用私有方法(需要BindingFlags) MethodInfo privateMethod = type.GetMethod("PrivateMethod", BindingFlags.NonPublic | BindingFlags.Instance); privateMethod.Invoke(instance, null); } } ``` **关键点说明:** 1. **获取方法信息**:使用`Type.GetMethod()`获取MethodInfo对象 2. **方法调用**: - 实例方法:`methodInfo.Invoke(instance, parameters)` - 静态方法:`methodInfo.Invoke(null, parameters)` 3. **参数传递**:参数以`object[]`数组形式传递 4. **访问修饰符处理**: - 私有方法需要指定`BindingFlags.NonPublic` - 默认只查找公共方法 **特殊场景处理:** ```csharp // 重载方法调用(指定参数) MethodInfo overloadedMethod = type.GetMethod("Method", new Type[] { typeof(string), typeof(int) }); // 方法调用 MethodInfo genericMethod = type.GetMethod("GenericMethod"); MethodInfo constructed = genericMethod.MakeGenericMethod(typeof(string)); constructed.Invoke(instance, null); ``` **注意事项:** 1. 方法不存在时会抛出`MissingMethodException` 2. 参数不匹配会抛出`ArgumentException` 3. 性能考虑:反射调用比直接调用慢约100-1000倍[^1] 4. 安全性:反射需要相应的代码访问权限 [^1]: 反射的核心类:Type, MethodInfo, FieldInfo, PropertyInfo, ConstructorInfo 等类提供了丰富的反射功能 [^2]: using System.Reflection; Type type = typeof(Example); object instance = Activator.CreateInstance(type); // 获取方法信息 MethodInfo method = type.GetMethod("Print"); method.Invoke(instance, null); [^3]: c# invoke()使用。编写一个类 namespace ReflectionTest { public class WriteTest { //带参数的公共方法 public void WriteString(string s, int i) { Console.WriteLine("WriteString:" + s + i.ToString()); } //带一个参数的静态方法 public static void StaticWriteString(string s) { Console.WriteLine("StaticWriteString:" + s); } //不带参数的静态方法 public static void NoneParaWriteString() { Console.WriteLine("NoParaWriteString"); } } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值