c# convert predicate between each other

Viewed 3485

I'm developing and multi-tier application solution and my solution looks like this

  • Business.DomainObject
  • Business.Process (* Actual business layer)
  • Data.Mapper
  • Data.Repository
  • Data.Sql.Entity (* Actual data layer that has .dbml file)

My Business.Process project (business layer) is only knows Business.DomainObject and Data.Repository projects, so doesn't know and not in relationship with Data.Sql.Entity project
I'm sending business (domain) objects to repository and do mapping inside this project, then I'm doing CRUD process inside repository layer with relationship data layers.

My traditional domain object is like this, it has only properties

public class UserBO
{
public string Email { get; set; }
public string Username { get; set; }
public string Password { get; set; }
}

My business layer class is like this,

Repository r = new UserRepository();
r.Insert(myUserDomainObject);


Everything is OK, but I have some problems about my "predicate" queries. I have a method in my repository interface

bool IsExists(Expression<Func<BusinessObject,bool>> predicate);

and use it in my business layer like this;

Repository r = new UserRepository(); <br/>
r.IsExists(p => p.Email.Equals("email address"));

as you can see, its parameter is "business object", but my actual repository (that connects with database) using "dataobject" that is inside my dbml file.

    public override bool IsExists(Expression<Func<DataObject, bool>> predicate){
return _table.Where(predicate).Any();
}

I want convert this two predicate, for example I'll send UserBO and convert to UserDataObject

how can i do that?

4 Answers

giving credit to @Markus, here is a generic converter class...

internal class ExpressionConverter<TInput, TOutput> : ExpressionVisitor
{
    public Expression<Func<TOutput, bool>> Convert(Expression<Func<TInput, bool>> expression)
    {
        return (Expression<Func<TOutput, bool>>)Visit(expression);
    }

    private ParameterExpression replaceParam;

    protected override Expression VisitLambda<T>(Expression<T> node)
    {
        if (typeof(T) == typeof(Func<TInput, bool>))
        {
            replaceParam = Expression.Parameter(typeof(TOutput), "p");
            return Expression.Lambda<Func<TOutput, bool>>(Visit(node.Body), replaceParam);
        }
        return base.VisitLambda<T>(node);
    }

    protected override Expression VisitParameter(ParameterExpression node)
    {
        if (node.Type == typeof(TInput))
            return replaceParam;
        return base.VisitParameter(node);
    }

    protected override Expression VisitMember(MemberExpression node)
    {
        if (node.Member.DeclaringType == typeof(TInput))
        {
            var member = typeof(TOutput).GetMember(node.Member.Name, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance).FirstOrDefault();
            if (member == null)
                throw new InvalidOperationException("Cannot identify corresponding member of DataObject");
            return Expression.MakeMemberAccess(Visit(node.Expression), member);
        }
        return base.VisitMember(node);
    }
}
Related