SaturnFramework / Saturn

Opinionated, web development framework for F# which implements the server-side, functional MVC pattern
https://saturnframework.org
MIT License
703 stars 108 forks source link

use_grpc fails if service has multiple constructors #328

Closed queil closed 3 months ago

queil commented 2 years ago

Problem

I am trying use_grpc with ReflectionServiceImpl. It fails with the following exception:

Grpc.AspNetCore.Server.ServerCallHandler[6]
      Error when executing service method 'ServerReflectionInfo'.
      System.InvalidOperationException: Multiple constructors accepting all given argument types have been found in type 'Grpc.Reflection.ReflectionServiceImpl'. There should only be one applicable constructor.
         at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.TryFindMatchingConstructor(Type instanceType, Type[] argumentTypes, ConstructorInfo& matchingConstructor, Nullable`1[]& parameterMap)
         at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.FindApplicableConstructor(Type instanceType, Type[] argumentTypes, ConstructorInfo& matchingConstructor, Nullable`1[]& matchingParameterMap)
         at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateFactory(Type instanceType, Type[] argumentTypes)
         at Grpc.AspNetCore.Server.Internal.DefaultGrpcServiceActivator`1.<>c.<.cctor>b__4_0()
         at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
      --- End of stack trace from previous location ---
         at System.Lazy`1.CreateValue()
         at System.Lazy`1.get_Value()
         at Grpc.AspNetCore.Server.Internal.DefaultGrpcServiceActivator`1.Create(IServiceProvider serviceProvider)
         at Grpc.Shared.Server.DuplexStreamingServerMethodInvoker`3.Invoke(HttpContext httpContext, ServerCallContext serverCallContext, IAsyncStreamReader`1 requestStream, IServerStreamWriter`1 responseStream)
         at Grpc.Shared.Server.DuplexStreamingServerMethodInvoker`3.Invoke(HttpContext httpContext, ServerCallContext serverCallContext, IAsyncStreamReader`1 requestStream, IServerStreamWriter`1 responseStream)
         at Grpc.AspNetCore.Server.Internal.CallHandlers.DuplexStreamingServerCallHandler`3.HandleCallAsyncCore(HttpContext httpContext, HttpContextServerCallContext serverCallContext)
         at Grpc.AspNetCore.Server.Internal.CallHandlers.ServerCallHandlerBase`3.<HandleCallAsync>g__AwaitHandleCall|8_0(HttpContextServerCallContext serverCallContext, Method`2 method, Task handleCall)

Workaround

Inherit from ReflectionServiceImpl and use the derived class with use_grpc:

type MyReflectionServiceImpl(descriptors: Google.Protobuf.Reflection.ServiceDescriptor seq) =
  inherit ReflectionServiceImpl(descriptors)

let app =
  application {
    use_grpc MyReflectionServiceImpl
   // other config removed for clarity
  }

Details