我有这个界面:
interface IRepository
{
string GetId<T>(T obj) where T : IDomainObject;
string GetId<T>(Reference<T> reference) where T : IDomainObject;
}
IDomainObject
和Reference
究竟与此问题无关。所以假设它们完全是空的:
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();
}
?
答案 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();
}
}