如何使用反射将方法与复杂的通用参数匹配?

时间:2017-08-04 08:52:42

标签: c# reflection

我正在尝试使用反射调用EntityFramework方法。 该方法的签名是

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

其中TEntity是类的类型参数。如何构造一个等于Expression <Func<TEntity, ICollection <TElement>>>的类型,以便找到方法的正确重载?我试过typeof(Expression<>).MakeGenericType(new[] { typeof(Func<,>) });,它在调试器中显示相同但不相等。一旦我有了这个方法,我该怎么称呼它?我设法通过使用字符串参数排除方法来找到该方法,但我仍然想知道如何正确匹配该方法。我尝试使用method.MakeGenericMethod(typeof(MyType)).Invoke(context.Entry(t), new[] { lambda });调用该方法,但我得到了异常“无法对ContainsGenericParameters为true的类型或方法执行后期绑定操作。”这是我到目前为止所拥有的

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 });

1 个答案:

答案 0 :(得分:0)

var collectionMethod = typeof(DbEntityEntry<>)

此行谴责您失败,因为将在通用定义上查找该方法,而不是在您使用的构造类型上查找。必须在具体类型上识别该方法,而不是在定义上,以便调用它。根据您的代码,我假设正确的表达式为typeof(DbEntityEntry<Trade>)