使用默认 ASP.NET Core DI 容器在 Service Fabric 上设置依赖注入

Posted

技术标签:

【中文标题】使用默认 ASP.NET Core DI 容器在 Service Fabric 上设置依赖注入【英文标题】:Set up Dependency Injection on Service Fabric using default ASP.NET Core DI container 【发布时间】:2019-06-08 16:20:20 【问题描述】:

我想使用 ASP.NET Core 的默认 DI 容器为我的 Service Fabric 项目设置 DI。

//This is what I've got so far, and it works great
ServiceRuntime.RegisterServiceAsync(
  "MyServiceType",
  context => new MyService(context, new MyMonitor()
).GetAwaiter().GetResult();

//This is how I use it
public MyService(StatefulServiceContext context, IMonitor myMonitor)
  : base(context)

  this._myMonitor = myMonitor;           

如果 MyMonitor 类依赖于 ConfigProvider 类,我将如何设置 DI,如下所示:

public MyMonitor(IConfigProvider configProvider)

  this._configProvider = configProvider;

【问题讨论】:

【参考方案1】:

我想这个问题会给你一些启发:Why does ServiceRuntime.RegisterServiceAsync return before the serviceFactory func completes?

从技术上讲,ServiceRuntime.RegisterServiceAsync() 是一个依赖注册,它需要你传递 serviceTypeName 和负责创建服务的工厂方法Func<StatelessServiceContext, StatelessService> serviceFactory

工厂方法接收上下文并返回服务(有状态或无状态)。

对于 DI,你应该提前注册所有依赖并调用解析服务来创建构造函数,比如:

var provider = new ServiceCollection()
            .AddLogging()
            .AddSingleton<IFooService, FooService>()
            .AddSingleton<IMonitor, MyMonitor>()
            .BuildServiceProvider();

ServiceRuntime.RegisterServiceAsync("MyServiceType",
    context => new MyService(context, provider.GetService<IMonitor>());
).GetAwaiter().GetResult();

PS:

永远不要在 DI 中注册上下文 (StatelessServiceContext\StatefulServiceContext),在共享进程方法中,多个分区可能托管在同一个进程上,并且会包含多个上下文。 此代码 sn-p 未测试,我过去使用过,无法验证是否匹配相同的代码,但非常接近使用的方法,可能需要一些调整。

【讨论】:

【参考方案2】:

嗨@OscarCabreraRodríguez

我正在致力于简化 Service Fabric Reliable Services 开发的项目,它对依赖注入场景具有强大的内置支持。

您可以找到一般信息project page、wiki 和有关依赖注入的具体信息here。

这个想法是项目将您从直接使用 Service 实例中抽象出来,而是为您提供一组更具体的对象。

这是一个简单的 ASP.NET Core 应用示例:

public static void Main(string[] args)

  new HostBuilder()
    .DefineStatefulService(
      serviceBuilder =>
      
        serviceBuilder
          .UseServiceType("ServiceType")
          .DefineAspNetCoreListener(
            listenerBuilder =>
            
              listenerBuilder
                .UseEndpoint("ServiceEndpoint")
                .UseUniqueServiceUrlIntegration()
                .ConfigureWebHost(
                  webHostBuilder => 
                   
                    webHostBuilder
                      .ConfigureServices(
                        services =>
                        
                          // You can configure as usual.
                          services.AddTransient<IMyService, MyService>();
                        )
                      .UseStartup<Startup>(); 
                  );
            );
      )
      .Build()
      .Run();

[Route("api")]
public class ApiController : Controller

  public ApiController(IMyService service)  

  [HttpGet]
  [Route("value")]
  public string GetValue()
  
    return $"Value from nameof(ApiController)";
  

希望我正确理解您的用例,并且此信息是相关的。

【讨论】:

感谢@Oleg Karasik,但我更喜欢使用 Diego Mendes 的答案(如下),因为它更接近我所寻找的

以上是关于使用默认 ASP.NET Core DI 容器在 Service Fabric 上设置依赖注入的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Core Web 应用程序系列- 使用ASP.NET Core内置的IoC容器DI进行批量依赖注入

ASP.NET Core Web 应用程序系列- 使用ASP.NET Core内置的IoC容器DI进行批量依赖注入(MVC当中应用)

从静态工厂类访问 ASP.NET Core DI 容器

替换 ASP.NET Core 内置 DI 容器中的服务注册?

向 ASP.NET Core DI 容器注册“类型化”gRPC 客户端

如何在 ASP.NET Core 中使控制器作用域或单例而不是瞬态?