簡體   English   中英

如何通過名稱及其通用參數獲取通用方法的MethodInfo?

[英]How to get MethodInfo for a generic method by name and its generic parameters?

我有這個界面:

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
}

我的問題是: 如何在接受Reference<T> IRepository中獲取GetId<T>方法的MethodInfo


這是我嘗試過的:

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

看來方法的參數類型與完全開放的泛型類型有所不同。 我猜,似乎方法的參數類型以某種方式鏈接到方法的泛型類型參數。

那么在這種情況下如何獲取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();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM