Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to map Expression<Func<TEntity, bool>> to Expression<Func<TDbEntity, bool>>

How can I map

from: Expression<Func<TEntity, bool>> to: Expression<Func<TDbEntity, bool>>

where TEntity: class, new() and TDbEntity: class, new()

TEntity is from Domain and TDbEntity is from Infrastructure layer, but have same properties.

It is possible?

like image 844
Omar Amalfi Avatar asked Mar 20 '17 11:03

Omar Amalfi


1 Answers

For relatively simple cases (and I guess in your case expressions are simple) you can use ExpressionVisitor with only a couple of overrides. For example:

public static class ExpressionExtensions {
    public static Expression<Func<TTo, bool>> ReplaceParameter<TFrom, TTo>(this Expression<Func<TFrom, bool>> target) {
        return (Expression<Func<TTo, bool>>) new WhereReplacerVisitor<TFrom, TTo>().Visit(target);
    }
    private class WhereReplacerVisitor<TFrom, TTo> : ExpressionVisitor {
        private readonly ParameterExpression _parameter = Expression.Parameter(typeof(TTo), "c");

        protected override Expression VisitLambda<T>(Expression<T> node) {
            // replace parameter here
            return Expression.Lambda(Visit(node.Body), _parameter);
        }            

        protected override Expression VisitMember(MemberExpression node) {
            // replace parameter member access with new type
            if (node.Member.DeclaringType == typeof(TFrom) && node.Expression is ParameterExpression) {
                return Expression.PropertyOrField(_parameter, node.Member.Name);
            }
            return base.VisitMember(node);
        }
    }
}

Usage is:

Expression<Func<ErrorModel, bool>> where = (c) => c.Created <= DateTime.UtcNow && c.ErrorCode == "code";
var replaced = where.ReplaceParameter<ErrorModel, Error>();
like image 55
Evk Avatar answered Oct 01 '22 22:10

Evk