I've got a generic method within a generic class. Inside this method, I need to call the same method for a parent type if the method's generic parameter's type isn't mapped, but the parent it. I'm getting different results for the two bits of code, though I'd expect them to be the same.
This succeeds:
MethodInfo methodInfo2 = this.GetType().GetMethods()[9]; // this is the correct one.
methodInfo2 = methodInfo2.MakeGenericMethod(mappedType);
This crashes:
MethodInfo methodInfo1 = System.Reflection.MethodBase.GetCurrentMethod() as MethodInfo;
methodInfo1 = methodInfo1.MakeGenericMethod(mappedType);
with this exception:
GenericArguments[0], 'GenericClassConstraintAbstract.Abstract', on 'System.Collections.Generic.IList`1[Entity] GetEntities[Entity](System.Linq.Expressions.Expression`1[System.Func`2[Entity,System.Boolean]], Sbu.Sbro.Common.Core.Pagination.Paginator`1[Entity])' violates the constraint of type 'Entity'.
If I add methodInfo1 == methodInfo2
in a debugger watch, I get false
, but I can't figure out what the difference is. I could be more intelligent than using [9]
to select the right method and do it that way, but I'd also like to know why the version that crashes does so.
Any ideas?
edit: now with better example:
interface BaseInterface
{ }
interface MyInterface : BaseInterface
{ }
abstract class Abstract : MyInterface
{ }
class Concrete : Abstract, MyInterface
{ }
class ProblemClass<GenericType> where GenericType : BaseInterface
{
public virtual IList<Entity> ProblemMethod<Entity>() where Entity : class, GenericType
{
if (typeof(Entity) == typeof(Concrete))
{
MethodInfo methodInfo = System.Reflection.MethodBase.GetCurrentMethod() as MethodInfo;
var t1 = this.GetType(); // perhaps the problem resides in
var t2 = methodInfo.DeclaringType; // these two not being equal?
methodInfo = methodInfo.MakeGenericMethod(typeof(Abstract));
return (methodInfo.Invoke(this, new Object[] { }) as IList).OfType<Entity>().ToList();
}
else
{
return new List<Entity>();
}
}
}
class Program
{
static void Main(string[] args)
{
new ProblemClass<MyInterface>().ProblemMethod<Concrete>();
}
}
So, the problem is that the declaring type was an open generic, and the constraint in the generic method was dependent on the generic type parameter in the type.
The following code solved the problem:
MethodInfo methodInfo = System.Reflection.MethodBase.GetCurrentMethod() as MethodInfo;
methodInfo = this.GetType().GetMethod(methodInfo.Name, methodInfo.GetParameters().Select(p => p.ParameterType).ToArray());
methodInfo = methodInfo.MakeGenericMethod(typeof(Abstract));
return (methodInfo.Invoke(this, new Object[] { }) as IList).OfType<Entity>().ToList();
See the remarks in http://msdn.microsoft.com/en-us/library/system.reflection.methodbase.getcurrentmethod.aspx.