Shane
Shane

Reputation: 2361

How to match method with a complex generic parameter using reflection?

I am trying to call a EntityFramework method using reflection. The signature of the method is

DbCollectionEntry<TEntity, TElement> Collection<TElement> 
(Expression <Func<TEntity, ICollection <TElement>>> navigationProperty) where TElement : class

where TEntity is a type parameter of the class. How can construct a type which which will equal Expression <Func<TEntity, ICollection <TElement>>> so I can find the right overload of the method? I tried typeof(Expression<>).MakeGenericType(new[] { typeof(Func<,>) }); which displays the same in the debugger but doesn't match by equality. Once I have the method how do I call it? I managed to find the method by excluding the one with a string parameter but I still want find out how to match the method properly. I tried invoking the method using method.MakeGenericMethod(typeof(MyType)).Invoke(context.Entry(t), new[] { lambda }); but I get the exception "Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true." Here's what I have so far

var collectionMethod = typeof(DbEntityEntry<>)
    .GetMethods()
        .Where(m => m.Name == "Collection")
        .Select(m => new { Method = m, Params = m.GetParameters(), Args = m.GetGenericArguments() })
        .Where(x => x.Args.Length == 1 && x.Params[0].ParameterType != typeof(string))
        .Select(x => x.Method)
        .First();

var lambda = Expression.Lambda<Func<Trade, ICollection<TradeLeg>>>(prop, param);

// this fails
var o = collectionMethod.MakeGenericMethod(typeof(TradeLeg))
    .Invoke(context.Entry(t), new[] { lambda });

Upvotes: 0

Views: 132

Answers (1)

IS4
IS4

Reputation: 13227

var collectionMethod = typeof(DbEntityEntry<>)

This line condemns you to a failure, because the method will be looked for on the generic definition, not on the constructed type you use. The method must be identified on the concrete type, not on the definition, in order to call it. Based on your code, I assume the correct expression is typeof(DbEntityEntry<Trade>).

Upvotes: 0

Related Questions