如何按名称及其通用参数获取通用方法的MethodInfo?

时间:2018-04-04 21:26:08

标签: c# reflection system.reflection

我有这个界面:

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

IDomainObjectReference究竟与此问题无关。所以假设它们完全是空的:

interface IDomainObject
{
    // something
}

class Reference<T> where T : IDomainObject
{
    // something
}

我的问题是:如何获得GetId<T>中接受IRepository的<{1}}方法的MethodInfo

这是我尝试过的:

Reference<T>

看起来方法的参数类型与完全开放的泛型类型有某种不同。我猜,似乎方法参数的类型以某种方式链接到方法的泛型类型参数。

那么如何在这种情况下获得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(); }

1 个答案:

答案 0 :(得分:2)

参数类型不能是泛型类型定义。它有一个类型参数 - 这是方法的类型参数。您可以从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();
    }
}