Редактировал(а) Alexandr Fokin 2026/04/02 19:25

Скрыть последних авторов
Alexandr Fokin 1.1 1 |(% style="width:186px" %) |(% style="width:1247px" %)Возможная реализация идеи фиксации правил в виде отдельных компонентов.
Alexandr Fokin 1.5 2 Позволяет держать все правила в одном месте, гарантирует что изменение повлияет на все нужные места.
3 Использование IQueryable т.к. он позволяет строить запросы (но важно учитывать конечный план запроса).
Alexandr Fokin 1.8 4 Также можно реализовать компоненты под другой формат взаимодействия (OneOf, TryGetIfNotNull) (например те, которые часто используются).
Alexandr Fokin 1.3 5 |(% style="width:186px" %) |(% style="width:1247px" %)[[IEnumerable>>doc:Разработка.NET.C#.Коллекции.IEnumerable.WebHome]], [[IQueryable>>doc:Разработка.NET.C#.Коллекции.IQueryable.WebHome]]
Alexandr Fokin 1.1 6 |(% style="width:186px" %)Пример компонента для фиксации правила/условия.|(% style="width:1247px" %)(((
7 |(% style="width:88px" %)InMemory condition|(% style="width:1104px" %){{code language="c#"}}public interface IInMemoryCondition<TData, TParameters>
8 {
9 /// <summary>
10 /// Проверить условие.
11 /// </summary>
12 /// <param name="source"></param>
13 /// <returns></returns>
14 bool Check(TData source, TParameters parameters);
15
16 /// <summary>
17 /// Фильтрация для InMemory.
18 /// </summary>
19 /// <param name="source"></param>
20 /// <returns></returns>
21 IEnumerable<TData> ApplayEnumerable(IEnumerable<TData> source, TParameters parameters);
22 }{{/code}}|{{code language="c#"}}public class DelegateInMemoryCondition<TData, TParameters>
23 : IInMemoryCondition<TData, TParameters>
24 {
25 private readonly Func<TData, TParameters, bool> _checkFunc;
26 private readonly Func<IEnumerable<TData>, TParameters, IEnumerable<TData>> _applayEnumerableFunc;
27
28 public DelegateInMemoryCondition(
29 Func<TData, TParameters, bool> checkFunc,
30 Func<IEnumerable<TData>, TParameters, IEnumerable<TData>>? applayEnumerableFunc = null)
31 {
32 _checkFunc = checkFunc;
33 _applayEnumerableFunc = applayEnumerableFunc
34 ?? ((source, parameter) => source.Where(e => Check(e, parameter)));
35 }
36
37 public bool Check(TData source, TParameters parameters)
38 {
39 return _checkFunc(source, parameters);
40 }
41
42 public IEnumerable<TData> ApplayEnumerable(IEnumerable<TData> source, TParameters parameters)
43 {
44 return _applayEnumerableFunc(source, parameters);
45 }
46 }{{/code}}
47 |(% style="width:88px" %)IQueryable condition|(% style="width:1104px" %){{code language="c#"}}public interface IQueryableCondition<TData, TParameters>
48 {
49 /// <summary>
50 /// Фильтрация для БД.
51 /// Может использовать специфичные для БД функции.
52 /// </summary>
53 /// <param name="source"></param>
54 /// <returns></returns>
55 IQueryable<TData> ApplayQueryable(IQueryable<TData> source, TParameters parameters);
56 }{{/code}}|{{code language="c#"}}public class DelegateIQueryableCondition<TData, TParameters>
57 : IQueryableCondition<TData, TParameters>
58 {
59 private readonly Func<IQueryable<TData>, TParameters, IQueryable<TData>> _applayQueryableFunc;
60
61 public DelegateIQueryableCondition(Func<IQueryable<TData>, TParameters, IQueryable<TData>> applayQueryableFunc)
62 {
63 _applayQueryableFunc = applayQueryableFunc;
64 }
65
66 public IQueryable<TData> ApplayQueryable(IQueryable<TData> source, TParameters parameters)
67 {
68 return _applayQueryableFunc(source, parameters);
69 }
70 }{{/code}}
Alexandr Fokin 1.10 71 |(% style="width:88px" %)Контейнер для агрегата.|(% style="width:1104px" %){{code language="c#"}}// *) Можно использовать в виде композиции, статичного класса, или создания/внедрения отельных компонентов.
Alexandr Fokin 1.9 72 public interface TEntityConditions
Alexandr Fokin 1.1 73 {
74 public (
75 IInMemoryCondition<TEntity, long> Memory,
76 IQueryableCondition<TEntity, long> Query
77 ) ById { get; }
78
79 public (
80 IInMemoryCondition<TEntity, string> Memory,
81 IQueryableCondition<TEntity, string> Query
82 ) ByName { get; }
83
84 public (
85 IInMemoryCondition<TEntity, object?> Memory,
86 IQueryableCondition<TEntity, object?> Query
87 ) IsRule1 { get; }
88 }{{/code}}|
89 )))
90 |(% style="width:186px" %)Вспомогательный Extension|(% style="width:1247px" %)(((
91 |{{code language="c#"}}public static class IConditionExtension
92 {
93 public static IQueryable<TEntity> ApplayFilterCondition<TEntity, TParameter>(
94 this IQueryable<TEntity> source,
95 IQueryableCondition<TEntity, TParameter> condition,
96 TParameter parameter)
97 {
98 return condition.ApplayQueryable(
99 source,
100 parameter);
101 }
102
103 public static IEnumerable<TEntity> ApplayFilterCondition<TEntity, TParameter>(
104 this IEnumerable<TEntity> source,
105 IInMemoryCondition<TEntity, TParameter> condition,
106 TParameter parameter)
107 {
108 return condition.ApplayEnumerable(
109 source,
110 parameter);
111 }
112 }{{/code}}|
113 | |
114 )))
115
116