C# 如何按名称及其泛型参数获取泛型方法的MethodInfo?

C# 如何按名称及其泛型参数获取泛型方法的MethodInfo?,c#,reflection,system.reflection,C#,Reflection,System.reflection,我有这个界面: interface IRepository { string GetId<T>(T obj) where T : IDomainObject; string GetId<T>(Reference<T> reference) where T : IDomainObject; } 我的问题是:如何获取接受引用的I假定中的GetId方法的属性? 以下是我尝试过的: public MethodInfo GetReferenceAcc

我有这个界面:

interface IRepository
{
    string GetId<T>(T obj) where T : IDomainObject;
    string GetId<T>(Reference<T> reference) where T : IDomainObject;
}
我的问题是:如何获取接受
引用的
I假定中的
GetId
方法的属性?


以下是我尝试过的:

public MethodInfo GetReferenceAcceptingGetIdMethod()
{
    // We want to return the MethodInfo for the GetId<T> method of IRepository
    // that accepts a Reference<T> argument.

    var repositoryInterfaceType = typeof(IRepository);

    // Look through all methods of IRepository...
    foreach (var m in repositoryInterfaceType.GetMethods())
    {
        // ... to find a candidate method, going by Genericness and Name ...
        if (m.IsGenericMethodDefinition && m.Name == nameof(IRepository.GetId))
        {
            // ... and to narrow it further down by looking at the parameters ...
            var parameters = m.GetParameters();
            if (parameters.Length == 1)
            {
                // ... to check if the one and only parameter is a generic Reference<>.
                var firstParamType = parameters[0].ParameterType;
                var genericReferenceType = typeof(Reference<>);
                if (firstParamType == genericReferenceType)
                {
                    // !!! This if will never be true.
                    // Why?
                    // And what do I have to change the condition into to make it work?
                    return m;
                }
            }
        }
    }

    throw new Exception();
}
公共方法信息GetReferenceAcceptingGetIdMethod() { //我们想返回IRepository的GetId方法的MethodInfo //接受引用参数的。 var repositoryInterfaceType=类型(IRepository); //通读所有的信息存储方法。。。 foreach(repositoryInterfaceType.GetMethods()中的var m) { //…要查找候选方法,请按泛型和名称。。。 if(m.IsGenericMethodDefinition&&m.Name==nameof(IRepository.GetId)) { //…并通过查看参数进一步缩小范围。。。 var参数=m.GetParameters(); if(parameters.Length==1) { //…以检查唯一的参数是否为泛型引用。 var firstParamType=参数[0]。ParameterType; var generireferencetype=typeof(参考); if(firstParamType==genericReferenceType) { //!!!这永远不会是真的。 //为什么?? //我必须把条件变成什么才能让它工作? 返回m; } } } } 抛出新异常(); }
该方法的参数类型似乎与完全开放的泛型类型有所不同。我猜,方法参数的类型似乎以某种方式与方法的泛型类型参数相关联


那么,在这种情况下,如何获取
MethodInfo

参数类型不能是泛型类型定义。它有一个类型参数-这是该方法的类型参数。您可以从
MethodInfo.GetGenericArguments()
中获取该类型参数,然后将其与
typeof(Reference)一起使用。MakeGenericType(…)
以获取所需的参数类型

下面是一个完整的示例,基本上是修改原始代码:

using System;
using System.Reflection;

class Reference<T> {}
interface IDomainObject {}

interface IRepository
{
    string GetId<T>(T obj) where T : IDomainObject;
    string GetId<T>(Reference<T> reference) where T : IDomainObject;
}

class Test
{
    static void Main()
    {
        var method = GetReferenceAcceptingGetIdMethod();
        Console.WriteLine(method);
    }

    public static MethodInfo GetReferenceAcceptingGetIdMethod()
    {
        var repositoryInterfaceType = typeof(IRepository);
        foreach (var m in repositoryInterfaceType.GetMethods())
        {
            if (m.IsGenericMethodDefinition && m.Name == nameof(IRepository.GetId))
            {
                var typeParameter = m.GetGenericArguments()[0];
                var expectedParameterType = typeof(Reference<>).MakeGenericType(typeParameter);
                var parameters = m.GetParameters();
                if (parameters.Length == 1)
                {
                    var firstParamType = parameters[0].ParameterType;
                    if (firstParamType == expectedParameterType)
                    {
                        return m;
                    }
                }
            }
        }        
        throw new Exception();
    }
}
使用系统;
运用系统反思;
类引用{}
接口IDomainObject{}
界面假定
{
字符串GetId(T obj),其中T:IDomainObject;
字符串GetId(引用),其中T:IDomainObject;
}
课堂测试
{
静态void Main()
{
var method=GetReferenceAcceptingGetIdMethod();
控制台写入线(方法);
}
公共静态方法信息GetReferenceAcceptingGetIdMethod()
{
var repositoryInterfaceType=类型(IRepository);
foreach(repositoryInterfaceType.GetMethods()中的var m)
{
if(m.IsGenericMethodDefinition&&m.Name==nameof(IRepository.GetId))
{
var typeParameter=m.GetGenericArguments()[0];
var expectedParameterType=typeof(参考)。MakeGenericType(typeParameter);
var参数=m.GetParameters();
if(parameters.Length==1)
{
var firstParamType=参数[0]。ParameterType;
if(firstParamType==expectedParameterType)
{
返回m;
}
}
}
}        
抛出新异常();
}
}

哇,太酷了。我没想到
m
在它仍然打开时会有一个泛型参数。此外,泛型参数似乎是一种非常奇怪的“类型”,名为
T
。但是您的解决方案非常有效,所以非常感谢。@HaukeP:在将其包含到代码中之前,请后退一步以确保您理解它是值得的(这样您以后可以在必要时对其进行更改,或者在将来编写类似的代码)。它一点也不奇怪——它是方法的类型参数。看看您是如何声明参数的:
Reference
。这不是一个开放的泛型类型;它是一个泛型类型,使用的类型参数恰好是方法中的类型参数。
using System;
using System.Reflection;

class Reference<T> {}
interface IDomainObject {}

interface IRepository
{
    string GetId<T>(T obj) where T : IDomainObject;
    string GetId<T>(Reference<T> reference) where T : IDomainObject;
}

class Test
{
    static void Main()
    {
        var method = GetReferenceAcceptingGetIdMethod();
        Console.WriteLine(method);
    }

    public static MethodInfo GetReferenceAcceptingGetIdMethod()
    {
        var repositoryInterfaceType = typeof(IRepository);
        foreach (var m in repositoryInterfaceType.GetMethods())
        {
            if (m.IsGenericMethodDefinition && m.Name == nameof(IRepository.GetId))
            {
                var typeParameter = m.GetGenericArguments()[0];
                var expectedParameterType = typeof(Reference<>).MakeGenericType(typeParameter);
                var parameters = m.GetParameters();
                if (parameters.Length == 1)
                {
                    var firstParamType = parameters[0].ParameterType;
                    if (firstParamType == expectedParameterType)
                    {
                        return m;
                    }
                }
            }
        }        
        throw new Exception();
    }
}