Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7955307
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 4, 20262026-06-04T03:41:05+00:00 2026-06-04T03:41:05+00:00

inspired by this answer I’m trying to map a property on a model class

  • 0

inspired by this answer I’m trying to map a property on a model class to an expression based on the actual entity.
These are the two classes involved:

public class Customer
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Id { get; set; }
    public DateTime? BirthDate { get; set; }
    public int CustomerTypeId { get; set; }
}

public class CustomerModel
{
    ...
    public bool HasEvenId { get; set; }
}

An example of a possible expression I’d like to convert is:

Expression<Func<CustomerModel, bool>> from = model => model.HasEvenId;
Expression<Func<Customer, bool>> to = entity => ((entity.Id % 2) == 0);

The problem is that I have to expose an OData endpoint via ASP.NET WebAPI but I need to make some operations on the entities before I can them, hence the need of a model class and the need to translate the expression based on the model that I could receive as an OData query in an expression based on the entity, that I would use to query EF4.

This is where I got so far:

private static readonly Dictionary<Expression, Expression> Mappings = GetMappings();

private static Dictionary<Expression, Expression> GetMappings()
{
    var mappings = new Dictionary<Expression, Expression>();

    var mapping = GetMappingFor((CustomerModel model) => model.HasEvenId, (Customer customer) => (customer.Id%2) == 0);
    mappings.Add(mapping.Item1, mapping.Item2);

    return mappings;
}

private static Tuple<Expression, Expression> GetMappingFor<TFrom, TTo, TValue>(Expression<Func<TFrom, TValue>> fromExpression, Expression<Func<TTo, TValue>> toExpression)
{
    MemberExpression fromMemberExpression = (MemberExpression) fromExpression.Body;
    return Tuple.Create<Expression, Expression>(fromMemberExpression, toExpression);
}

public static Expression<Func<TTo, bool>> Translate<TFrom, TTo>(Expression<Func<TFrom, bool>> expression, Dictionary<Expression, Expression> mappings = null)
{
    if (expression == null)
        return null;

    string parameterName = expression.Parameters[0].Name;

    parameterName = string.IsNullOrWhiteSpace(parameterName) ? "p" : parameterName;

    var param = Expression.Parameter(typeof(TTo), parameterName);
    var subst = new Dictionary<Expression, Expression> { { expression.Parameters[0], param } };
    ParameterChangeVisitor parameterChange = new ParameterChangeVisitor(parameterName);
    if (mappings != null)
        foreach (var mapp in mappings)
            subst.Add(mapp.Key, parameterChange.Visit(mapp.Value));

    var visitor = new TypeChangeVisitor(typeof(TFrom), typeof(TTo), subst);
    return Expression.Lambda<Func<TTo, bool>>(visitor.Visit(expression.Body), param);
}

public IQueryable<CustomerModel> Get()
{
    var filterExtractor = new ODataFilterExtractor<CustomerModel>();
    Expression<Func<CustomerModel, bool>> expression = filterExtractor.Extract(Request);
    Expression<Func<Customer, bool>> translatedExpression = Translate<CustomerModel, Customer>(expression, Mappings);

    IQueryable<Customer> query = _context.Customers;

    if (translatedExpression != null)
        query = query.Where(translatedExpression);

    var finalQuery = from item in query.AsEnumerable() 
                     select new CustomerModel()
                        {
                            FirstName = item.FirstName, 
                            LastName = item.LastName, 
                            Id = item.Id, 
                            BirthDate = item.BirthDate, 
                            CustomerTypeId = item.CustomerTypeId,
                            HasEvenId = (item.Id % 2 ) == 0
                        };

    return finalQuery.AsQueryable();
}

where:

  • ODataFilterExtractor is a class that extract the $filter expression from the RequestMessage we receive;
  • ParameterChangeVisitor just changes all the ParameterExpression to a new one having the provided string as parameter name;

In addition, I changed the VisitMember method of the answer linked above in this way:

protected override Expression VisitMember(MemberExpression node)
{
    // if we see x.Name on the old type, substitute for new type
    if (node.Member.DeclaringType == _from)
    {
        MemberInfo toMember = _to.GetMember(node.Member.Name, node.Member.MemberType, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).SingleOrDefault();
        if (toMember != null)
        {
            return Expression.MakeMemberAccess(Visit(node.Expression), toMember);
        }
        else
        {
            if (_substitutions.Select(kvp => kvp.Key).OfType<MemberExpression>().Any(me => me.Member.Equals(node.Member)))
            {
                MemberExpression key = _substitutions.Select(kvp => kvp.Key).OfType<MemberExpression>().Single(me => me.Member.Equals(node.Member));
                Expression value = _substitutions[key];

                // What to return here?
                return Expression.Invoke(value);
            }
        }
    }
    return base.VisitMember(node);
}

