Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何创建对返回布尔值的Lambda表达式的C#反射_C#_Linq_Generics_Reflection_Expression - Fatal编程技术网

如何创建对返回布尔值的Lambda表达式的C#反射

如何创建对返回布尔值的Lambda表达式的C#反射,c#,linq,generics,reflection,expression,C#,Linq,Generics,Reflection,Expression,我有一个规范接口和类: public interface ISpecification<TEntity> where TEntity : class, new() { Expression<Func<TEntity, bool>> SatisfiedBy(); } public abstract class Specification<TEntity> : ISpecification<TEntity> where TEnti

我有一个规范接口和类:

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;
    }
}
。。。当tenty为t1时,propertyName为name,其值propertyValue为“test_name”,运算符propertyOperator为“=”

需要帮忙吗

非常感谢

给定

public class EntityByCustomSpecification<TEntity> : Specification<TEntity> where TEntity : class, new()
{
    Expression<Func<TEntity, bool>> _Expression = null;

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

    public override Expression<Func<TEntity, bool>> SatisfiedBy()
    {
        return this._Expression;
    }
}
公共类EntityByCustomSpecification:规范,其中tenty:class,new()
{
表达式_Expression=null;
public EntityByCustomSpecification(表达式)
{
这个._表达式=表达式;
}
公共重写表达式sutisfiedby()
{
返回此表达式;
}
}
(不清楚您是否已经拥有)

你想要的是:

public IEnumerable<TEntity> GetBySpecification<TEntity>(object propertyValue, string propertyName = "name", ExpressionType operation = ExpressionType.Equal) where TEntity : class, new()
{
    ParameterExpression par = Expression.Parameter(typeof(TEntity));

    Expression left = Expression.PropertyOrField(par, propertyName);
    Expression right = Expression.Constant(propertyValue, left.Type);

    Expression comparison;

    try
    {
        comparison = Expression.MakeBinary(operation, left, right);
    }
    catch (InvalidOperationException)
    {
        // string case, for example
        Type icomparable = typeof(IComparable<>).MakeGenericType(left.Type);

        if (!left.Type.GetInterfaces().Any(x => x == icomparable))
        {
            throw;
        }

        InterfaceMapping interfaceMap = left.Type.GetInterfaceMap(icomparable);
        int ix = Array.FindIndex(interfaceMap.InterfaceMethods, x => x.Name == "CompareTo");
        MethodInfo method = interfaceMap.TargetMethods[ix];

        // left.CompareTo(right) [operation] 0
        comparison = Expression.MakeBinary(operation, Expression.Call(left, method, right), Expression.Constant(0));
    }

    if (comparison.Type != typeof(bool))
    {
        throw new ArgumentException("operationType");
    }

    Expression<Func<TEntity, bool>> lambda = Expression.Lambda<Func<TEntity, bool>>(comparison, par);

    ISpecification<TEntity> specification = new EntityByCustomSpecification<TEntity>(lambda);

    var result = context.Set<TEntity>().Where(specification.SatisfiedBy());
    return result;
}
public IEnumerable GetBySpecification(对象propertyValue,字符串propertyName=“name”,ExpressionType operation=ExpressionType.Equal),其中TEntity:class,new() { 参数表达式PAL=表达式参数(Type of(TEntity)); Expression left=Expression.PropertyOrField(par,propertyName); 表达式right=表达式.Constant(propertyValue,left.Type); 表达比较; 尝试 { 比较=表达式.MakeBinary(操作,左,右); } 捕获(无效操作异常) { //例如,字符串大小写 类型icomparable=typeof(icomparable).MakeGenericType(left.Type); 如果(!left.Type.GetInterfaces().Any(x=>x==icomparable)) { 投掷; } interfaceMap interfaceMap=left.Type.GetInterfaceMap(icomparable); intix=Array.FindIndex(interfaceMap.InterfaceMethods,x=>x.Name==“CompareTo”); MethodInfo方法=接口映射目标方法[ix]; //左。与(右)比较[操作]0 比较=Expression.MakeBinary(操作,Expression.Call(左,方法,右),Expression.Constant(0)); } if(comparison.Type!=typeof(bool)) { 抛出新的ArgumentException(“operationType”); } 表达式lambda=表达式.lambda(比较,par); ISpecification specification=新实体ByCustomSpecification(λ); var result=context.Set().Where(specification.SatisfiedBy()); 返回结果; } 请注意,为了使其更简单,它不接受
字符串属性运算符
,而是接受
表达式类型
ExpressionType
包含所有比较运算符(
),以及可以忽略的数学运算符(
+
-
…)。您可以轻松编写一个方法,给定
字符串
返回正确的
表达式类型


我已经纠正了一个具有可空类型的错误。我已经通过
IComparable
界面添加了对
string
的支持。

现在,如果我设置operation=“Expression.GreaterThan”并且propertyValue是string类型,那么让比较表达式与字符串一起工作应该是什么样的方式呢。。。。。。。BinaryExpression比较=Expression.MakeBinary(操作,左,右)。。。。。不work@ForumAccount大开关
表达式式操作;开关(stringop)案例“=”:操作=表达式类型。相等;打破case“>=”:operation=ExpressionType。
问题是,像“GreaterThan”这样的运算符类型不适用于字符串或DateTime…@ForumAccount for
String
,即使在LINQ中,执行
x=>x.MyString>=x.MyString
也是无效的。对于
DateTime
我应该已经修复了它。
DateTime
没有问题,但字段可以为空。对于字符串,必须执行
x.MyString.CompareTo(x.MyString)>=0
才能执行
=
比较。@ForumAccount添加了对
字符串的支持。它使用
比较器
(t1 => t1.name == "test_name")
public class EntityByCustomSpecification<TEntity> : Specification<TEntity> where TEntity : class, new()
{
    Expression<Func<TEntity, bool>> _Expression = null;

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

    public override Expression<Func<TEntity, bool>> SatisfiedBy()
    {
        return this._Expression;
    }
}
public IEnumerable<TEntity> GetBySpecification<TEntity>(object propertyValue, string propertyName = "name", ExpressionType operation = ExpressionType.Equal) where TEntity : class, new()
{
    ParameterExpression par = Expression.Parameter(typeof(TEntity));

    Expression left = Expression.PropertyOrField(par, propertyName);
    Expression right = Expression.Constant(propertyValue, left.Type);

    Expression comparison;

    try
    {
        comparison = Expression.MakeBinary(operation, left, right);
    }
    catch (InvalidOperationException)
    {
        // string case, for example
        Type icomparable = typeof(IComparable<>).MakeGenericType(left.Type);

        if (!left.Type.GetInterfaces().Any(x => x == icomparable))
        {
            throw;
        }

        InterfaceMapping interfaceMap = left.Type.GetInterfaceMap(icomparable);
        int ix = Array.FindIndex(interfaceMap.InterfaceMethods, x => x.Name == "CompareTo");
        MethodInfo method = interfaceMap.TargetMethods[ix];

        // left.CompareTo(right) [operation] 0
        comparison = Expression.MakeBinary(operation, Expression.Call(left, method, right), Expression.Constant(0));
    }

    if (comparison.Type != typeof(bool))
    {
        throw new ArgumentException("operationType");
    }

    Expression<Func<TEntity, bool>> lambda = Expression.Lambda<Func<TEntity, bool>>(comparison, par);

    ISpecification<TEntity> specification = new EntityByCustomSpecification<TEntity>(lambda);

    var result = context.Set<TEntity>().Where(specification.SatisfiedBy());
    return result;
}