Reputation: 665
Following my own question it has occured to me that I now need to invoke the same service and the same method by passing an Expression<Func<T, object>>
to my method. Here is the method definition:
IList<T> List(params Expression<Func<T, object>>[] includeProperties);
Here is the code I have right now:
//Get generic type
var entityRelationType = typeof(Applicant).Assembly.GetType(string.Format("Permet.BackEnd.ETL.Domain.Models.{0}", tableRelation.RelationEntityName));
//create service that will receive the generic type
var definitionIService = typeof(IService<>).MakeGenericType(entityRelationType);
//instantiate the service using Unity (todo: fix singleton)
var serviceInstance = UnitySingleton.Container.Resolve(definitionIService, "");
//create the argument for the method that we invoke
var paramsType =
typeof(Expression<>).MakeGenericType(typeof(Func<,>)
.MakeGenericType(entityRelationType, typeof(object))).MakeArrayType();
#region Get Dynamic Data
ParameterExpression relationParameter = Expression.Parameter(entityRelationType, "");
//build the parameter that we want to pass to the method (Expression<Func<T, object>>
var include =
Expression.Lambda(
Expression.Property(relationParameter, tableRelation.NaviguationProprietyName),
relationParameter
);
dynamic datas = constructedIService
.GetMethod("List", new Type[] { paramsType }).Invoke(serviceInstance, new object[] { include });
The include successfully creates my lambda expression (Param_0 => Param_0.Groupings) which I believed would be my Expression<Func<T, object>>
. However, since Param_0.Groupings is actually an IList, I get an exception:
Object of type 'System.Linq.Expressions.Expression
1[System.Func
2[Permet.BackEnd.ETL.Domain.Models.CLLI,System.Collections.Generic.IList1[Permet.BackEnd.ETL.Domain.Models.Grouping]]]' cannot be converted to type 'System.Linq.Expressions.Expression
1[System.Func`2[Permet.BackEnd.ETL.Domain.Models.CLLI,System.Object]][]'.
Which basically means that my Expression<Func<CLLI, IList<Grouping>>>
cannot be use in my method which expects a Expression<Func<CLLI, object>>
.
If I actually call my service directly doing:
IService<CLLI> clliService = new Service<CLLI>();
clliService.List(clli => clli.Groupings);
It works.
How would I go around this issue? Isn't an IList an object?
Upvotes: 2
Views: 1772
Reputation: 144126
The problem is that Expression<T>
is invariant, so even if you have a type T
which can be assigned to type U
, that doesn't mean that Expression<T>
can be assigned to Expression<U>
. In your case, T
is Func<CLI, IList<Grouping>>
and U
is Func<CLLI, object>
.
I think the only solution is to create a function to wrap a given expression in an Expression<Func<T, object>>
which delegates to the inner expression and casts the result to object
:
public static Expression<Func<T, object>> ConvertResult<T, TOut>(Expression<Func<T, TOut>> expr)
{
var paramExpr = Expression.Parameter(typeof(T));
var invokeExpr = Expression.Invoke(expr, paramExpr);
var castExpr = Expression.Convert(invokeExpr, typeof(object));
return Expression.Lambda<Func<T, object>>(castExpr, paramExpr);
}
Upvotes: 1