Thanks for you help.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-04T03:41:06+00:00Added an answer on June 4, 2026 at 3:41 am

    I took the liberty of modifying your code just a hair but this does the trick,

    public class Customer
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int Id { get; set; }
        public DateTime? BirthDate { get; set; }
        public int CustomerTypeId { get; set; }
    }
    
    public class CustomerModel
    {
        public string FullName { get; set; }
        public bool HasEvenId { get; set; }
    }
    
    sealed class AToBConverter<TA, TB> : ExpressionVisitor
    {
        private readonly Dictionary<ParameterExpression, ParameterExpression> _parameters = new Dictionary<ParameterExpression, ParameterExpression>();
        private readonly Dictionary<MemberInfo, LambdaExpression> _mappings;
    
        protected override Expression VisitParameter(ParameterExpression node)
        {
            if (node.Type == typeof(TA))
            {
                ParameterExpression parameter;
                if (!this._parameters.TryGetValue(node, out parameter))
                {
                    this._parameters.Add(node, parameter = Expression.Parameter(typeof(TB), node.Name));
                }
                return parameter;
            }
            return node;
        }
    
        protected override Expression VisitMember(MemberExpression node)
        {
            if (node.Expression == null || node.Expression.Type != typeof(TA))
            {
                return base.VisitMember(node);
            }
            Expression expression = this.Visit(node.Expression);
            if (expression.Type != typeof(TB))
            {
                throw new Exception("Whoops");
            }
            LambdaExpression lambdaExpression;
            if (this._mappings.TryGetValue(node.Member, out lambdaExpression))
            {
                return new SimpleExpressionReplacer(lambdaExpression.Parameters.Single(), expression).Visit(lambdaExpression.Body);
            }
            return Expression.Property(
                expression,
                node.Member.Name
            );
        }
    
        protected override Expression VisitLambda<T>(Expression<T> node)
        {
            return Expression.Lambda(
                this.Visit(node.Body),
                node.Parameters.Select(this.Visit).Cast<ParameterExpression>()
            );
        }
    
        public AToBConverter(Dictionary<MemberInfo, LambdaExpression> mappings)
        {
            this._mappings = mappings;
        }
    }
    
    sealed class SimpleExpressionReplacer : ExpressionVisitor
    {
        private readonly Expression _replacement;
        private readonly Expression _toFind;
    
        public override Expression Visit(Expression node)
        {
            return node == this._toFind ? this._replacement : base.Visit(node);
        }
    
        public SimpleExpressionReplacer(Expression toFind, Expression replacement)
        {
            this._toFind = toFind;
            this._replacement = replacement;
        }
    }
    
    class Program 
    {
        private static Dictionary<MemberInfo, LambdaExpression> GetMappings()
        {
            var mappings = new Dictionary<MemberInfo, LambdaExpression>();
            var mapping = GetMappingFor(model => model.HasEvenId, customer => (customer.Id % 2) == 0);
            mappings.Add(mapping.Item1, mapping.Item2);
            mapping = GetMappingFor(model => model.FullName, customer => customer.FirstName + " " + customer.LastName);
            mappings.Add(mapping.Item1, mapping.Item2);
            return mappings;
        }
    
        private static Tuple<MemberInfo, LambdaExpression> GetMappingFor<TValue>(Expression<Func<CustomerModel, TValue>> fromExpression, Expression<Func<Customer, TValue>> toExpression)
        {
            return Tuple.Create(((MemberExpression)fromExpression.Body).Member, (LambdaExpression)toExpression);
        }
    
        static void Main()
        {
            Expression<Func<CustomerModel, bool>> source = model => model.HasEvenId && model.FullName == "John Smith";
            Expression<Func<Customer, bool>> desiredResult = model => (model.Id % 2) == 0 && (model.FirstName + " " + model.LastName) == "John Smith";
            Expression output = new AToBConverter<CustomerModel, Customer>(GetMappings()).Visit(source);
            Console.WriteLine("The two expressions do {0}match.", desiredResult.ToString() == output.ToString() ? null : "not ");
            Console.ReadLine();
        }
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Inspired by the encoding scheme of the answer to this question , I implemented
Inspired by this answer .. Can you guys point me to something similar--something that
Inspired by this answer about dynamic cast to void* : ... bool eqdc(B* b1,
This question was inspired by this answer to another question, indicating that you can
G'day, Inspired by a comment I made in my answer to this question on
This question is language agnostic but is inspired by these c/c++ questions. How to
This question is inspired by Jon Skeet's answer: Is there a c# equivalent to
This question was inspired by this answer . I've always been of the philosophy
Inspired by this question and answer , how do I create a generic permutations
This is inspired by this question and the comments on one particular answer in

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.