动态LINQ(Lambda表达式)

时间:2023-03-09 07:04:48
动态LINQ(Lambda表达式)

1.准备数据实体

        public class Data
{
public string AccountNO { get; set; } public int Count { get; set; }
}

创建测试数据

 public static List<Data> GetTestData()
{
Data account = new Data
{
AccountNO = "",
Count =
}; Data account1 = new Data
{
AccountNO = "",
Count =
}; Data account2 = new Data
{
AccountNO = "",
Count =
}; Data account3 = new Data
{
AccountNO = "",
Count =
}; Data account4 = new Data
{
AccountNO = "",
Count =
};
var rel = new List<Data>
{
account,
account1,
account2,
account3,
account4
};
return rel;
}

2.准备查询条件实体

        public class Condition
{
[DynamicExpression(Name = "AccountNO", Operator = "Contains")]
public string Name { get; set; } [DynamicExpression(Name = "Count", Operator = ">")]
public int? Age { get; set; }
}

数据实体2个字段一个帐号一个年龄大小

查询条件2个字段一个姓名(Name帐号)一个年龄(Age)

为了确保查询字段和数据字段名字保持一直 引用一个自定义特性 在查询条件的每个字段上面标记

自定义特性包含2个字段一个Name 需要跟数据实体保持一致的名称(注:必须和数据实体的字段对应) Operator 表示运算逻辑符

附自定义实体代码

 [AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, AllowMultiple = true)]
public class DynamicExpressionAttribute : Attribute
{
/// <summary>
/// 名称
/// </summary>
public string Name { get; set; } /// <summary>
/// 运行符号
/// </summary>
public string Operator { get; set; }
}

从查询条件中提取特效值的扩展类

    public static class CustomAttributeExtension<TAttribute>
where TAttribute : Attribute
{
/// <summary>
/// Cache Data
/// </summary>
private static readonly Dictionary<string, TAttribute> Cache = new Dictionary<string, TAttribute>(); /// <summary>
/// 获取CustomAttribute Value
/// </summary>
/// <param name="type">实体对象类型</param>
/// <param name="propertyInfo">实体对象属性信息</param>
/// <returns>返回Attribute的值,没有则返回null</returns>
public static TAttribute GetCustomAttributeValue(Type type, PropertyInfo propertyInfo)
{
var key = BuildKey(type, propertyInfo);
if (!Cache.ContainsKey(key))
{
CacheAttributeValue(type, propertyInfo);
}
return Cache[key];
} /// <summary>
/// 获取CustomAttribute Value
/// </summary>
/// <param name="sourceType">实体对象数据类型</param>
/// <returns>返回Attribute的值,没有则返回null</returns>
public static TAttribute GetCustomAttributeValue(Type sourceType)
{
var key = BuildKey(sourceType, null);
if (!Cache.ContainsKey(key))
{
CacheAttributeValue(sourceType, null);
}
return Cache[key];
} /// <summary>
/// 获取实体类上的特性
/// </summary>
/// <param name="type">实体对象类型</param>
/// <returns>返回Attribute的值,没有则返回null</returns>
private static TAttribute GetClassAttributes(Type type)
{
var attribute = type.GetCustomAttributes(typeof(TAttribute), false).FirstOrDefault();
return (TAttribute)attribute;
} /// <summary>
/// 获取实体属性上的特性
/// </summary>
/// <param name="propertyInfo">属性信息</param>
/// <returns>返回Attribute的值,没有则返回null</returns>
private static TAttribute GetPropertyAttributes(PropertyInfo propertyInfo)
{
var attribute = propertyInfo?.GetCustomAttributes(typeof(TAttribute), false).FirstOrDefault();
return (TAttribute)attribute;
} /// <summary>
/// 缓存Attribute Value
/// <param name="type">实体对象类型</param>
/// <param name="propertyInfo">实体对象属性信息</param>
/// </summary>
private static void CacheAttributeValue(Type type, PropertyInfo propertyInfo)
{
var key = BuildKey(type, propertyInfo);
TAttribute value;
if (propertyInfo == null)
{
value = GetClassAttributes(type);
}
else
{
value = GetPropertyAttributes(propertyInfo);
} lock (key + "_attributeValueLockKey")
{
if (!Cache.ContainsKey(key))
{
Cache[key] = value;
}
}
} /// <summary>
/// 缓存Collection Name Key
/// <param name="type">type</param>
/// <param name="propertyInfo">propertyInfo</param>
/// </summary>
private static string BuildKey(Type type, PropertyInfo propertyInfo)
{
if (string.IsNullOrEmpty(propertyInfo?.Name))
{
return type.FullName;
}
return type.FullName + "." + propertyInfo.Name;
}
}

根据数据和查询条件生成表达式

 public static Func<TResult, bool> GetDynamicExpression<TResult, TCondition>(this IEnumerable<TResult> data, TCondition condtion)
where TResult : class
where TCondition : class
{
Type tConditionType = typeof(TCondition);
Type tResultType = typeof(TResult); Expression totalExpr = Expression.Constant(true);
ParameterExpression param = Expression.Parameter(typeof(TResult), "n");
foreach (PropertyInfo property in tConditionType.GetProperties())
{
string key = property.Name;
object value = property.GetValue(condtion);
if (value != null && value.ToString() != string.Empty)
{
DynamicExpressionAttribute dynamicExpressionAttribute = CustomAttributeExtension<DynamicExpressionAttribute>.GetCustomAttributeValue(tConditionType, property); //等式左边的值
string name = dynamicExpressionAttribute.Name ?? key;
Expression left = Expression.Property(param, tResultType.GetProperty(name));
//等式右边的值
Expression right = Expression.Constant(value); Expression filter;
switch (dynamicExpressionAttribute.Operator)
{
case "!=":
filter = Expression.NotEqual(left, right);
break;
case ">":
filter = Expression.GreaterThan(left, right);
break;
case ">=":
filter = Expression.GreaterThanOrEqual(left, right);
break;
case "<":
filter = Expression.LessThan(left, right);
break;
case "<=":
filter = Expression.LessThanOrEqual(left, right);
break;
case "Contains":
filter = Expression.Call(Expression.Property(param, tResultType.GetProperty(name)), typeof(string).GetMethod("Contains", new [] { typeof(string) }), Expression.Constant(value)); ;
break;
default:
filter = Expression.Equal(left, right);
break;
}
totalExpr = Expression.And(filter, totalExpr);
}
}
var predicate = Expression.Lambda(totalExpr, param);
var dynamic = (Func<TResult, bool>)predicate.Compile();
return dynamic;
}

测试 : (查询帐号包含1的数据)

 public static void Test()
{
var data = GetTestData();
var codition = new Condition { Name = "1"};
var dynamicExpression = GetDynamicExpression(data, codition);
var query1 = data.Where(dynamicExpression);
}