代码之家  ›  专栏  ›  技术社区  ›  Mike Q

如何确定方法是否是泛型方法的泛型实例

  •  7
  • Mike Q  · 技术社区  · 14 年前

    MethodInfo containsMethod = typeof(ICollection<>).GetMethod("Contains");
    if (methodInfo.Equals(containsMethod)
    {
       // do something
    }
    

    但这不起作用,因为methodInfo有一个特定的泛型类型。例如,如果我知道ICollection始终是string类型,那么这个示例就可以工作。

    MethodInfo containsMethod = typeof(ICollection<string>).GetMethod("Contains");
    if (methodInfo.Equals(containsMethod)
    {
       // do something
    }
    

    我如何检查MethodInfo是否是泛型方法的任何类型的实例,而不关心类型是什么?

    编辑:问题澄清

    正如正确指出的那样,方法不是泛型的,但包含类是泛型的,因此问题更多的是如何找出MethodInfo是否用于ICollection的类型化实例<>。

    编辑:更多上下文

    我正在写一个Linq提供者,并试图处理“in”的情况

    IList<string> myList = new List<string>{ "1", "2" };
    
    from Something s in ...
    where myList.Contains(s.name)
    select s;
    
    5 回复  |  直到 14 年前
        1
  •  3
  •   Andrew Kennan    14 年前

    您可以检查声明类型:

    if( methodInfo.Name == "Contains" 
        &&  methodInfo.DeclaringType.IsGenericType
        && methodInfo.DeclaringType.GetGenericTypeDefinition() == typeof(ICollection<>))
    {
    
        2
  •  4
  •   Marc Gravell    14 年前

    ICollection<T>.Contains 泛型方法-它是 非泛型 泛型类型的方法。否则 IsGenericMethod GetGenericTypeDefinition 会有帮助的。您可以获得泛型类型定义( DeclaringType.GetGenericTypeDefinition() Contains ,但我想知道你是不是在努力解决这个问题。

    通常,如果您使用的是反射,那么使用非泛型可能比较实用 IList

        3
  •  2
  •   Anthony Pegram    14 年前

    一些错误检查将需要添加到这个,但我相信这大致上做你想要的。可以使用带或不带类型参数的方法作为参数。

    static bool IsContainsMethod(MethodInfo methodInfo)
    {
        Type[] types = { methodInfo.GetParameters().First().ParameterType };
        MethodInfo containsMethod = typeof(ICollection<>).MakeGenericType(types).GetMethod("Contains");
        return methodInfo.Equals(containsMethod);
    }
    
        4
  •  0
  •   Quartermeister    14 年前

    问题是没有泛型方法:泛型类型上有一个非泛型方法。我不知道如何使用反射直接从开放泛型类型上的方法定义转到封闭泛型类型上的相同方法,反之亦然。但是,您可以利用 GetMethods() 打开和关闭的泛型类型的顺序应始终相同,并按索引进行转换:

    MethodInfo containsMethod = typeof(ICollection<>).GetMethod("Contains");
    var methodIndex = Array.IndexOf(methodInfo.DeclaringType.GetMethods(), methodInfo);
    var methodOnTypeDefinition = methodInfo.DeclaringType.GetGenericTypeDefinition().GetMethods()[methodIndex];
    if (methodOnTypeDefinition.Equals(containsMethod))
    {
        // do something
    }
    
        5
  •  0
  •   Tiju John    14 年前

    试试这个方法

        public static bool CheckGenericMethod(MethodInfo methodInfo)
        {
            bool areSimilarMethods = false;
            MethodInfo methodToCompare = typeof(ISomeInterface<>).GetMethod("func");
            Type interfaceInfo = methodInfo.DeclaringType.GetInterface(methodToCompare.DeclaringType.FullName);
    
            if (interfaceInfo != null)
                areSimilarMethods = (methodToCompare.Name.Equals(methodInfo.Name)
                && interfaceInfo.FullName.Contains(methodToCompare.DeclaringType.FullName));
            else
            {
                areSimilarMethods = methodToCompare.DeclaringType.Equals(methodInfo.DeclaringType);
            }
    
            return areSimilarMethods;
    
        }
    

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Reflection;
    
    namespace TestReflection
    {
        public class Program
        {
            static void Main(string[] args)
            {
                MethodInfo info1 = typeof(ISomeInterface<>).GetMethod("func");
                MethodInfo info2 = typeof(MyStringCollection).GetMethod("func");
                MethodInfo info3 = typeof(MyProgramCollection).GetMethod("func");
                MethodInfo info4 = typeof(MyXCollection).GetMethod("func");
    
                if (CheckGenericMethod(info1)) Console.WriteLine("true");else Console.WriteLine("false");
                if (CheckGenericMethod(info2)) Console.WriteLine("true");else Console.WriteLine("false");
                if (CheckGenericMethod(info3)) Console.WriteLine("true");else Console.WriteLine("false");
                if (CheckGenericMethod(info4)) Console.WriteLine("true"); else Console.WriteLine("false");
    
                Console.ReadKey();
            }
    
    
            public static bool CheckGenericMethod(MethodInfo methodInfo)
            {
                bool areSimilarMethods = false;
                MethodInfo methodToCompare = typeof(ISomeInterface<>).GetMethod("func");
                Type interfaceInfo = methodInfo.DeclaringType.GetInterface(methodToCompare.DeclaringType.FullName);
    
                if (interfaceInfo != null)
                    areSimilarMethods = (methodToCompare.Name.Equals(methodInfo.Name)
                    && interfaceInfo.FullName.Contains(methodToCompare.DeclaringType.FullName));
                else
                {
                    areSimilarMethods = methodToCompare.DeclaringType.Equals(methodInfo.DeclaringType);
                }
    
                return areSimilarMethods;
    
            }
        }
    
        public interface ISomeInterface<T> where T : class
        {
            T func(T s);
        }
    
        public class MyStringCollection : ISomeInterface<string>
        {
            public string func(string s)
            {
                return s;
            }
        }
    
        public class MyProgramCollection : ISomeInterface<Program>
        {
            public Program func(Program s)
            {
                return s;
            }
        }
    
        public class MyXCollection
        {
            public int func(int s)
            {
                return s;
            }
        }
    
    }