tgstation-server 6.19.0
The /tg/station 13 server suite
Loading...
Searching...
No Matches
TransformerBase{TInput,TOutput}.cs
Go to the documentation of this file.
1using System;
2using System.Linq.Expressions;
3
6
8{
10 abstract class TransformerBase<TInput, TOutput> : ITransformer<TInput, TOutput>
11 {
15 static Func<TInput, TOutput>? compiledExpression; // This is safe https://stackoverflow.com/a/9647661/3976486
16
20 static Expression<Func<TInput, ProjectedPair<TInput, TOutput>>>? projectedExpression;
21
23 public Expression<Func<TInput, TOutput>> Expression { get; }
24
26 public Expression<Func<TInput, ProjectedPair<TInput, TOutput>>> ProjectedExpression { get; }
27
29 public Func<TInput, TOutput> CompiledExpression { get; }
30
36 protected static T NotNullFallback<T>()
37 where T : notnull
38 => default!;
39
49 protected static Expression<Func<TInput, TOutput>> BuildSubProjection<TSubInput, TSubOutput, TTransformer>(
50 Expression<Func<TInput, TSubOutput?, TOutput>> transformerExpression,
51 Expression<Func<TInput, TSubInput?>> subInputSelectionExpression)
52 where TSubOutput : class
53 where TTransformer : ITransformer<TSubInput, TSubOutput>, new()
54 {
55 var subTransformer = new TTransformer();
56
57 var primaryInput = global::System.Linq.Expressions.Expression.Parameter(typeof(TInput), "input");
58 var subInputExpression = global::System.Linq.Expressions.Expression.Invoke(subInputSelectionExpression, primaryInput);
59
60 var notNullExpression = global::System.Linq.Expressions.Expression.MakeBinary(
61 ExpressionType.NotEqual,
62 subInputExpression,
63 global::System.Linq.Expressions.Expression.Constant(null, typeof(TSubInput)));
64
65 var subOutputExpression = global::System.Linq.Expressions.Expression.Invoke(subTransformer.Expression, subInputExpression);
66
67 var conditionalSubOutputExpression = global::System.Linq.Expressions.Expression.Condition(
68 notNullExpression,
69 subOutputExpression,
70 global::System.Linq.Expressions.Expression.Constant(null, typeof(TSubOutput)));
71
72 var outputExpression = global::System.Linq.Expressions.Expression.Invoke(transformerExpression, primaryInput, conditionalSubOutputExpression);
73
74 return global::System.Linq.Expressions.Expression.Lambda<Func<TInput, TOutput>>(outputExpression, primaryInput);
75 }
76
90 protected static Expression<Func<TInput, TOutput>> BuildSubProjection<
91 TSubInput1,
92 TSubInput2,
93 TSubOutput1,
94 TSubOutput2,
95 TTransformer1,
96 TTransformer2>(
97 Expression<Func<TInput, TSubOutput1?, TSubOutput2?, TOutput>> transformerExpression,
98 Expression<Func<TInput, TSubInput1?>> subInput1SelectionExpression,
99 Expression<Func<TInput, TSubInput2?>> subInput2SelectionExpression)
100 where TSubOutput1 : class
101 where TSubOutput2 : class
102 where TTransformer1 : ITransformer<TSubInput1, TSubOutput1>, new()
103 where TTransformer2 : ITransformer<TSubInput2, TSubOutput2>, new()
104 {
105 var subTransformer1 = new TTransformer1();
106 var subTransformer2 = new TTransformer2();
107
108 var primaryInput = global::System.Linq.Expressions.Expression.Parameter(typeof(TInput), "input");
109
110 var subInput1Expression = global::System.Linq.Expressions.Expression.Invoke(subInput1SelectionExpression, primaryInput);
111 var subInput2Expression = global::System.Linq.Expressions.Expression.Invoke(subInput2SelectionExpression, primaryInput);
112
113 var notNullExpression1 = global::System.Linq.Expressions.Expression.MakeBinary(
114 ExpressionType.NotEqual,
115 subInput1Expression,
116 global::System.Linq.Expressions.Expression.Constant(null, typeof(TSubInput1)));
117 var notNullExpression2 = global::System.Linq.Expressions.Expression.MakeBinary(
118 ExpressionType.NotEqual,
119 subInput2Expression,
120 global::System.Linq.Expressions.Expression.Constant(null, typeof(TSubInput2)));
121
122 var subOutput1Expression = global::System.Linq.Expressions.Expression.Invoke(subTransformer1.Expression, subInput1Expression);
123 var subOutput2Expression = global::System.Linq.Expressions.Expression.Invoke(subTransformer2.Expression, subInput2Expression);
124
125 var conditionalSubOutput1Expression = global::System.Linq.Expressions.Expression.Condition(
126 notNullExpression1,
127 subOutput1Expression,
128 global::System.Linq.Expressions.Expression.Constant(null, typeof(TSubOutput1)));
129
130 var conditionalSubOutput2Expression = global::System.Linq.Expressions.Expression.Condition(
131 notNullExpression2,
132 subOutput2Expression,
133 global::System.Linq.Expressions.Expression.Constant(null, typeof(TSubOutput2)));
134
135 var outputExpression = global::System.Linq.Expressions.Expression.Invoke(transformerExpression, primaryInput, conditionalSubOutput1Expression, conditionalSubOutput2Expression);
136
137 return global::System.Linq.Expressions.Expression.Lambda<Func<TInput, TOutput>>(outputExpression, primaryInput);
138 }
139
145 Expression<Func<TInput, TOutput>> expression)
146 {
147 compiledExpression ??= expression.Compile();
148 projectedExpression ??= expression.Projected();
149 Expression = expression;
152 }
153 }
154}
Expression< Func< TInput, TOutput > > Expression
Expression<TDelegate> form of the transformation.
static T NotNullFallback< T >()
Gets the T that should be used when a database projected non-null DTO value is null in the expressio...
static ? Func< TInput, TOutput > compiledExpression
static cache for CompiledExpression.
Expression< Func< TInput, ProjectedPair< TInput, TOutput > > > ProjectedExpression
Expression<TDelegate> for mapping TInput into a ProjectedPair<TQueried, TResult>.
Func< TInput, TOutput > CompiledExpression
The compiled Expression.
TransformerBase(Expression< Func< TInput, TOutput > > expression)
Initializes a new instance of the TransformerBase<TInput, TOutput> class.
static ? Expression< Func< TInput, ProjectedPair< TInput, TOutput > > > projectedExpression
static cache for ProjectedExpression.
Contains a transformation Expression for converting TInput s to TOutput s.