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;
}
1 Answer 1
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 if
s there.
-
\$\begingroup\$ Good stuff, though I'd hope
if (blah == typeof(Guid))
is obvious enough to not require either comment or variable. \$\endgroup\$404– 4042016年09月13日 14:08:37 +00:00Commented 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 severalif
s with multiple conditions then for the sake of consistancy I'd probably create a helper variable anyway ;-) \$\endgroup\$t3chb0t– t3chb0t2016年09月13日 14:14:11 +00:00Commented Sep 13, 2016 at 14:14