✅ AutoMapper and Expression
So how do i create map for Expression<Func<T,bool>> to Expression<Func<TDto,bool>> for example
34 Replies
Why would you want to map that?
Automapper, generally, is useful mostly for simple mappings
Mapping expressions seems way out of it's scope
For example you have getAll(Expression) in your repository
that repository is working with T
Now we have Commands and handlers
and they work with TDto
So handler get Expression<Func<TDto,bool>>
Yeah, so you map from
T
to TDto
but repository needs Expression<Func<T,bool>>
or some such
You map the result, not the expression
mhm, i have expression that i get from request, handler gets it and that expresion is Expression<Func<TDto,bool>>, now if i want to call repository i need Expression<Func<T,bool>>
So the only way is to map that
That seems way overengineered for my liking, I'm already lost lol
or is there way to change expression just that T part
I just inject
DbContext
into my query handlers and donei would do that too yes, but arhitectures and stuff
I dont like it either
A.k.a. "writing code for the sake of writing code"
Im writing mathematicaly correct code xD
Yeah, sorry, I've never seen expressions being mapped with automapper
I barely use automapper in the first place
I didnt even know i can do that
In my eyes, it's something wrong with your architecture if you need to map expressions
but it seems like its possible
I mean, there is other ways to do that, but its way to harder, this is lazy option
i mean if we look at filtrering data
Expressions are best
Yeah
I really cant have 100 handlers for that
So you pass a predicate that takes a
T
filter for adress
You never map it to another expression
Thats cheating
You just map the result of the filtering
how
Repository will broke then
so if i got in request Expression<Func<TDto,bool>>
and mt rep need Expression<Func<T,bool>>
i cant just change rep to get Expression<Func<TDto,bool>>
I guess you could do the filtering later...?
Wdym by that
So
the_expression
can be <TDto, bool>
lets look that this way
hanlder prepare the expresion bla bla
and in repository i just .Where(the_expression) // here it's a collection of TDto
.ToListAsync();\
I think i need to know how to manipulate expressions
If i can manipulate expression to go from T to Tdto
thats just one of parameters
who knows, i guess it will be never forgoten bettle
I'd say you're much better off mapping the type first, then using the expression
i mapped that way back
but need the expressions to
In that case, yeah, I've no clue
Good luck and mercy on your soul
And my condolences that you have to do all that
Thanks, i guss thats the best way to learn something
the more i look around the more i found out
if you are intrested in solution:
public class ExpressionManipulator
{
public Expression<Func<T, bool>> ConvertToTExpression(Expression<Func<TDto, bool>> sourceExpression)
{
var parameter = Expression.Parameter(typeof(T), sourceExpression.Parameters[0].Name);
var body = new TExpressionVisitor(parameter).Visit(sourceExpression.Body);
var TExpression= Expression.Lambda<Func<T, bool>>(body, parameter);
return TExpression;
}
private class TExpressionVisitor : ExpressionVisitor
{
private readonly ParameterExpression _parameterExpression;
public TExpressionVisitor(ParameterExpression parameterExpression)
{
_parameterExpression = parameterExpression;
}
protected override Expression VisitParameter(ParameterExpression node)
{
return _parameterExpression;
}
protected override Expression VisitMember(MemberExpression node)
{
if (node.Member.DeclaringType == typeof(TDto))
{
var memberName = node.Member.Name;
var targetMember = typeof(T).GetProperty(memberName);
if (targetMember != null)
{
return Expression.MakeMemberAccess(_parameterExpression, targetMember);
}
}
return base.VisitMember(node);
}
}
}
I'm actually impressed a solution exists lol
And it doesn't even seem to involve reflections or
unsafe
blocks!i know i need to manipulate expression
so i guess i did it
thats it for next month, im not doing something like this agian