Версия 1.1 от Alexandr Fokin на 2023/02/08 13:11

Последние авторы
1 {{code language="c#"}}
2 public class ExpressionMapper2<TEntity, TValue>
3 {
4 private readonly Dictionary<
5 string,
6 TValue
7 > Mapping;
8
9 private readonly Func<IEnumerable<Expression>, string> KeySelector;
10 private static readonly Func<IEnumerable<Expression>, string> DefaultKeySelector =
11 (e) =>
12 {
13 var expression = e.First(e2 => e2 is MemberExpression) as MemberExpression;
14 return expression.Member.Name;
15 };
16
17 public ExpressionMapper2(
18 IEnumerable<(string key, TValue value)> source,
19 Func<IEnumerable<Expression>, string>? keySelector = null
20 )
21 {
22 KeySelector = keySelector ?? DefaultKeySelector;
23 Mapping = source.ToDictionary(
24 e => e.key,
25 e => e.value
26 );
27 }
28 public ExpressionMapper2(
29 IEnumerable<(Expression<Func<TEntity, object>> keyExpression, TValue value)> source,
30 Func<IEnumerable<Expression>, string>? keySelector = null
31 )
32 {
33 KeySelector = keySelector ?? DefaultKeySelector;
34 Mapping = source.ToDictionary(
35 e => GetKey(e.keyExpression),
36 e => e.value
37 );
38 }
39
40
41 private string GetKey(Expression expression)
42 {
43 Visitor visitor = new Visitor();
44 visitor.Visit(expression);
45 var key = KeySelector(visitor.ExpressionList);
46 return key;
47 }
48
49 public bool TryGetValue<T>(
50 Expression<Func<TEntity, T>> expression,
51 out TValue value
52 )
53 {
54 var key = GetKey(expression);
55 return Mapping.TryGetValue(
56 key,
57 out value
58 );
59 }
60
61 public TValue GetValue<T>(
62 Expression<Func<TEntity, T>> expression
63 )
64 {
65 if (TryGetValue(expression, out var value))
66 {
67 return value;
68 }
69 else
70 {
71 throw new KeyNotFoundException();
72 }
73 }
74
75
76 private sealed class Visitor
77 : ExpressionVisitor
78 {
79 public List<Expression> ExpressionList { get; private set; }
80 = new List<Expression>();
81
82
83 [return: NotNullIfNotNull("node")]
84 public override Expression? Visit(
85 Expression? node
86 )
87 {
88 ExpressionList.Add(node);
89 return base.Visit(node);
90 }
91 }
92
93 public static Builder CreateBuilder()
94 {
95 return new Builder();
96 }
97
98 public class Builder
99 {
100 private Func<IEnumerable<Expression>, string> KeySelector = DefaultKeySelector;
101 private List<(Expression, TValue)> Rules = new List<(Expression, TValue)>();
102
103
104 public Builder SetKeySelector(
105 Func<IEnumerable<Expression>, string> keySelector
106 )
107 {
108 KeySelector = keySelector;
109 return this;
110 }
111
112 public Builder AddRule<T>(
113 Expression<Func<TEntity, T>> rule,
114 TValue value
115 )
116 {
117 Rules.Add((rule, value));
118 return this;
119 }
120
121
122 public ExpressionMapper2<TEntity, TValue> Build()
123 {
124 (string key, TValue value)[] rules = new (string key, TValue value)[Rules.Count];
125 {
126 Visitor visitor = new Visitor();
127 int i = 0;
128 foreach (var elem in Rules)
129 {
130 visitor.Visit(elem.Item1);
131 var key = KeySelector(visitor.ExpressionList);
132 visitor.ExpressionList.Clear();
133
134 rules[i] = (key, elem.Item2);
135 i++;
136 }
137 }
138
139 return new ExpressionMapper2<TEntity, TValue>(
140 rules,
141 KeySelector
142 );
143 }
144 }
145 }
146 {{/code}}