I'd like to streamline my current view model mapping. I currently use Automapper ProjectTo
to create my view model, then call a post mapping method to populate a StatusDescription
string
property from a Status
enum whose value is in another int
property in the view model class, StatusId
.
I found this other answer, but I am not able to get it to work, and am having a hard time understanding what exactly it is doing due to my general lack of experience with expressions.
For reference, here is the expression method (note I had to comment out the defaultValue parameter as I was getting an error An expression tree may not contain a call or invocation that uses optional arguments
:
public static Expression<Func<TSource, String>> CreateEnumToStringExpression<TSource, TMember>(
Expression<Func<TSource, TMember>> memberAccess)//,string defaultValue = ""
{
string defaultValue = "";
var type = typeof(TMember);
if (!type.IsEnum)
{
throw new InvalidOperationException("TMember must be an Enum type");
}
var enumNames = Enum.GetNames(type);
var enumValues = (TMember[])Enum.GetValues(type);
var inner = (Expression)Expression.Constant(defaultValue);
var parameter = memberAccess.Parameters[0];
for (int i = 0; i < enumValues.Length; i++)
{
inner = Expression.Condition(
Expression.Equal(memberAccess.Body, Expression.Constant(enumValues[i])),
Expression.Constant(enumNames[i]),
inner);
}
var expression = Expression.Lambda<Func<TSource, string>>(inner, parameter);
return expression;
}
I am calling it like this:
.ForMember(dest => dest.Status, option =>
option.MapFrom(src =>
EnumHelper.ExpressionHelper
.CreateEnumToStringExpression((ShippingContainerHeader s) => s.StatusId)
))
The error I am getting when I run this is:
LINQ to Entities does not recognize the method 'System.String ToString()' method, and this method cannot be translated into a store expression..
A.) I think I am calling this wrong maybe? Shouldn't I be using the reference to src
in the MapFrom
method call in order to pass the actual value of StatusId
to the expression method?
B.) Seems like there is an issue with the expression generation method as it is producing the ToString()
error. There is not an explicit .ToString()
call in that method, but it must be implied somehow.
C.) Understanding the code: I can follow all of the code within the CreateEnumToStringExpression
method except what the parameter
variable is and the final expression
variable expression statement. Also the generic types I'm confused on...there are a lot of generic types and the call to the method from the linked example doesn't explicitly define any of them.
In Expression<Func<TSource, String>>
I'm pretty sure TSource
is the input, which is an int
. String
is the output, which would be the enum name.
In CreateEnumToStringExpression<TSource, TMember>
and Expression<Func<TSource, TMember>> memberAccess
: TSource
again is int
, TMember
is the enum class type.
But do you not have to explicitly call these out when calling the method? Something like: CreateEnumToStringExpression<int, StatusesEnum>(new Expression<Func<int, ShippingContainerHeader>> { s => s.StatusId })