2
\$\begingroup\$

Here is my generic method for creating linq expression based on field name of a type, operator (as enumerations of operators generated from XSD) and value of field

 private Expression<Func<T, bool>> GetCriteriaPredicate<T>(string fieldName, OperatorRef selectedOperator, string value)
 {
 PropertyDescriptor prop = TypeDescriptor.GetProperties(typeof(GoodsWorksService)).Find(fieldName, true);
 if (prop != null)
 {
 //value as object
 object fieldValue = null;
 //GUID
 if (prop.PropertyType == typeof(Guid?))
 {
 fieldValue = new Guid(value) as Guid?;
 }
 //Integer
 if (prop.PropertyType == typeof(int?) || prop.PropertyType == typeof(int))
 {
 int intValue;
 if (Int32.TryParse(value, out intValue))
 {
 fieldValue = intValue;
 }
 }
 //DateTime
 if (prop.PropertyType == typeof(DateTime?) || prop.PropertyType == typeof(DateTime))
 {
 DateTime dateTimeValue;
 if (DateTime.TryParse(value, out dateTimeValue))
 {
 fieldValue = dateTimeValue;
 }
 }
 //String
 if (prop.PropertyType == typeof(string))
 {
 fieldValue = value;
 }
 var parameter = Expression.Parameter(typeof(T));
 switch (selectedOperator)
 {
 // "="
 case OperatorRef.Item:
 { 
 var body = Expression.Equal(Expression.Property(parameter, prop.Name), Expression.Constant(fieldValue, prop.PropertyType));
 return Expression.Lambda<Func<T, bool>>(body, parameter);
 }
 // "!="
 case OperatorRef.Item1:
 // "<>"
 case OperatorRef.Item2:
 { 
 var body = Expression.NotEqual(Expression.Property(parameter, prop.Name), Expression.Constant(fieldValue, prop.PropertyType));
 return Expression.Lambda<Func<T, bool>>(body, parameter);
 }
 // "<"
 case OperatorRef.Item3:
 { 
 var body = Expression.LessThan(Expression.Property(parameter, prop.Name), Expression.Constant(fieldValue, prop.PropertyType));
 return Expression.Lambda<Func<T, bool>>(body, parameter);
 }
 // "<="
 case OperatorRef.Item4:
 { 
 var body = Expression.LessThanOrEqual(Expression.Property(parameter, prop.Name), Expression.Constant(fieldValue, prop.PropertyType));
 return Expression.Lambda<Func<T, bool>>(body, parameter);
 }
 // ">"
 case OperatorRef.Item5:
 { 
 var body = Expression.GreaterThan(Expression.Property(parameter, prop.Name), Expression.Constant(fieldValue, prop.PropertyType));
 return Expression.Lambda<Func<T, bool>>(body, parameter);
 }
 // ">="
 case OperatorRef.Item6:
 { 
 var body = Expression.GreaterThanOrEqual(Expression.Property(parameter, prop.Name), Expression.Constant(fieldValue));
 return Expression.Lambda<Func<T, bool>>(body, parameter);
 }
 //By containing string in field
 case OperatorRef.LIKE:
 { 
 MethodInfo contains = typeof(string).GetMethod("Contains");
 var body = Expression.Call(Expression.Property(parameter, prop.Name), contains, Expression.Constant(fieldValue, prop.PropertyType));
 return Expression.Lambda<Func<T, bool>>(body, parameter);
 }
 // по умолчанию - "="
 default:
 { 
 var body = Expression.Equal(Expression.Property(parameter, prop.Name), Expression.Constant(fieldValue, prop.PropertyType));
 return Expression.Lambda<Func<T, bool>>(body, parameter);
 }
 }
 }
 return null;
 }
asked Sep 12, 2016 at 15:35
\$\endgroup\$

1 Answer 1

5
\$\begingroup\$

Avoid nesting where possible.

if (prop != null)
{
}

Should be:

if (prop == null) { return null; }

//GUID
if (prop.PropertyType == typeof(Guid?))
{
 fieldValue = new Guid(value) as Guid?;
}

Use variables instead of comments where possible and makes sense.

 var isGuid = prop.PropertyType == typeof(Guid?);
 if (isGuid)
 {
 fieldValue = new Guid(value) as Guid?;
 }

or

var isInt = prop.PropertyType == typeof(int?) || prop.PropertyType == typeof(int);
if (isInt) {... }

Name your constatnts/enums properly so that you don't have to comment them.

OperatorRef.Item

Should be

OperatorRef.EqualSign

or instead of

OperatorRef.Item1
OperatorRef.Item2

you do

 OperatorRef.NotEqualCSharp
 OperatorRef.NotEqualVB

and so on...


You should create another method that parses/converts the value into the property type and put the ifs there.

answered Sep 12, 2016 at 15:53
\$\endgroup\$
2
  • \$\begingroup\$ Good stuff, though I'd hope if (blah == typeof(Guid)) is obvious enough to not require either comment or variable. \$\endgroup\$ Commented Sep 13, 2016 at 14:08
  • \$\begingroup\$ @eurotrash you're right, if I had only a single if I'd put the short condition inside the it but if I had several ifs with multiple conditions then for the sake of consistancy I'd probably create a helper variable anyway ;-) \$\endgroup\$ Commented Sep 13, 2016 at 14:14

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.