如何创建对返回布尔值的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 forString
,即使在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;
}