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

发布于 2024-09-11 06:53:47 字数 835 浏览 5 评论 0原文

我有一个 MethodInfo 传递给一个函数,我想执行以下操作

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

但这不起作用,因为 methodInfo 具有特定的泛型类型。如果我知道 ICollection 始终是字符串类型,则该示例确实有效。

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;

I have a MethodInfo passed in to a function and I want to do the following

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. For the example does work if I knew that the ICollection was always of type string.

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?

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<>.

EDIT: more context

I am writing a Linq provider and trying to handle the "in" case

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

喜你已久 2024-09-18 06:53:48

请注意,ICollection.Contains 不是泛型方法 - 它是泛型类型的非泛型方法。否则,IsGenericMethodGetGenericTypeDefinition 会有所帮助。您可以获取泛型类型定义 (DeclaringType.GetGenericTypeDefinition()) 并返回到 Contains,但我想知道您是否正在以困难的方式解决这个问题。

通常,如果您使用反射,则放弃到非通用 IList 可能是务实的 - 除非您需要类型数据(例如,用于元编程)。在这种情况下,我会考虑仔细查看是否可以简化此处的设置。

Note that ICollection<T>.Contains is not a generic method - it is a non-generic method of a generic type. Otherwise IsGenericMethod and GetGenericTypeDefinition would help. 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.

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). And in that case, I would consider looking closely to see if you can simplify the setup here.

成熟的代价 2024-09-18 06:53:48

您可以检查声明类型:

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

You could check the declaring type:

if( methodInfo.Name == "Contains" 
    &&  methodInfo.DeclaringType.IsGenericType
    && methodInfo.DeclaringType.GetGenericTypeDefinition() == typeof(ICollection<>))
{
南薇 2024-09-18 06:53:48

需要添加一些错误检查,但我相信这大致可以满足您的要求。您可以使用带或不带类型参数的方法作为参数。

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

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);
}
烟─花易冷 2024-09-18 06:53:48

问题是您没有泛型方法:您在泛型类型上有非泛型方法。我不知道如何使用反射直接从开放泛型类型上的方法定义转到封闭泛型类型上的相同方法,反之亦然。但是,您可以利用以下事实:开放泛型类型和封闭泛型类型上的 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
}

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:

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
}
芯好空 2024-09-18 06:53:48

尝试这个方法

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

}

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

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文