LinqExpressionLearn\Linq\ParameterRebinder.cs
using System.Linq.Expressions;
/// <summary>
/// 表达式参数
/// </summary>
public class ParameterRebinder : ExpressionVisitor
{
/// <summary>
/// 参数字典
/// </summary>
private readonly Dictionary<ParameterExpression, ParameterExpression> map;
public ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map)
{
this.map = map ?? new Dictionary<ParameterExpression, ParameterExpression>();
}
/// <summary>
/// 参数替换
/// </summary>
/// <param name="map"></param>
/// <param name="exp"></param>
/// <returns></returns>
public static Expression ReplaceParameters(
Dictionary<ParameterExpression, ParameterExpression> map,
Expression exp
)
{
return new ParameterRebinder(map).Visit(exp);
}
/// <summary>
/// 表达式转换
/// </summary>
/// <param name="p"></param>
/// <returns></returns>
protected override Expression VisitParameter(ParameterExpression p)
{
if (map.TryGetValue(p, out ParameterExpression replacement))
{
p = replacement;
}
return base.VisitParameter(p);
}
}
LinqExpressionLearn\Linq\PredicateBuilder.cs
using System.Linq.Expressions;
/// <summary>
/// Linq动态拼接
/// </summary>
public static class PredicateBuilder
{
/// <summary>
/// True表达式
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static Expression<Func<T, bool>> True<T>()
{
return f => true;
}
/// <summary>
/// False表达式
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static Expression<Func<T, bool>> False<T>()
{
return f => false;
}
/// <summary>
/// 表达式拼接
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="first"></param>
/// <param name="second"></param>
/// <param name="merge"></param>
/// <returns></returns>
public static Expression<T> Compose<T>(
this Expression<T> first,
Expression<T> second,
Func<Expression, Expression, Expression> merge
)
{
// 构建参数映射(从第二个参数到第一个参数)
var map = first
.Parameters.Select((f, i) => new { f, s = second.Parameters[i] })
.ToDictionary(p => p.s, p => p.f);
// 将第二个lambda表达式中的参数替换为第一个lambda中的参数
var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body);
// 将lambda表达式体的组合应用于第一个表达式中的参数
return Expression.Lambda<T>(merge(first.Body, secondBody), first.Parameters);
}
/// <summary>
/// 表达式And拼接
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="first"></param>
/// <param name="second"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> And<T>(
this Expression<Func<T, bool>> first,
Expression<Func<T, bool>> second
)
{
return first.Compose(second, Expression.And);
}
/// <summary>
/// 表达式AndAlso拼接
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="first"></param>
/// <param name="second"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> AndAlso<T>(
this Expression<Func<T, bool>> first,
Expression<Func<T, bool>> second
)
{
return first.Compose(second, Expression.AndAlso);
}
/// <summary>
/// 表达式Or拼接
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="first"></param>
/// <param name="second"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> Or<T>(
this Expression<Func<T, bool>> first,
Expression<Func<T, bool>> second
)
{
return first.Compose(second, Expression.Or);
}
/// <summary>
/// 表达式OrElse拼接
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="first"></param>
/// <param name="second"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> OrElse<T>(
this Expression<Func<T, bool>> first,
Expression<Func<T, bool>> second
)
{
return first.Compose(second, Expression.OrElse);
}
}
LinqExpressionLearn\EleTodo.cs
/// <summary>
/// todo状态
/// </summary>
public enum TodoStatus
{
/// <summary>
/// 未做
/// </summary>
Pending,
/// <summary>
/// 已做
/// </summary>
Completed,
}
public class EleTodo
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Remark { get; set; }
public TodoStatus Status { get; set; }
}
LinqExpressionLearn\global.json
{
"sdk": {
"version": "8.0.300"
}
}
LinqExpressionLearn\ISpecification.cs
using System.Linq.Expressions;
/// <summary>
/// 规约接口
/// </summary>
/// <typeparam name="T"></typeparam>
public interface ISpecification<T>
{
/// <summary>
/// 用来验证模型是否满足规约要求
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
bool IsSatisfiedBy(T obj);
/// <summary>
/// 获取表示当前规约的LINQ表达式。
/// </summary>
/// <returns></returns>
Expression<Func<T, bool>> ToExpression();
}
LinqExpressionLearn\LinqExpressionLearn.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
LinqExpressionLearn\LinqExpressionLearn.sln
LinqExpressionLearn\Program.cs
class Program
{
static void Main(string[] args)
{
// 创建一些示例待办事项
var todos = new List<EleTodo>
{
new EleTodo { Id = Guid.NewGuid(), Name = "买牛奶", Remark = "超市", Status = TodoStatus.Pending },
new EleTodo { Id = Guid.NewGuid(), Name = "买面包", Remark = "便利店", Status = TodoStatus.Completed },
new EleTodo { Id = Guid.NewGuid(), Name = "买鸡蛋", Remark = "超市", Status = TodoStatus.Pending },
new EleTodo { Id = Guid.NewGuid(), Name = "买面包", Remark = "超市", Status = TodoStatus.Pending }
};
// 创建 TodoAppService 实例
var todoAppService = new TodoAppService(todos.AsEnumerable());
// 使用规约来过滤待办事项
var filteredTodos = todoAppService.FilterTodos("买面包");
// 输出过滤后的待办事项
foreach (var todo in filteredTodos)
{
Console.WriteLine($"ID: {todo.Id}, Name: {todo.Name}, Remark: {todo.Remark}, Status: {todo.Status}");
}
}
}
LinqExpressionLearn\Specification.cs
using System.Linq.Expressions;
/// <summary>
/// 规约
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class Specification<T> : ISpecification<T>
{
/// <summary>
/// 用来验证模型是否满足规约要求
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public virtual bool IsSatisfiedBy(T obj)
{
return ToExpression().Compile()(obj);
}
/// <summary>
/// 获取表示当前规范的LINQ表达式
/// </summary>
/// <returns></returns>
public abstract Expression<Func<T, bool>> ToExpression();
/// <summary>
/// 将规范隐式转换为表达式。
/// </summary>
/// <param name="specification"></param>
public static implicit operator Expression<Func<T, bool>>(Specification<T> specification)
{
return specification.ToExpression();
}
}
LinqExpressionLearn\TodoAppService.cs
public class TodoAppService
{
private readonly IEnumerable<EleTodo> _todos;
public TodoAppService(IEnumerable<EleTodo> todos)
{
_todos = todos;
}
public IEnumerable<EleTodo> FilterTodos(string? name, string? remark = null, TodoStatus? status =null)
{
var specification = new TodoNameRemarkStatusFiltereSpecification(name, remark, status);
var filteredTodos = _todos.Where(specification.ToExpression().Compile()).ToList();
return filteredTodos;
}
}
LinqExpressionLearn\TodoNameRemarkStatusFiltereSpecification.cs
using System.Linq.Expressions;
public class TodoNameRemarkStatusFiltereSpecification : Specification<EleTodo>
{
private string? _name;
private string? _remark;
private TodoStatus? _status;
public TodoNameRemarkStatusFiltereSpecification(string? name, string? remark, TodoStatus? status)
{
_name = name;
_remark = remark;
_status = status;
}
public override Expression<Func<EleTodo, bool>> ToExpression()
{
Expression<Func<EleTodo, bool>> filter = PredicateBuilder.True<EleTodo>();
if (!string.IsNullOrEmpty(_name))
{
filter = filter.Compose(x => x.Name.Contains(_name), Expression.AndAlso);
}
if (!string.IsNullOrEmpty(_name) && !string.IsNullOrEmpty(_remark))
{
filter = filter.Compose(x => x.Name.Contains(_name) && (x.Remark == null ? false : x.Remark.Contains(_remark)), Expression.AndAlso);
}
if (!string.IsNullOrEmpty(_name) && !string.IsNullOrEmpty(_remark) && _status != null)
{
filter = filter.Compose(
x => x.Name.Contains(_name) && (x.Remark == null ? false : x.Remark.Contains(_remark)) && x.Status == _status,
Expression.AndAlso
);
}
return filter;
}
}
标签:return,string,规约,高级,linq,name,Expression,public,LinqExpressionLearn
From: https://www.cnblogs.com/zhuoss/p/18365816