How do I determine if a method is a generic instance of a generic method
I have a MethodInfo passed in to a function and I want to do the following
MethodInfo containsMethod = typeof(ICollection<>).GetMethod("Contains");
if (methodInfo.Equals(containsMethod)
{
// do something
}
But this doesn't work because the methodInfo has a specific generic type. For the example does work if I knew that the ICollection was always of type string.
MethodInfo containsMethod = typeof(ICollection<string>).GetMethod("Contains");
if (methodInfo.Equals(containsMethod)
{
// do something
}
How can I check whether the MethodInfo is a ANY typed instance of the generic method without caring what the type is?
Thanks.
EDIT: Question clarification
As correctly pointed out the method is not generic but the containing class is so the question is more how to I find out if the MethodInfo is for a Type which is a typed instance of ICollection<>.
EDIT: more context
I am writing a Linq pro开发者_运维百科vider and trying to handle the "in" case
IList<string> myList = new List<string>{ "1", "2" };
from Something s in ...
where myList.Contains(s.name)
select s;
Note that ICollection<T>.Contains
is not a generic method - it is a non-generic method of a generic type. Otherwise IsGenericMethod
and GetGenericTypeDefinition
would help. You could obtain the generic type definition (DeclaringType.GetGenericTypeDefinition()
) and work back up to Contains
, but I wonder if you are approaching this problem the hard way.
Usually, if you are using reflection, it may be pragmatic to drop to non-generic IList
- unless you need the type data (for example, for meta-programming). And in that case, I would consider looking closely to see if you can simplify the setup here.
You could check the declaring type:
if( methodInfo.Name == "Contains"
&& methodInfo.DeclaringType.IsGenericType
&& methodInfo.DeclaringType.GetGenericTypeDefinition() == typeof(ICollection<>))
{
Some error checking would need to be added to this, but I believe this roughly does what you want. You can use a method with or without a type argument as the parameter.
static bool IsContainsMethod(MethodInfo methodInfo)
{
Type[] types = { methodInfo.GetParameters().First().ParameterType };
MethodInfo containsMethod = typeof(ICollection<>).MakeGenericType(types).GetMethod("Contains");
return methodInfo.Equals(containsMethod);
}
The problem is that you don't have a generic method: you have a non-generic method on a generic type. I don't know of a way to use reflection to go directly from a method definition on an open generic type to that same method on a closed generic type or vice versa. However, you can take advantage of the fact that the methods returned by GetMethods()
on the open and closed generic types should always be in the same order and do the translation by index:
MethodInfo containsMethod = typeof(ICollection<>).GetMethod("Contains");
var methodIndex = Array.IndexOf(methodInfo.DeclaringType.GetMethods(), methodInfo);
var methodOnTypeDefinition = methodInfo.DeclaringType.GetGenericTypeDefinition().GetMethods()[methodIndex];
if (methodOnTypeDefinition.Equals(containsMethod))
{
// do something
}
try this method
public static bool CheckGenericMethod(MethodInfo methodInfo)
{
bool areSimilarMethods = false;
MethodInfo methodToCompare = typeof(ISomeInterface<>).GetMethod("func");
Type interfaceInfo = methodInfo.DeclaringType.GetInterface(methodToCompare.DeclaringType.FullName);
if (interfaceInfo != null)
areSimilarMethods = (methodToCompare.Name.Equals(methodInfo.Name)
&& interfaceInfo.FullName.Contains(methodToCompare.DeclaringType.FullName));
else
{
areSimilarMethods = methodToCompare.DeclaringType.Equals(methodInfo.DeclaringType);
}
return areSimilarMethods;
}
and here is the full example usage.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace TestReflection
{
public class Program
{
static void Main(string[] args)
{
MethodInfo info1 = typeof(ISomeInterface<>).GetMethod("func");
MethodInfo info2 = typeof(MyStringCollection).GetMethod("func");
MethodInfo info3 = typeof(MyProgramCollection).GetMethod("func");
MethodInfo info4 = typeof(MyXCollection).GetMethod("func");
if (CheckGenericMethod(info1)) Console.WriteLine("true");else Console.WriteLine("false");
if (CheckGenericMethod(info2)) Console.WriteLine("true");else Console.WriteLine("false");
if (CheckGenericMethod(info3)) Console.WriteLine("true");else Console.WriteLine("false");
if (CheckGenericMethod(info4)) Console.WriteLine("true"); else Console.WriteLine("false");
Console.ReadKey();
}
public static bool CheckGenericMethod(MethodInfo methodInfo)
{
bool areSimilarMethods = false;
MethodInfo methodToCompare = typeof(ISomeInterface<>).GetMethod("func");
Type interfaceInfo = methodInfo.DeclaringType.GetInterface(methodToCompare.DeclaringType.FullName);
if (interfaceInfo != null)
areSimilarMethods = (methodToCompare.Name.Equals(methodInfo.Name)
&& interfaceInfo.FullName.Contains(methodToCompare.DeclaringType.FullName));
else
{
areSimilarMethods = methodToCompare.DeclaringType.Equals(methodInfo.DeclaringType);
}
return areSimilarMethods;
}
}
public interface ISomeInterface<T> where T : class
{
T func(T s);
}
public class MyStringCollection : ISomeInterface<string>
{
public string func(string s)
{
return s;
}
}
public class MyProgramCollection : ISomeInterface<Program>
{
public Program func(Program s)
{
return s;
}
}
public class MyXCollection
{
public int func(int s)
{
return s;
}
}
}
精彩评论