@@ -324,7 +324,7 @@ private static void GenerateHandleItemMethods(IndentedStringBuilder source, Hand
324324 /// <param name="resultVar">Variable name to store the handler result.</param>
325325 /// <param name="messageVar">Variable name containing the typed message (default: "message").</param>
326326 /// <param name="targetTupleIndex">For tuple return types, the index of the tuple item this method returns (0 = Item1, 1 = Item2, etc.). -1 for non-tuple handlers.</param>
327- private static void EmitHandlerInvocationCode ( IndentedStringBuilder source , HandlerInfo handler , GeneratorConfiguration configuration , string resultVar , string messageVar = "message" , int targetTupleIndex = 0 )
327+ private static void EmitHandlerInvocationCode ( IndentedStringBuilder source , HandlerInfo handler , GeneratorConfiguration configuration , string resultVar , string messageVar = "message" , int targetTupleIndex = 0 , bool isUntypedMethod = false )
328328 {
329329 var variables = new Dictionary < string , string > { [ "System.IServiceProvider" ] = "serviceProvider" } ;
330330
@@ -359,7 +359,7 @@ private static void EmitHandlerInvocationCode(IndentedStringBuilder source, Hand
359359 else
360360 {
361361 // Original code path - no Execute middleware
362- EmitPipelineCode ( source , handler , beforeMiddleware , afterMiddleware , finallyMiddleware , configuration , variables , resultVar , messageVar , targetTupleIndex , requiresTryCatch ) ;
362+ EmitPipelineCode ( source , handler , beforeMiddleware , afterMiddleware , finallyMiddleware , configuration , variables , resultVar , messageVar , targetTupleIndex , requiresTryCatch , isUntypedMethod : isUntypedMethod ) ;
363363 }
364364 }
365365
@@ -396,8 +396,8 @@ private static void EmitExecuteMiddlewareChain(
396396 source . AppendLine ( $ "{ handler . ReturnType . UnwrappedFullName } { ( allowNull ? "?" : "" ) } innerResult = default;") ;
397397 }
398398
399- // Emit the full pipeline inside the delegate
400- EmitPipelineCode ( source , handler , beforeMiddleware , afterMiddleware , finallyMiddleware , configuration , innerVariables , "innerResult" , messageVar , targetTupleIndex , requiresTryCatch , insideExecuteDelegate : true ) ;
399+ // Emit the full pipeline inside the delegate - isUntypedMethod is false here because we're inside a delegate that returns object?
400+ EmitPipelineCode ( source , handler , beforeMiddleware , afterMiddleware , finallyMiddleware , configuration , innerVariables , "innerResult" , messageVar , targetTupleIndex , requiresTryCatch , insideExecuteDelegate : true , isUntypedMethod : false ) ;
401401
402402 source . AppendLine ( handler . HasReturnValue ? "return innerResult;" : "return null;" ) ;
403403 source . DecrementIndent ( ) ;
@@ -483,6 +483,8 @@ private static string BuildExecuteParameters(IndentedStringBuilder source, Equat
483483 /// </summary>
484484 /// <param name="insideExecuteDelegate">When true, we're inside an Execute middleware delegate and short-circuit
485485 /// returns should return the full tuple type (not just one item) since the delegate returns object?.</param>
486+ /// <param name="isUntypedMethod">When true, we're generating UntypedHandleAsync which returns ValueTask<object?>,
487+ /// so void handlers should return null instead of just return.</param>
486488 private static void EmitPipelineCode (
487489 IndentedStringBuilder source ,
488490 HandlerInfo handler ,
@@ -495,7 +497,8 @@ private static void EmitPipelineCode(
495497 string messageVar ,
496498 int targetTupleIndex ,
497499 bool requiresTryCatch ,
498- bool insideExecuteDelegate = false )
500+ bool insideExecuteDelegate = false ,
501+ bool isUntypedMethod = false )
499502 {
500503 // Main execution with optional try-catch-finally
501504 if ( requiresTryCatch )
@@ -510,7 +513,7 @@ private static void EmitPipelineCode(
510513 variables [ "System.Exception" ] = "exception" ;
511514 }
512515
513- EmitBeforeMiddlewareCalls ( source , beforeMiddleware , handler , variables , messageVar , targetTupleIndex , insideExecuteDelegate ) ;
516+ EmitBeforeMiddlewareCalls ( source , beforeMiddleware , handler , variables , messageVar , targetTupleIndex , insideExecuteDelegate , isUntypedMethod ) ;
514517 EmitHandlerInvocation ( source , handler , variables , resultVar , messageVar ) ;
515518 EmitAfterMiddlewareCalls ( source , afterMiddleware , variables , messageVar ) ;
516519
@@ -632,7 +635,8 @@ private static void EmitBeforeMiddlewareCalls(
632635 Dictionary < string , string > variables ,
633636 string messageVar ,
634637 int targetTupleIndex ,
635- bool insideExecuteDelegate = false )
638+ bool insideExecuteDelegate = false ,
639+ bool isUntypedMethod = false )
636640 {
637641 foreach ( var m in beforeMiddleware )
638642 {
@@ -645,7 +649,7 @@ private static void EmitBeforeMiddlewareCalls(
645649
646650 if ( m . Method . ReturnType . IsHandlerResult )
647651 {
648- EmitShortCircuitCheck ( source , m , handler , targetTupleIndex , insideExecuteDelegate ) ;
652+ EmitShortCircuitCheck ( source , m , handler , targetTupleIndex , insideExecuteDelegate , isUntypedMethod ) ;
649653 }
650654 }
651655 source . AppendLineIf ( beforeMiddleware . Any ( ) ) ;
@@ -656,7 +660,8 @@ private static void EmitShortCircuitCheck(
656660 ( MiddlewareMethodInfo Method , MiddlewareInfo Middleware ) m ,
657661 HandlerInfo handler ,
658662 int targetTupleIndex ,
659- bool insideExecuteDelegate = false )
663+ bool insideExecuteDelegate = false ,
664+ bool isUntypedMethod = false )
660665 {
661666 string resultVarName = $ "{ m . Middleware . Identifier . ToCamelCase ( ) } Result";
662667 string valueAccess = m . Method . ReturnType . IsGeneric ? $ "{ resultVarName } .Value" : $ "{ resultVarName } .Value!";
@@ -682,7 +687,9 @@ private static void EmitShortCircuitCheck(
682687 }
683688 else
684689 {
685- source . AppendLine ( " return;" ) ;
690+ // For void handlers: UntypedHandleAsync returns ValueTask<object?> so needs "return null"
691+ // Typed HandleAsync returns ValueTask so needs just "return"
692+ source . AppendLine ( isUntypedMethod ? " return null;" : " return;" ) ;
686693 }
687694
688695 source . AppendLine ( "}" ) ;
@@ -870,7 +877,7 @@ private static void GenerateUntypedHandleMethod(IndentedStringBuilder source, Ha
870877 source . AppendLine ( "var serviceProvider = (System.IServiceProvider)mediator;" ) ;
871878
872879 // Emit the handler invocation code - use "typedMessage" since we cast the object message above
873- EmitHandlerInvocationCode ( source , handler , configuration , "result" , "typedMessage" ) ;
880+ EmitHandlerInvocationCode ( source , handler , configuration , "result" , "typedMessage" , isUntypedMethod : true ) ;
874881
875882 // For tuple returns, use PublishCascadingMessagesAsync for runtime dispatch
876883 if ( handler . ReturnType . IsTuple )
0 commit comments