From 55f5392cc4e1f650a6047143a3fff59cb826282e Mon Sep 17 00:00:00 2001 From: Jordan Dominion Date: Sun, 17 Aug 2025 15:35:14 -0400 Subject: [PATCH] Deduplicate `BuildSubProjection` code --- .../Models/TransformerBase{TInput,TOutput}.cs | 188 +++++++++--------- 1 file changed, 95 insertions(+), 93 deletions(-) diff --git a/src/Tgstation.Server.Host/Models/TransformerBase{TInput,TOutput}.cs b/src/Tgstation.Server.Host/Models/TransformerBase{TInput,TOutput}.cs index 73295f68ef..761b93eaff 100644 --- a/src/Tgstation.Server.Host/Models/TransformerBase{TInput,TOutput}.cs +++ b/src/Tgstation.Server.Host/Models/TransformerBase{TInput,TOutput}.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics; using System.Linq.Expressions; using Tgstation.Server.Host.Authority.Core; @@ -48,28 +49,20 @@ namespace Tgstation.Server.Host.Models Expression> subInputSelectionExpression) where TSubOutput : class where TTransformer : ITransformer, new() - { - var subTransformer = new TTransformer(); - - var primaryInput = global::System.Linq.Expressions.Expression.Parameter(typeof(TInput), "input"); - var subInputExpression = global::System.Linq.Expressions.Expression.Invoke(subInputSelectionExpression, primaryInput); - - var notNullExpression = global::System.Linq.Expressions.Expression.MakeBinary( - ExpressionType.NotEqual, - subInputExpression, - global::System.Linq.Expressions.Expression.Constant(null, typeof(TSubInput))); - - var subOutputExpression = global::System.Linq.Expressions.Expression.Invoke(subTransformer.Expression, subInputExpression); - - var conditionalSubOutputExpression = global::System.Linq.Expressions.Expression.Condition( - notNullExpression, - subOutputExpression, - global::System.Linq.Expressions.Expression.Constant(null, typeof(TSubOutput))); - - var outputExpression = global::System.Linq.Expressions.Expression.Invoke(transformerExpression, primaryInput, conditionalSubOutputExpression); - - return global::System.Linq.Expressions.Expression.Lambda>(outputExpression, primaryInput); - } + => BuildSubProjectionN( + transformerExpression, + [ + typeof(TSubInput), + ], + [ + typeof(TSubOutput), + ], + [ + subInputSelectionExpression, + ], + [ + new TTransformer().Expression, + ]); /// /// Build an for to when contains two sub-inputs with their own s. @@ -98,40 +91,24 @@ namespace Tgstation.Server.Host.Models where TSubOutput2 : class where TTransformer1 : ITransformer, new() where TTransformer2 : ITransformer, new() - { - var subTransformer1 = new TTransformer1(); - var subTransformer2 = new TTransformer2(); - - var primaryInput = global::System.Linq.Expressions.Expression.Parameter(typeof(TInput), "input"); - - var subInput1Expression = global::System.Linq.Expressions.Expression.Invoke(subInput1SelectionExpression, primaryInput); - var subInput2Expression = global::System.Linq.Expressions.Expression.Invoke(subInput2SelectionExpression, primaryInput); - - var notNullExpression1 = global::System.Linq.Expressions.Expression.MakeBinary( - ExpressionType.NotEqual, - subInput1Expression, - global::System.Linq.Expressions.Expression.Constant(null, typeof(TSubInput1))); - var notNullExpression2 = global::System.Linq.Expressions.Expression.MakeBinary( - ExpressionType.NotEqual, - subInput2Expression, - global::System.Linq.Expressions.Expression.Constant(null, typeof(TSubInput2))); - - var subOutput1Expression = global::System.Linq.Expressions.Expression.Invoke(subTransformer1.Expression, subInput1Expression); - var subOutput2Expression = global::System.Linq.Expressions.Expression.Invoke(subTransformer2.Expression, subInput2Expression); - - var conditionalSubOutput1Expression = global::System.Linq.Expressions.Expression.Condition( - notNullExpression1, - subOutput1Expression, - global::System.Linq.Expressions.Expression.Constant(null, typeof(TSubOutput1))); - var conditionalSubOutput2Expression = global::System.Linq.Expressions.Expression.Condition( - notNullExpression2, - subOutput2Expression, - global::System.Linq.Expressions.Expression.Constant(null, typeof(TSubOutput2))); - - var outputExpression = global::System.Linq.Expressions.Expression.Invoke(transformerExpression, primaryInput, conditionalSubOutput1Expression, conditionalSubOutput2Expression); - - return global::System.Linq.Expressions.Expression.Lambda>(outputExpression, primaryInput); - } + => BuildSubProjectionN( + transformerExpression, + [ + typeof(TSubInput1), + typeof(TSubInput2), + ], + [ + typeof(TSubOutput1), + typeof(TSubOutput2), + ], + [ + subInput1SelectionExpression, + subInput2SelectionExpression, + ], + [ + new TTransformer1().Expression, + new TTransformer2().Expression, + ]); /// /// Build an for to when contains three sub-inputs with their own s. @@ -170,53 +147,78 @@ namespace Tgstation.Server.Host.Models where TTransformer1 : ITransformer, new() where TTransformer2 : ITransformer, new() where TTransformer3 : ITransformer, new() + => BuildSubProjectionN( + transformerExpression, + [ + typeof(TSubInput1), + typeof(TSubInput2), + typeof(TSubInput3), + ], + [ + typeof(TSubOutput1), + typeof(TSubOutput2), + typeof(TSubOutput3), + ], + [ + subInput1SelectionExpression, + subInput2SelectionExpression, + subInput3SelectionExpression, + ], + [ + new TTransformer1().Expression, + new TTransformer2().Expression, + new TTransformer3().Expression, + ]); + + /// + /// Build an for to when contains N sub-inputs with their own s. + /// + /// The to take a and transformed sub-outputs and produce a . + /// The s in that need transforming. + /// The transformed . + /// s to select the from . + /// s to transform the into . + /// An expression converting into based on with its other arguments generated from the transformation result of . + private static Expression> BuildSubProjectionN( + LambdaExpression transformerExpression, + Type[] subInputTypes, + Type[] subOutputTypes, + LambdaExpression[] subInputSelectionExpressions, + LambdaExpression[] subInputTransformerExpressions) { - var subTransformer1 = new TTransformer1(); - var subTransformer2 = new TTransformer2(); - var subTransformer3 = new TTransformer3(); + var n = subInputTypes.Length; + + Debug.Assert(n == subOutputTypes.Length, $"{nameof(subOutputTypes)}.{nameof(Array.Length)} != {nameof(subInputTypes)}.{nameof(Array.Length)}"); + Debug.Assert(n == subInputSelectionExpressions.Length, $"{nameof(subInputSelectionExpressions)}.{nameof(Array.Length)} != n"); + Debug.Assert(n == subInputTransformerExpressions.Length, $"{nameof(subInputTransformerExpressions)}.{nameof(Array.Length)} != n"); var primaryInput = global::System.Linq.Expressions.Expression.Parameter(typeof(TInput), "input"); - var subInput1Expression = global::System.Linq.Expressions.Expression.Invoke(subInput1SelectionExpression, primaryInput); - var subInput2Expression = global::System.Linq.Expressions.Expression.Invoke(subInput2SelectionExpression, primaryInput); - var subInput3Expression = global::System.Linq.Expressions.Expression.Invoke(subInput3SelectionExpression, primaryInput); + var finalExpressionParameters = new Expression[n + 1]; + finalExpressionParameters[0] = primaryInput; - var notNullExpression1 = global::System.Linq.Expressions.Expression.MakeBinary( - ExpressionType.NotEqual, - subInput1Expression, - global::System.Linq.Expressions.Expression.Constant(null, typeof(TSubInput1))); - var notNullExpression2 = global::System.Linq.Expressions.Expression.MakeBinary( - ExpressionType.NotEqual, - subInput2Expression, - global::System.Linq.Expressions.Expression.Constant(null, typeof(TSubInput2))); - var notNullExpression3 = global::System.Linq.Expressions.Expression.MakeBinary( - ExpressionType.NotEqual, - subInput3Expression, - global::System.Linq.Expressions.Expression.Constant(null, typeof(TSubInput3))); + for (int i = 0; i < n; i++) + { + var subInputExpression = global::System.Linq.Expressions.Expression.Invoke(subInputSelectionExpressions[i], primaryInput); - var subOutput1Expression = global::System.Linq.Expressions.Expression.Invoke(subTransformer1.Expression, subInput1Expression); - var subOutput2Expression = global::System.Linq.Expressions.Expression.Invoke(subTransformer2.Expression, subInput2Expression); - var subOutput3Expression = global::System.Linq.Expressions.Expression.Invoke(subTransformer3.Expression, subInput3Expression); + var notNullExpression = global::System.Linq.Expressions.Expression.MakeBinary( + ExpressionType.NotEqual, + subInputExpression, + global::System.Linq.Expressions.Expression.Constant(null, subInputTypes[i])); - var conditionalSubOutput1Expression = global::System.Linq.Expressions.Expression.Condition( - notNullExpression1, - subOutput1Expression, - global::System.Linq.Expressions.Expression.Constant(null, typeof(TSubOutput1))); - var conditionalSubOutput2Expression = global::System.Linq.Expressions.Expression.Condition( - notNullExpression2, - subOutput2Expression, - global::System.Linq.Expressions.Expression.Constant(null, typeof(TSubOutput2))); - var conditionalSubOutput3Expression = global::System.Linq.Expressions.Expression.Condition( - notNullExpression3, - subOutput3Expression, - global::System.Linq.Expressions.Expression.Constant(null, typeof(TSubOutput3))); + var subOutputExpression = global::System.Linq.Expressions.Expression.Invoke(subInputTransformerExpressions[i], subInputExpression); + + var conditionalSubOutputExpression = global::System.Linq.Expressions.Expression.Condition( + notNullExpression, + subOutputExpression, + global::System.Linq.Expressions.Expression.Constant(null, subOutputTypes[i])); + + finalExpressionParameters[i + 1] = conditionalSubOutputExpression; + } var outputExpression = global::System.Linq.Expressions.Expression.Invoke( transformerExpression, - primaryInput, - conditionalSubOutput1Expression, - conditionalSubOutput2Expression, - conditionalSubOutput3Expression); + finalExpressionParameters); return global::System.Linq.Expressions.Expression.Lambda>(outputExpression, primaryInput); }