Section85.1:QueryFilterclass
Thisclassholdspredicatefiltersvalues.
publicclassQueryFilter
{
publicstringPropertyName{get;set;}
publicstringValue{get;set;}
publicOperatorOperator{get;set;}
//Inthequery{a=>a.Name.Equals(“Pedro”)}
//Propertynametofilter-propertyName=”Name”
//Filtervalue-value=”Pedro”
//Operationtoperform-operation=enumOperator.Equals
publicQueryFilter(stringpropertyName,stringvalue,OperatoroperatorValue)
{
PropertyName=propertyName;
Value=value;
Operator=operatorValue;
}
}
Enumtoholdtheoperationsvalues:
publicenumOperator
{
Contains, GreaterThan,
GreaterThanOrEqual,
LessThan,
LessThanOrEqualTo,
StartsWith,EndsWith,
Equals,
NotEqual
}
Section85.2:GetExpressionMethod
publicstaticExpression<Func<T,bool>>GetExpression<T>(IList<QueryFilter>filters)
{
Expressionexp=null;
//Representsanamedparameterexpression.{parm=>parm.Name.Equals()},itistheparampart
//TocreateaParameterExpressionneedthetypeoftheentitythatthequeryisagainstana
name
//ThetypeispossibletofindwiththegenericTandthenameisfixedparm
ParameterExpressionparam=Expression.Parameter(typeof(T),”parm”);
//Itisgoodparcticenevertrustintheclient,soitiswisetovalidate.
if(filters.Count==0)
returnnull;
//Theexpressioncreationdifferifthereisone,twoormorefilters.
if(filters.Count!=1)
{
if(filters.Count==2)
//Itisresultfromdirectcall.
//Forsimplicitysaketheprivateoverloadswillbeexplainedinanotherexample.
exp=GetExpression<T>(param,filters[0],filters[1]);
else
{
//Asthereisnomethodformorethantwofilters,
//IiteratethroughallthefiltersandputIinthequerytwoatatime
while(filters.Count>0)
{
//Retrievethefirsttwofilters
varf1=filters[0];
varf2=filters[1];
//TobuildaexpressionwithaconditionalANDoperationthatevaluates
//thesecondoperandonlyifthefirstoperandevaluatestotrue.
//ItneededtousetheBinaryExpressionaExpressionderivedclass
//ThathastheAndAlsomethodthatjointwoexpressiontogether
exp=exp==null?GetExpression<T>(param, filters[0], filters[1]):
Expression.AndAlso(exp,GetExpression<T>(param, filters[0], filters[1]));
nextfilters
//Removethetwojustusedfilters,forthemethodinthenextiterationfindsthe
filters.Remove(f1); filters.Remove(f2);
//Ifitisthatlastfilter,addthelastoneandremoveit
if(filters.Count==1)
{
exp=Expression.AndAlso(exp,GetExpression<T>(param,filters[0])); filters.RemoveAt(0);
}
}
}
}
else
//Itisresultfromdirectcall.
exp=GetExpression<T>(param,filters[0]);
//convertstheExpressionintoLambdaandretunsthequery
returnExpression.Lambda<Func<T,bool>>(exp,param);
}
Section85.3:GetExpressionPrivateoverload
Forone filter:
Hereiswherethequeryiscreated,itreceivesaexpressionparameterandafilter.
privatestaticExpressionGetExpression<T>(ParameterExpressionparam,QueryFilterqueryFilter)
{
//Representsaccessingafieldorproperty,sohereweareaccessingforexample:
//theproperty“Name”oftheentity
MemberExpressionmember=Expression.Property(param,queryFilter.PropertyName);
//Representsanexpressionthathasaconstantvalue,sohereweareaccessingforexample:
//thevaluesoftheProperty”Name”.
//AlsoforclaritysaketheGetConstantwillbeexplainedinanotherexample.
ConstantExpressionconstant=GetConstant(member.Type,queryFilter.Value);
//Withthesetwo,nowIcanbuildtheexpression
//everyoperatorhasitonewaytocall,sotheswitchwilldo.
switch(queryFilter.Operator)
{
caseOperator.Equals:
returnExpression.Equal(member,constant);
caseOperator.Contains:
returnExpression.Call(member,ContainsMethod,constant);
caseOperator.GreaterThan:
returnExpression.GreaterThan(member,constant);
caseOperator.GreaterThanOrEqual:
returnExpression.GreaterThanOrEqual(member,constant);
caseOperator.LessThan:
returnExpression.LessThan(member,constant);
caseOperator.LessThanOrEqualTo:
returnExpression.LessThanOrEqual(member,constant);
caseOperator.StartsWith:
returnExpression.Call(member,StartsWithMethod,constant);
caseOperator.EndsWith:
returnExpression.Call(member,EndsWithMethod,constant);
}
returnnull;
}
Fortwofilters:
ItreturnstheBinaryExpresioninstanceinsteadofthesimpleExpression.
privatestaticBinaryExpressionGetExpression<T>(ParameterExpressionparam,QueryFilterfilter1, QueryFilterfilter2)
{
//Builttwoseparatedexpressionandjointhemafter.
Expressionresult1=GetExpression<T>(param,filter1);
Expressionresult2=GetExpression<T>(param,filter2);
returnExpression.AndAlso(result1,result2);
}
Section85.4:ConstantExpressionMethod
ConstantExpressionmustbethesametypeoftheMemberExpression.Thevalueinthisexampleisastring,whichis converted before creating the ConstantExpressioninstance.
privatestaticConstantExpressionGetConstant(Typetype,stringvalue)
{
//Discoverthetype,convertit,andcreateConstantExpression
ConstantExpressionconstant=null;
if(type==typeof(int))
{
intnum;
int.TryParse(value,outnum);
constant=Expression.Constant(num);
}
elseif(type==typeof(string))
{
constant=Expression.Constant(value);
}
elseif(type==typeof(DateTime))
{
DateTimedate;
DateTime.TryParse(value,outdate);
constant=Expression.Constant(date);
}
elseif(type==typeof(bool))
{
boolflag;
if(bool.TryParse(value,outflag))
{
flag=true;
}
constant=Expression.Constant(flag);
}
elseif(type==typeof(decimal))
{
decimalnumber;decimal.TryParse(value,outnumber);
constant=Expression.Constant(number);
}
returnconstant;
}
Collectionfilters=newList();QueryFilterfilter=newQueryFilter(“Name”,”Burger”,Operator.StartsWith); filters.Add(filter);
Expression<Func<Food,bool>>query=ExpressionBuilder.GetExpression<Food>(filters);
Inthiscase,itisaqueryagainsttheFoodentity,thatwanttofindallfoodsthatstartwith”Burger”inthename.
Output:
query={parm=>a.parm.StartsWith(“Burger”)}
Expression<Func<T,bool>>GetExpression<T>(IList<QueryFilter>filters)
About us and this blog
We are a digital marketing company with a focus on helping our customers achieve great results across several key areas.
Request a free quote
We offer professional SEO services that help websites increase their organic search score drastically in order to compete for the highest rankings even when it comes to highly competitive keywords.
Subscribe to our newsletter!
More from our blog
See all postsRecent Posts
- Chapter120:YieldKeyword 20/05/2024
- Chapter119:LockStatement 19/05/2024
- Chapter118:Makingavariablethreadsafe 18/05/2024