简体   繁体   English

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

[英]How do I determine if a method is a generic instance of a generic method

I have a MethodInfo passed in to a function and I want to do the following 我有一个MethodInfo传入一个函数,我想做以下

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

But this doesn't work because the methodInfo has a specific generic type. 但这不起作用,因为methodInfo具有特定的泛型类型。 For the example does work if I knew that the ICollection was always of type string. 如果我知道ICollection始终是字符串类型,那么该示例确实有效。

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

How can I check whether the MethodInfo is a ANY typed instance of the generic method without caring what the type is? 如何检查MethodInfo是否是泛型方法的任何类型实例,而不关心类型是什么?

Thanks. 谢谢。

EDIT: Question clarification 编辑:问题澄清

As correctly pointed out the method is not generic but the containing class is so the question is more how to I find out if the MethodInfo is for a Type which is a typed instance of ICollection<>. 正确地指出这个方法不是通用的,但是包含类的问题更多的是我如何找出MethodInfo是否是一个类型是ICollection <>的类型化实例。

EDIT: more context 编辑:更多背景

I am writing a Linq provider and trying to handle the "in" case 我正在写一个Linq提供程序并试图处理“in”情况

IList<string> myList = new List<string>{ "1", "2" };

from Something s in ...
where myList.Contains(s.name)
select s;

Note that ICollection<T>.Contains is not a generic method - it is a non-generic method of a generic type. 请注意, ICollection<T>.Contains 不是泛型方法 - 它是泛型类型的非泛型方法。 Otherwise IsGenericMethod and GetGenericTypeDefinition would help. 否则IsGenericMethodGetGenericTypeDefinition会有所帮助。 You could obtain the generic type definition ( DeclaringType.GetGenericTypeDefinition() ) and work back up to Contains , but I wonder if you are approaching this problem the hard way. 你可以获得泛型类型定义( DeclaringType.GetGenericTypeDefinition() )并返回到Contains ,但我想知道你是否正在努力解决这个问题。

Usually, if you are using reflection, it may be pragmatic to drop to non-generic IList - unless you need the type data (for example, for meta-programming). 通常,如果您使用反射,则删除非泛型IList可能是实用的 - 除非您需要类型数据(例如,用于元编程)。 And in that case, I would consider looking closely to see if you can simplify the setup here. 在这种情况下,我会考虑仔细查看是否可以简化设置。

You could check the declaring type: 您可以检查声明类型:

if( methodInfo.Name == "Contains" 
    &&  methodInfo.DeclaringType.IsGenericType
    && methodInfo.DeclaringType.GetGenericTypeDefinition() == typeof(ICollection<>))
{

Some error checking would need to be added to this, but I believe this roughly does what you want. 需要添加一些错误检查,但我相信这大致可以满足您的需求。 You can use a method with or without a type argument as the parameter. 您可以使用带或不带类型参数的方法作为参数。

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

The problem is that you don't have a generic method: you have a non-generic method on a generic type. 问题是您没有通用方法:在泛型类型上有非泛型方法。 I don't know of a way to use reflection to go directly from a method definition on an open generic type to that same method on a closed generic type or vice versa. 我不知道如何使用反射直接从开放泛型类型的方法定义转到封闭泛型类型上的相同方法,反之亦然。 However, you can take advantage of the fact that the methods returned by GetMethods() on the open and closed generic types should always be in the same order and do the translation by index: 但是,您可以利用以下事实: 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
}

try this method 试试这个方法

    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;

    }

and here is the full example usage. 这是完整的示例用法。

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

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM