Home > Net >  Use enum parameter with c# expression
Use enum parameter with c# expression

Time:11-13

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));
  • Related