vendredi 8 mai 2015

How to create C# Reflection to Lambda Expression returning boolean

I have an Specification interface and classes:

public interface ISpecification<TEntity> where TEntity : class, new()
{
    Expression<Func<TEntity, bool>> SatisfiedBy();
}

public abstract class Specification<TEntity> : ISpecification<TEntity> where TEntity : class, new()
{
    public abstract Expression<Func<TEntity, bool>> SatisfiedBy();
    public static Specification<TEntity> operator &(Specification<TEntity> leftSideSpecification, Specification<TEntity> rightSideSpecification)
    {
        return new AndSpecification<TEntity>(leftSideSpecification, rightSideSpecification);
    }
    public static Specification<TEntity> operator |(Specification<TEntity> leftSideSpecification, Specification<TEntity> rightSideSpecification)
    {
        return new OrSpecification<TEntity>(leftSideSpecification, rightSideSpecification);
    }
    public static Specification<TEntity> operator !(Specification<TEntity> specification)
    {
        return new NotSpecification<TEntity>(specification);
    }
    public static bool operator false(Specification<TEntity> specification)
    {
        return false;
    }
    public static bool operator true(Specification<TEntity> specification)
    {
        return true;
    }
}

public class Table1BySpecification: Specification<Table1>
{
    Propiedades Privadas
    Expression<Func<Table1, bool>> _Expression = null;

    public Table1BySpecification(Expression<Func<Table1, bool>> expression)
    {
        this._Expression = expression;
    }

    public override Expression<Func<Table1, bool>> SatisfiedBy()
    {
        return this._Expression;
    }
}

I create a Table1BySpecification so I can run from a generic function...

public IEnumerable<TEntity> GetBySpecification(string propertyName, object propertyValue, propertyOperator ){

    ISpecification<Table1> Specification = new Table1BySpecification(t1 => t1.name == "test_name");          
    context.CreateDbSet<Table1>().Where(Specification.SatisfiedBy())
}

This works fine for Table1 entity, however I'd like to use TEntity instead, and use dynamic specification using reflection. Maybe I could have something like:

public IEnumerable<TEntity> GetBySpecification(string propertyName = "name", object propertyValue = "test_name", string propertyOperator = "==" ){

    var source = typeof(TEntity); 
    var t = Expression.Parameter( source, "t" );
    var sourceProperty = Expression.MakeMemberAccess( arg, source.GetProperty( propertyName ) );
    PropertyInfo propertyField = type.GetProperty(propertyName);
    Type propertyType = propertyField.GetType();

    PropertyInfo[] props = typeof(TEntity).GetProperties();
    foreach (PropertyInfo prop in props)
    {
        var displayAttribute = prop.GetCustomAttributes(false).FirstOrDefault(a => a.GetType() == propertyType);
        if (displayAttribute != null)
        {
            var parameterExpression = Expression.Parameter(typeof(TEntity), "x");
            var memberExpression = Expression.PropertyOrField(parameterExpression, prop.Name);
            var memberExpressionConversion = Expression.Convert(memberExpression, typeof(object));
            var lambda = Expression.Lambda<Func<TEntity, object>>(memberExpressionConversion, parameterExpression);                    
        }
    }

    ISpecification<TEntity> Specification = new EntityByCustomSpecification<TEntity>(***Reflection_Expression***);

    context.CreateDbSet<TEntity>().Where(Specification.SatisfiedBy()),
}

I don't know whether this code can be part of the solution in order to create (Reflection_Expression) at least in regards to propertyName variable. I really can't manage to create (Reflection_Expression) as a lambda Expression and at the end get for that Reflection_Expression the implementation of...

(t1 => t1.name == "test_name")

... when TEntity is t1, propertyName is name, its value propertyValue is "test_name" and the operator propertyOperator is "=="

Any help, please???

Many thanks indeed!





Aucun commentaire:

Enregistrer un commentaire