@@ -64,7 +64,11 @@ public void Execute(GeneratorExecutionContext context)
6464
6565 foreach ( INamedTypeSymbol classSymbol in syntaxReceiver . GatheredInfo )
6666 {
67- // Create a static method to validate all properties in a given class.
67+ // Create a static factory method creating a delegate that can be used to validate all properties in a given class.
68+ // This pattern is used so that the library doesn't have to use MakeGenericType(...) at runtime, nor use unsafe casts
69+ // over the created delegate to be able to cache it as an Action<object> instance. This pattern enables the same
70+ // functionality and with almost identical performance (not noticeable in this context anyway), but while preserving
71+ // full runtime type safety (as a safe cast is used to validate the input argument), and with less reflection needed.
6872 // This code takes a class symbol and produces a compilation unit as follows:
6973 //
7074 // // Licensed to the .NET Foundation under one or more agreements.
@@ -84,9 +88,14 @@ public void Execute(GeneratorExecutionContext context)
8488 // {
8589 // [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
8690 // [global::System.Obsolete("This method is not intended to be called directly by user code")]
87- // public static void ValidateAllProperties (<INSTANCE_TYPE> instance )
91+ // public static global::System.Action<object> CreateAllPropertiesValidator (<INSTANCE_TYPE> _ )
8892 // {
89- // <BODY>
93+ // static void ValidateAllProperties(<INSTANCE_TYPE> instance)
94+ // {
95+ // <BODY>
96+ // }
97+ //
98+ // return static o => ValidateAllProperties((<INSTANCE_TYPE>)o);
9099 // }
91100 // }
92101 // }
@@ -102,8 +111,8 @@ public void Execute(GeneratorExecutionContext context)
102111 Token ( SyntaxKind . StaticKeyword ) ,
103112 Token ( SyntaxKind . PartialKeyword ) ) . AddAttributeLists ( classAttributes ) . AddMembers (
104113 MethodDeclaration (
105- PredefinedType ( Token ( SyntaxKind . VoidKeyword ) ) ,
106- Identifier ( "ValidateAllProperties " ) ) . AddAttributeLists (
114+ GenericName ( "global::System.Action" ) . AddTypeArgumentListArguments ( PredefinedType ( Token ( SyntaxKind . ObjectKeyword ) ) ) ,
115+ Identifier ( "CreateAllPropertiesValidator " ) ) . AddAttributeLists (
107116 AttributeList ( SingletonSeparatedList (
108117 Attribute ( IdentifierName ( "global::System.ComponentModel.EditorBrowsable" ) ) . AddArgumentListArguments (
109118 AttributeArgument ( ParseExpression ( "global::System.ComponentModel.EditorBrowsableState.Never" ) ) ) ) ) ,
@@ -114,8 +123,24 @@ public void Execute(GeneratorExecutionContext context)
114123 Literal ( "This method is not intended to be called directly by user code" ) ) ) ) ) ) ) . AddModifiers (
115124 Token ( SyntaxKind . PublicKeyword ) ,
116125 Token ( SyntaxKind . StaticKeyword ) ) . AddParameterListParameters (
117- Parameter ( Identifier ( "instance" ) ) . WithType ( IdentifierName ( classSymbol . ToDisplayString ( SymbolDisplayFormat . FullyQualifiedFormat ) ) ) )
118- . WithBody ( Block ( EnumerateValidationStatements ( classSymbol , validationSymbol ) . ToArray ( ) ) ) ) ) )
126+ Parameter ( Identifier ( "_" ) ) . WithType ( IdentifierName ( classSymbol . ToDisplayString ( SymbolDisplayFormat . FullyQualifiedFormat ) ) ) )
127+ . WithBody ( Block (
128+ LocalFunctionStatement (
129+ PredefinedType ( Token ( SyntaxKind . VoidKeyword ) ) ,
130+ Identifier ( "ValidateAllProperties" ) )
131+ . AddModifiers ( Token ( SyntaxKind . StaticKeyword ) )
132+ . AddParameterListParameters (
133+ Parameter ( Identifier ( "instance" ) ) . WithType ( IdentifierName ( classSymbol . ToDisplayString ( SymbolDisplayFormat . FullyQualifiedFormat ) ) ) )
134+ . WithBody ( Block ( EnumerateValidationStatements ( classSymbol , validationSymbol ) . ToArray ( ) ) ) ,
135+ ReturnStatement (
136+ SimpleLambdaExpression ( Parameter ( Identifier ( "o" ) ) )
137+ . AddModifiers ( Token ( SyntaxKind . StaticKeyword ) )
138+ . WithExpressionBody (
139+ InvocationExpression ( IdentifierName ( "ValidateAllProperties" ) )
140+ . AddArgumentListArguments ( Argument (
141+ CastExpression (
142+ IdentifierName ( classSymbol . ToDisplayString ( SymbolDisplayFormat . FullyQualifiedFormat ) ) ,
143+ IdentifierName ( "o" ) ) ) ) ) ) ) ) ) ) )
119144 . NormalizeWhitespace ( )
120145 . ToFullString ( ) ;
121146
0 commit comments