我有一个自制的库,可以在网格ui elemen中创建用于文件串数据的表达式 这是基本方法:
public static Expression<Func<T, bool>> GetPredicate<T>( String modelPropertyName, SearchType searchType, object data)
查询对象非常简单。基本上,您只需要比较属性名称,运算符和数据。它使用反射为每个操作员创建表达式。
现在我要求扩展此功能.... 您可以看到此方法使用Type T.现在他们希望我更改它并将Type作为参数传递 所以新方法应该是这样的:
public static Expression<Func<object, bool>> GetPredicate(Type T , String modelPropertyName, SearchType searchType, object data)
不知道会反对多少属性。 他们也想要使用&#34;动态&#34;对象和ExpandoObjects。那很糟糕。
我不知道我是否可以在ExpandObject中从运行时获取匿名类型。 我也不知道我是否可以回来
Expression<Func<object, bool>>
并将此表达式应用于动态对象。当然,它不能在linq中用于sql,但即使在linq中它也很难实现。
事实上,他们(从我的团队开始)正在考虑使用词典。
有人能指出我可能会有一些图书馆吗?或者也许我的方式从这个开始?
这是全班(非常有用的BTW)
namespace ###########################
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
public static class PredicateBuilder
{
#region Public Static Methods
/// <summary>
/// This is main Method of this Class It returns predicate
///
/// </summary>
/// <typeparam name="T">Entity Type - Search Where</typeparam>
/// <param name="modelPropertyName">property to compare (compare what)(can be nested property)</param>
/// <param name="searchType">comparation Type (compare how)</param>
/// <param name="data">data to compare (compare to what )</param>
/// <returns>Able to translate to SQl predicate</returns>
public static Expression<Func<T, bool>> GetPredicate<T>(String modelPropertyName, SearchType searchType, object data) where T : class
{
ParameterExpression parameterExp = Expression.Parameter(typeof(T), "t");
MemberExpression member = Expression.PropertyOrField(parameterExp, modelPropertyName.Split('.').First());
// If there are any dots in parram then we have to change expression
foreach (var innerMember in modelPropertyName.Split('.').Skip(1))
{
member = Expression.PropertyOrField(member, innerMember);
}
if (member.Type.BaseType.ToString() == "System.Enum")
{
data = Int32.Parse(data.ToString());
String name = Enum.GetName(member.Type, data);
data = Enum.Parse(member.Type, name, false);
}
else if (searchType != SearchType.IsIn)
{
switch (member.Type.ToString())
{
case "System.Nullable`1[System.Int32]":
data = data.ToString().ToNullableInt32();
break;
case "System.Nullable`1[System.Boolean]":
data = data.ToString().ToNullableBoolean();
break;
case "System.Boolean":
data = Boolean.Parse(data.ToString());
break;
case "System.Nullable`1[System.DateTime]":
data = data.ToString().ToNullableDateTime();
break;
case "System.DateTime":
data = DateTime.Parse(data.ToString());
break;
case "System.Int32":
data = Int32.Parse(data.ToString());
break;
}
}
ConstantExpression valuetoCheck;
if (searchType == SearchType.IsIn)
{
valuetoCheck = Expression.Constant(data, GetListType(member.Type));
}
else
{
valuetoCheck = Expression.Constant(data, member.Type);
}
Expression expression = getExpression<T>(searchType, member, valuetoCheck);
Expression<Func<T, bool>> predicate = Expression.Lambda<Func<T, bool>>(expression, new ParameterExpression[] { parameterExp });
return predicate;
}
private static Expression getExpression<T>(SearchType searchType, MemberExpression member, ConstantExpression valuetoCheck) where T : class
{
Expression expression;
switch (searchType)
{
case SearchType.Equal:
expression = Equals<T>(member, valuetoCheck);
break;
case SearchType.NotEqual:
expression = NotEquals<T>(member, valuetoCheck);
break;
case SearchType.Less:
expression = Less<T>(member, valuetoCheck);
break;
case SearchType.LessOrEqual:
expression = LessOrEqual<T>(member, valuetoCheck);
break;
case SearchType.Greater:
expression = More<T>(member, valuetoCheck);
break;
case SearchType.GreaterOrEqual:
expression = MoreorEqual<T>(member, valuetoCheck);
break;
case SearchType.BeginsWith:
expression = BeginsWith<T>(member, valuetoCheck);
break;
case SearchType.DoesNotBeginWith:
expression = NotBeginsWith<T>(member, valuetoCheck);
break;
case SearchType.IsIn:
expression = IsIn<T>(member, valuetoCheck);
break;
case SearchType.IsNotIn:
expression = NotContains<T>(member, valuetoCheck);
break;
case SearchType.EndsWith:
expression = EndsWith<T>(member, valuetoCheck);
break;
case SearchType.DoesNotEndWith:
expression = NotEndsWith<T>(member, valuetoCheck);
break;
case SearchType.Contains:
expression = Contains<T>(member, valuetoCheck);
break;
case SearchType.DoesNotContain:
expression = NotContains<T>(member, valuetoCheck);
break;
case SearchType.IsNull:
expression = IsNull<T>(member, valuetoCheck);
break;
case SearchType.IsNotNull:
expression = IsNotNull<T>(member, valuetoCheck);
break;
default:
expression = Expression<Func<T, bool>>.Equal(member, valuetoCheck);
break;
}
return expression;
}
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>
(Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
}
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>
(Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
}
public static Expression<Func<T, bool>> False<T>()
{
return f => false;
}
public static Expression<Func<T, bool>> True<T>()
{
return f => true;
}
public static IList CreateList(Type type)
{
Type genericListType = typeof(List<>).MakeGenericType(type);
return ((IList)Activator.CreateInstance(genericListType));
}
public static Type GetListType(Type type)
{
return CreateList(type).GetType();
}
#endregion Public Static Methods
#region predicateExpressions
private static Expression BeginsWith<T>(MemberExpression member, ConstantExpression valuetoCheck)
{
MethodInfo method = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
return Expression<Func<T, bool>>.Call(member, method, valuetoCheck);
}
private static Expression Contains<T>(MemberExpression member, ConstantExpression valuetoCheck)
{
MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
return Expression<Func<T, bool>>.Call(member, method, valuetoCheck);
}
private static Expression IsIn<T>(MemberExpression member, ConstantExpression valuetoCheck)
{
MethodInfo method = GetListType(member.Type).GetMethod("Contains", new[] { member.Type });
return Expression<Func<T, bool>>.Call(valuetoCheck, method, member);
}
private static Expression EndsWith<T>(MemberExpression member, ConstantExpression valuetoCheck)
{
MethodInfo method = typeof(string).GetMethod("EndsWith", new[] { typeof(string) });
return Expression<Func<T, bool>>.Call(member, method, valuetoCheck);
}
private static Expression Equals<T>(MemberExpression member, ConstantExpression valuetoCheck)
{
return Expression<Func<T, bool>>.Equal(member, valuetoCheck);
}
private static Expression IsNotNull<T>(MemberExpression member, ConstantExpression valuetoCheck)
{
return Expression<Func<T, bool>>.NotEqual(member, Expression.Constant(null, member.Type));
}
private static Expression IsNull<T>(MemberExpression member, ConstantExpression valuetoCheck)
{
return Expression<Func<T, bool>>.Equal(member, Expression.Constant(null, member.Type));
}
private static Expression Less<T>(MemberExpression member, ConstantExpression valuetoCheck)
{
return Expression<Func<T, bool>>.LessThan(member, valuetoCheck);
}
private static Expression LessOrEqual<T>(MemberExpression member, ConstantExpression valuetoCheck)
{
return Expression<Func<T, bool>>.LessThanOrEqual(member, valuetoCheck);
}
private static Expression More<T>(MemberExpression member, ConstantExpression valuetoCheck)
{
return Expression<Func<T, bool>>.GreaterThan(member, valuetoCheck);
}
private static Expression MoreorEqual<T>(MemberExpression member, ConstantExpression valuetoCheck)
{
return Expression<Func<T, bool>>.GreaterThanOrEqual(member, valuetoCheck);
}
private static Expression NotBeginsWith<T>(MemberExpression member, ConstantExpression valuetoCheck)
{
MethodInfo method = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
return Expression.Not(Expression<Func<T, bool>>.Call(member, method, valuetoCheck));
}
private static Expression NotContains<T>(MemberExpression member, ConstantExpression valuetoCheck)
{
MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
return Expression.Not(Expression<Func<T, bool>>.Call(member, method, valuetoCheck));
}
private static Expression NotEndsWith<T>(MemberExpression member, ConstantExpression valuetoCheck)
{
MethodInfo method = typeof(string).GetMethod("EndsWith", new[] { typeof(string) });
return Expression.Not(Expression<Func<T, bool>>.Call(member, method, valuetoCheck));
}
private static Expression NotEquals<T>(MemberExpression member, ConstantExpression valuetoCheck)
{
return Expression<Func<T, bool>>.NotEqual(member, valuetoCheck);
}
#endregion predicateExpressions
#region Pivate static
private static Boolean? ToNullableBoolean(this string s)
{
bool i;
if (Boolean.TryParse(s, out i)) return i;
return null;
}
private static DateTime? ToNullableDateTime(this string s)
{
DateTime i;
if (DateTime.TryParse(s, out i)) return i;
return null;
}
private static int? ToNullableInt32(this string s)
{
int i;
if (Int32.TryParse(s, out i)) return i;
return null;
}
#endregion
}
}