@@ -22,9 +22,24 @@ public GeneratedInvokableDescription Generate(InvokableMethodDescription invokab
2222 var generatedClassName = GetSimpleClassName ( invokableMethodInfo ) ;
2323
2424 var baseClassType = GetBaseClassType ( invokableMethodInfo ) ;
25- var fieldDescriptions = GetFieldDescriptions ( invokableMethodInfo ) ;
26- var fields = GetFieldDeclarations ( invokableMethodInfo , fieldDescriptions ) ;
27- var ( ctor , ctorArgs ) = GenerateConstructor ( generatedClassName , invokableMethodInfo , baseClassType ) ;
25+ var fieldDescriptions = GetFieldDescriptions ( invokableMethodInfo , baseClassType ) ;
26+ var invokableTypeSyntax = CreateInvokableTypeSyntax ( generatedClassName , invokableMethodInfo ) ;
27+ var fields = GetFieldDeclarations ( invokableMethodInfo , fieldDescriptions , invokableTypeSyntax ) ;
28+ var ( ctor , ctorArgs ) = GenerateConstructor ( generatedClassName , invokableMethodInfo , baseClassType , fieldDescriptions , invokableTypeSyntax ) ;
29+ var compatibilityCtor = fieldDescriptions . OfType < PoolFieldDescription > ( ) . Any ( )
30+ ? ConstructorDeclaration ( generatedClassName )
31+ . AddModifiers ( Token ( SyntaxKind . PublicKeyword ) )
32+ . WithInitializer (
33+ ConstructorInitializer (
34+ SyntaxKind . ThisConstructorInitializer ,
35+ ArgumentList (
36+ SingletonSeparatedList (
37+ Argument (
38+ PostfixUnaryExpression (
39+ SyntaxKind . SuppressNullableWarningExpression ,
40+ LiteralExpression ( SyntaxKind . NullLiteralExpression ) ) ) ) ) ) )
41+ . WithBody ( Block ( ) )
42+ : null ;
2843 var accessibility = GetAccessibility ( method ) ;
2944 var compoundTypeAliases = GetCompoundTypeAliasAttributeArguments ( invokableMethodInfo , invokableMethodInfo . Key ) ;
3045
@@ -52,6 +67,7 @@ public GeneratedInvokableDescription Generate(InvokableMethodDescription invokab
5267 baseClassType ,
5368 fieldDescriptions ,
5469 fields ,
70+ compatibilityCtor ,
5571 ctor ,
5672 compoundTypeAliases ,
5773 targetField ,
@@ -77,6 +93,7 @@ [.. fieldDescriptions.OfType<IMemberDescription>()],
7793 serializationHooks ,
7894 baseClassType ,
7995 ctorArgs ,
96+ fieldDescriptions . OfType < PoolFieldDescription > ( ) . Any ( ) ,
8097 compoundTypeAliases ,
8198 returnValueInitializerMethod ,
8299 classDeclaration ) ;
@@ -106,6 +123,7 @@ private ClassDeclarationSyntax GetClassDeclarationSyntax(
106123 INamedTypeSymbol baseClassType ,
107124 List < InvokerFieldDescription > fieldDescriptions ,
108125 MemberDeclarationSyntax [ ] fields ,
126+ ConstructorDeclarationSyntax ? compatibilityCtor ,
109127 ConstructorDeclarationSyntax ? ctor ,
110128 List < CompoundTypeAliasComponent [ ] > compoundTypeAliases ,
111129 TargetFieldDescription targetField ,
@@ -123,7 +141,12 @@ private ClassDeclarationSyntax GetClassDeclarationSyntax(
123141 AttributeList ( SingletonSeparatedList ( GetCompoundTypeAliasAttribute ( alias ) ) ) ) ;
124142 }
125143
126- if ( ctor != null )
144+ if ( compatibilityCtor is not null )
145+ {
146+ classDeclaration = classDeclaration . AddMembers ( compatibilityCtor ) ;
147+ }
148+
149+ if ( ctor is not null )
127150 {
128151 classDeclaration = classDeclaration . AddMembers ( ctor ) ;
129152 }
@@ -568,6 +591,7 @@ private static MemberDeclarationSyntax GenerateDisposeMethod(
568591 INamedTypeSymbol baseClassType )
569592 {
570593 var body = new List < StatementSyntax > ( ) ;
594+ PoolFieldDescription ? poolField = null ;
571595 foreach ( var field in fields )
572596 {
573597 if ( field is CancellationTokenSourceFieldDescription ctsField )
@@ -582,6 +606,11 @@ private static MemberDeclarationSyntax GenerateDisposeMethod(
582606 MemberBindingExpression ( IdentifierName ( "Dispose" ) ) ) ) ) ) ;
583607 }
584608
609+ if ( field is PoolFieldDescription candidate )
610+ {
611+ poolField = candidate ;
612+ }
613+
585614 if ( field . IsInstanceField )
586615 {
587616 body . Add (
@@ -601,6 +630,17 @@ private static MemberDeclarationSyntax GenerateDisposeMethod(
601630 body . Add ( ExpressionStatement ( InvocationExpression ( BaseExpression ( ) . Member ( "Dispose" ) ) . WithArgumentList ( ArgumentList ( ) ) ) ) ;
602631 }
603632
633+ if ( poolField is not null )
634+ {
635+ body . Add (
636+ ExpressionStatement (
637+ ConditionalAccessExpression (
638+ IdentifierName ( poolField . FieldName ) ,
639+ InvocationExpression (
640+ MemberBindingExpression ( IdentifierName ( "Return" ) ) ,
641+ ArgumentList ( SingletonSeparatedList ( Argument ( ThisExpression ( ) ) ) ) ) ) ) ) ;
642+ }
643+
604644 return MethodDeclaration ( PredefinedType ( Token ( SyntaxKind . VoidKeyword ) ) , "Dispose" )
605645 . WithModifiers ( TokenList ( Token ( SyntaxKind . PublicKeyword ) , Token ( SyntaxKind . OverrideKeyword ) ) )
606646 . WithBody ( Block ( body ) ) ;
@@ -678,9 +718,24 @@ public static string GetSimpleClassName(InvokableMethodDescription method)
678718 return $ "Invokable_{ method . ContainingInterface . Name } _{ proxyKey } _{ method . GeneratedMethodId } { typeArgs } ";
679719 }
680720
721+ private static TypeSyntax CreateInvokableTypeSyntax ( string generatedClassName , InvokableMethodDescription method )
722+ {
723+ if ( method . AllTypeParameters . Count == 0 )
724+ {
725+ return IdentifierName ( generatedClassName ) ;
726+ }
727+
728+ var typeArguments = method . AllTypeParameters . Select ( parameter =>
729+ ( TypeSyntax ) IdentifierName ( method . TypeParameterSubstitutions [ parameter . Parameter ] ) ) ;
730+ return GenericName (
731+ Identifier ( generatedClassName ) ,
732+ TypeArgumentList ( SeparatedList ( typeArguments ) ) ) ;
733+ }
734+
681735 private MemberDeclarationSyntax [ ] GetFieldDeclarations (
682736 InvokableMethodDescription method ,
683- List < InvokerFieldDescription > fieldDescriptions )
737+ List < InvokerFieldDescription > fieldDescriptions ,
738+ TypeSyntax invokableTypeSyntax )
684739 {
685740 return [ .. fieldDescriptions . Select ( GetFieldDeclaration ) ] ;
686741
@@ -708,6 +763,14 @@ MemberDeclarationSyntax GetFieldDeclaration(InvokerFieldDescription description)
708763 ] ) ) ) ) ) ) ) )
709764 . AddModifiers ( Token ( SyntaxKind . PrivateKeyword ) , Token ( SyntaxKind . StaticKeyword ) , Token ( SyntaxKind . ReadOnlyKeyword ) ) ;
710765 }
766+ else if ( description is PoolFieldDescription )
767+ {
768+ field = FieldDeclaration (
769+ VariableDeclaration (
770+ LibraryTypes . InvokablePool_1 . ToTypeSyntax ( invokableTypeSyntax ) ,
771+ SingletonSeparatedList ( VariableDeclarator ( description . FieldName ) ) ) )
772+ . AddModifiers ( Token ( SyntaxKind . PrivateKeyword ) , Token ( SyntaxKind . ReadOnlyKeyword ) ) ;
773+ }
711774 else
712775 {
713776 field = FieldDeclaration (
@@ -738,14 +801,30 @@ private static ExpressionSyntax GetTypesArray(InvokableMethodDescription method,
738801 private ( ConstructorDeclarationSyntax ? Constructor , List < TypeSyntax > ConstructorArguments ) GenerateConstructor (
739802 string simpleClassName ,
740803 InvokableMethodDescription method ,
741- INamedTypeSymbol baseClassType )
804+ INamedTypeSymbol baseClassType ,
805+ List < InvokerFieldDescription > fieldDescriptions ,
806+ TypeSyntax invokableTypeSyntax )
742807 {
743808 var parameters = new List < ParameterSyntax > ( ) ;
744809
745810 var body = new List < StatementSyntax > ( ) ;
746811
747812 List < TypeSyntax > constructorArgumentTypes = new ( ) ;
748813 List < ArgumentSyntax > baseConstructorArguments = new ( ) ;
814+
815+ if ( fieldDescriptions . OfType < PoolFieldDescription > ( ) . FirstOrDefault ( ) is { } poolField )
816+ {
817+ var poolType = LibraryTypes . InvokablePool_1 . ToTypeSyntax ( invokableTypeSyntax ) ;
818+ constructorArgumentTypes . Add ( poolType ) ;
819+ parameters . Add ( Parameter ( Identifier ( "pool" ) ) . WithType ( poolType ) ) ;
820+ body . Add (
821+ ExpressionStatement (
822+ AssignmentExpression (
823+ SyntaxKind . SimpleAssignmentExpression ,
824+ IdentifierName ( poolField . FieldName ) ,
825+ IdentifierName ( "pool" ) ) ) ) ;
826+ }
827+
749828 foreach ( var constructor in baseClassType . GetAllMembers < IMethodSymbol > ( ) )
750829 {
751830 if ( constructor . MethodKind != MethodKind . Constructor || constructor . DeclaredAccessibility == Accessibility . Private || constructor . IsImplicitlyDeclared )
@@ -791,7 +870,9 @@ private static ExpressionSyntax GetTypesArray(InvokableMethodDescription method,
791870 return ( constructorDeclaration , constructorArgumentTypes ) ;
792871 }
793872
794- private List < InvokerFieldDescription > GetFieldDescriptions ( InvokableMethodDescription method )
873+ private List < InvokerFieldDescription > GetFieldDescriptions (
874+ InvokableMethodDescription method ,
875+ INamedTypeSymbol baseClassType )
795876 {
796877 var fields = new List < InvokerFieldDescription > ( ) ;
797878 uint fieldId = 0 ;
@@ -811,7 +892,27 @@ private List<InvokerFieldDescription> GetFieldDescriptions(InvokableMethodDescri
811892 fields . Add ( new CancellationTokenSourceFieldDescription ( LibraryTypes ) ) ;
812893 }
813894
895+ var requiresDependencyInjection = baseClassType . GetAllMembers < IMethodSymbol > ( )
896+ . Any ( constructor =>
897+ constructor . MethodKind == MethodKind . Constructor
898+ && constructor . HasAttribute ( LibraryTypes . GeneratedActivatorConstructorAttribute ) ) ;
899+ if ( method . MethodTypeParameters . Count == 0
900+ && method . CustomInitializerMethods . Count == 0
901+ && ! requiresDependencyInjection
902+ && IsPoolableBaseType ( baseClassType ) )
903+ {
904+ fields . Add ( new PoolFieldDescription ( LibraryTypes ) ) ;
905+ }
906+
814907 return fields ;
908+
909+ static bool IsPoolableBaseType ( INamedTypeSymbol type )
910+ => type . ContainingNamespace . ToDisplayString ( ) == "Orleans.Runtime"
911+ && type . MetadataName is "Request"
912+ or "Request`1"
913+ or "TaskRequest"
914+ or "TaskRequest`1"
915+ or "VoidRequest" ;
815916 }
816917
817918 internal abstract class InvokerFieldDescription ( ITypeSymbol fieldType , string fieldName )
@@ -910,4 +1011,10 @@ internal sealed class MethodInfoFieldDescription(ITypeSymbol fieldType, string f
9101011 public override bool IsSerializable => false ;
9111012 public override bool IsInstanceField => false ;
9121013 }
1014+
1015+ internal sealed class PoolFieldDescription ( LibraryTypes libraryTypes ) : InvokerFieldDescription ( libraryTypes . InvokablePool_1 , "_pool" )
1016+ {
1017+ public override bool IsSerializable => false ;
1018+ public override bool IsInstanceField => false ;
1019+ }
9131020}
0 commit comments