C# Language
जेनेरिक लैंबडा क्वेरी बिल्डर
खोज…
टिप्पणियों
वर्ग को ExpressionBuilder
कहा जाता है। इसके तीन गुण हैं:
private static readonly MethodInfo ContainsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
private static readonly MethodInfo StartsWithMethod = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
private static readonly MethodInfo EndsWithMethod = typeof(string).GetMethod("EndsWith", new[] { typeof(string) });
एक सार्वजनिक विधि GetExpression
जो GetExpression
अभिव्यक्ति लौटाता है, और तीन निजी तरीके:
-
Expression GetExpression<T>
-
BinaryExpression GetExpression<T>
-
ConstantExpression GetConstant
सभी तरीकों को उदाहरणों में विवरण में समझाया गया है।
QueryFilter वर्ग
यह वर्ग विधेय फिल्टर मूल्यों को समर्पित करता है।
public class QueryFilter
{
public string PropertyName { get; set; }
public string Value { get; set; }
public Operator Operator { get; set; }
// In the query {a => a.Name.Equals("Pedro")}
// Property name to filter - propertyName = "Name"
// Filter value - value = "Pedro"
// Operation to perform - operation = enum Operator.Equals
public QueryFilter(string propertyName, string value, Operator operatorValue)
{
PropertyName = propertyName;
Value = value;
Operator = operatorValue;
}
}
संचालन मान रखने के लिए Enum:
public enum Operator
{
Contains,
GreaterThan,
GreaterThanOrEqual,
LessThan,
LessThanOrEqualTo,
StartsWith,
EndsWith,
Equals,
NotEqual
}
GetExpression विधि
public static Expression<Func<T, bool>> GetExpression<T>(IList<QueryFilter> filters)
{
Expression exp = null;
// Represents a named parameter expression. {parm => parm.Name.Equals()}, it is the param part
// To create a ParameterExpression need the type of the entity that the query is against an a name
// The type is possible to find with the generic T and the name is fixed parm
ParameterExpression param = Expression.Parameter(typeof(T), "parm");
// It is good parctice never trust in the client, so it is wise to validate.
if (filters.Count == 0)
return null;
// The expression creation differ if there is one, two or more filters.
if (filters.Count != 1)
{
if (filters.Count == 2)
// It is result from direct call.
// For simplicity sake the private overloads will be explained in another example.
exp = GetExpression<T>(param, filters[0], filters[1]);
else
{
// As there is no method for more than two filters,
// I iterate through all the filters and put I in the query two at a time
while (filters.Count > 0)
{
// Retreive the first two filters
var f1 = filters[0];
var f2 = filters[1];
// To build a expression with a conditional AND operation that evaluates
// the second operand only if the first operand evaluates to true.
// It needed to use the BinaryExpression a Expression derived class
// That has the AndAlso method that join two expression together
exp = exp == null ? GetExpression<T>(param, filters[0], filters[1]) : Expression.AndAlso(exp, GetExpression<T>(param, filters[0], filters[1]));
// Remove the two just used filters, for the method in the next iteration finds the next filters
filters.Remove(f1);
filters.Remove(f2);
// If it is that last filter, add the last one and remove it
if (filters.Count == 1)
{
exp = Expression.AndAlso(exp, GetExpression<T>(param, filters[0]));
filters.RemoveAt(0);
}
}
}
}
else
// It is result from direct call.
exp = GetExpression<T>(param, filters[0]);
// converts the Expression into Lambda and retuns the query
return Expression.Lambda<Func<T, bool>>(exp, param);
}
GetExpression निजी अधिभार
एक फिल्टर के लिए:
यहां वह जगह है जहां क्वेरी बनाई गई है, यह एक अभिव्यक्ति पैरामीटर और एक फिल्टर प्राप्त करता है।
private static Expression GetExpression<T>(ParameterExpression param, QueryFilter queryFilter)
{
// Represents accessing a field or property, so here we are accessing for example:
// the property "Name" of the entity
MemberExpression member = Expression.Property(param, queryFilter.PropertyName);
//Represents an expression that has a constant value, so here we are accessing for example:
// the values of the Property "Name".
// Also for clarity sake the GetConstant will be explained in another example.
ConstantExpression constant = GetConstant(member.Type, queryFilter.Value);
// With these two, now I can build the expression
// every operator has it one way to call, so the switch will do.
switch (queryFilter.Operator)
{
case Operator.Equals:
return Expression.Equal(member, constant);
case Operator.Contains:
return Expression.Call(member, ContainsMethod, constant);
case Operator.GreaterThan:
return Expression.GreaterThan(member, constant);
case Operator.GreaterThanOrEqual:
return Expression.GreaterThanOrEqual(member, constant);
case Operator.LessThan:
return Expression.LessThan(member, constant);
case Operator.LessThanOrEqualTo:
return Expression.LessThanOrEqual(member, constant);
case Operator.StartsWith:
return Expression.Call(member, StartsWithMethod, constant);
case Operator.EndsWith:
return Expression.Call(member, EndsWithMethod, constant);
}
return null;
}
दो फिल्टर के लिए:
यह साधारण एक्सप्रेशन के बजाय बाइनरी एक्सप्रेशन उदाहरण देता है।
private static BinaryExpression GetExpression<T>(ParameterExpression param, QueryFilter filter1, QueryFilter filter2)
{
// Built two separated expression and join them after.
Expression result1 = GetExpression<T>(param, filter1);
Expression result2 = GetExpression<T>(param, filter2);
return Expression.AndAlso(result1, result2);
}
कॉन्स्टेंट एक्सप्रेशन विधि
ConstantExpression
एक ही प्रकार का MemberExpression
होना चाहिए। इस उदाहरण में मान एक स्ट्रिंग है, जिसे ConstantExpression
उदाहरण बनाने से पहले परिवर्तित किया जाता है।
private static ConstantExpression GetConstant(Type type, string value)
{
// Discover the type, convert it, and create ConstantExpression
ConstantExpression constant = null;
if (type == typeof(int))
{
int num;
int.TryParse(value, out num);
constant = Expression.Constant(num);
}
else if(type == typeof(string))
{
constant = Expression.Constant(value);
}
else if (type == typeof(DateTime))
{
DateTime date;
DateTime.TryParse(value, out date);
constant = Expression.Constant(date);
}
else if (type == typeof(bool))
{
bool flag;
if (bool.TryParse(value, out flag))
{
flag = true;
}
constant = Expression.Constant(flag);
}
else if (type == typeof(decimal))
{
decimal number;
decimal.TryParse(value, out number);
constant = Expression.Constant(number);
}
return constant;
}
प्रयोग
संग्रह फ़िल्टर = नई सूची (); QueryFilter फ़िल्टर = नया QueryFilter ("नाम", "बर्गर", संचालक। SartsWith); filters.Add (फिल्टर);
Expression<Func<Food, bool>> query = ExpressionBuilder.GetExpression<Food>(filters);
इस मामले में, यह खाद्य इकाई के खिलाफ एक क्वेरी है, जो सभी खाद्य पदार्थों को ढूंढना चाहते हैं जो नाम में "बर्गर" से शुरू होते हैं।
आउटपुट:
query = {parm => a.parm.StartsWith("Burger")}
Expression<Func<T, bool>> GetExpression<T>(IList<QueryFilter> filters)