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;
    }
\$\endgroup\$
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.

\$\endgroup\$
  • \$\begingroup\$ Good stuff, though I'd hope if (blah == typeof(Guid)) is obvious enough to not require either comment or variable. \$\endgroup\$ – 404 Sep 13 '16 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\$ – t3chb0t Sep 13 '16 at 14:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.