I'd like to have an expression that converts an entity item into a DTO object and use an additional parameter to select which data should be copied into the DTO. This works very well until I add the parameter:
private static readonly Expression<Func<User, UserDataGroupType, UserData>> s_entityToDataExpression = (User entity, UserDataGroupType dataGroups) => new UserData
{
Id = entity.Id,
State = entity.State,
Role = entity.Role.ToData(),
BaseData = dataGroups.HasFlag(UserDataGroupType.Base) ? entity.ToDataBase() : null,
BirthData = dataGroups.HasFlag(UserDataGroupType.Birth) ? entity.ToDataBirth() : null,
AddressData = dataGroups.HasFlag(UserDataGroupType.Address) ? entity.ToDataAddress() : null,
ExtendedData = dataGroups.HasFlag(UserDataGroupType.Extended) ? entity.ToDataExtended() : null,
};
private static readonly Func<User, UserDataGroupType, UserData> s_entityToDataDelegate = s_entityToDataExpression.Compile();
public static UserData ToData(this User entity, UserDataGroupType dataGroups) => s_entityToDataDelegate(entity, dataGroups);
public static IQueryable<UserData> ToData(this IQueryable<User> queryable, UserDataGroupType dataGroups) => queryable.Select(s_entityToDataExpression);
It complains at the parameter of the the last line:
cannot convert from 'System.Linq.Expressions.Expression<System.Func<Entities.User, Enums.UserDataGroupType, UserData>>' to 'System.Linq.Expressions.Expression<System.Func<Entities.User, int, UserData>>'
Where is that int coming from? UserDataGroupType is a byte type flag enum.
Update
After the modifications suggested by @guru-stron the working code looks like this:
private static Expression<Func<User, UserData>> GetToDataExpression(UserDataGroupType dataGroups) => (entity) => new UserData {...}
public static IQueryable<UserData> ToData(this IQueryable<User> queryable, UserDataGroupType dataGroups) => queryable.Select(GetToDataExpression(dataGroups));
CodePudding user response:
Queryable.Select
has 2 overloads with Func
's with one and two parameters -
Select<TSource,TResult>(IQueryable<TSource>, Expression<Func<TSource,Int32,TResult>>)
Select<TSource,TResult>(IQueryable<TSource>, Expression<Func<TSource,TResult>>)
The first one representing the expression like .Select((item, index) => ...)
, your s_entityToDataExpression
represents a Func
requiring 2 parameters so compiler tries to cast it to Expression<System.Func<Entities.User, int, UserData>>
, which is not possible.
It looks like you need to change your code to something like:
private static Expression<Func<User, UserData>> GetExpression(UserDataGroupType dataGroups) => (User entity, UserDataGroupType ) => new UserData
{
Id = entity.Id,
State = entity.State,
Role = entity.Role.ToData(),
BaseData = dataGroups.HasFlag(UserDataGroupType.Base) ? entity.ToDataBase() : null,
BirthData = dataGroups.HasFlag(UserDataGroupType.Birth) ? entity.ToDataBirth() : null,
AddressData = dataGroups.HasFlag(UserDataGroupType.Address) ? entity.ToDataAddress() : null,
ExtendedData = dataGroups.HasFlag(UserDataGroupType.Extended) ? entity.ToDataExtended() : null,
};
public static IQueryable<UserData> ToData(this IQueryable<User> queryable, UserDataGroupType dataGroups)
=> queryable.Select(GetExpression(dataGroups));