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

豪克

我有这个界面:

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
}

我的问题是:如何获取接受aMethodInfoGetId<T>方法IRepositoryReference<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();
}

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

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

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章