Первый универсальный параметр делегата Func<T, TResult>
объявлен как контравариантный (in
), что означает, что вы можете назначить делегат с менее производным параметром делегату с более производным параметром, но не вице наоборот (другими словами, вы можете разыграть Func<IDynamicGeneratedModelClass,Object>
до Func<DynamicGeneratedModelClass,Object>
, но не можете разыграть Func<DynamicGeneratedModelClass,Object>
до Func<IDynamicGeneratedModelClass,Object>
).
Чтобы избежать этой проблемы, вместо лямбда-выражения, которое вы генерируете сейчас:
// lambda has "wrong" type Func<DynamicGeneratedModelClass, object>
(DynamicGeneratedModelClass item) => item.SomeProperty
генерирует лямбда-эквивалент, эквивалентный этому:
// lambda now has "correct" type Func<IDynamicGeneratedModelClass, object>
(IDynamicGeneratedModelClass item) => ((DynamicGeneratedModelClass)item).SomeProperty
Я не знаком с библиотекой DynamicExpression
, которую вы использовали для создания лямбды, но это легко сделать с помощью System.Linq.Expression
классов:
var itemType = list.First().GetType();
var propertyName = "SomeProperty";
var parameterExpr = Expression.Parameter(typeof(IDynamicGeneratedModelClass));
var castExpr = Expression.Convert(parameterExpr, itemType);
var propExpr = Expression.Property(castExpr, propertyName);
var lambdaExpr = Expression.Lambda(propExpr, parameterExpr);
// Compiled lambda is now of type Func<IDynamicGeneratedModelClass, object>
Func<IDynamicGeneratedModelClass, object> compiledLambdaFunction = (Func<IDynamicGeneratedModelClass, object>)lambdaExpr.Compile();
var result = list.GroupBy(compiledLambdaFunction);