gpt4 book ai didi

c# - 在项目之间共享 Microsoft.Extensions.DependencyInjection.ServiceProvider 配置

转载 作者:太空宇宙 更新时间:2023-11-03 18:53:32 25 4
gpt4 key购买 nike

我有一个包含以下项目的解决方案

  • Acme.Core
  • Acme.Domain
  • Acme.Repositories
  • Acme.Services
  • Acme.Web

过去,我在完整的框架项目中使用 Unity 进行 DI。我能够将具体对象注册到可执行项目(Web 应用程序、控制台应用程序、测试应用程序)中的接口(interface)映射。

我正在尝试使用 .NET Core 实现相同的方法。我想先尝试使用 Microsoft.Extensions.DependencyInjection 库。在 ASP.NET Core 应用程序中,它运行良好。不幸的是,当我尝试将该实例与其他项目(例如 .NET Standard 库)的注册共享/引用时遇到了问题。

我的想法是将 ServiceProvider 注入(inject)到服务的构造函数中:

public class AddressService : BaseService, IAddressService
{
private readonly IServiceProvider _serviceProvider;

public AddressService(IServiceProvider serviceProvider, string userOrProcessName)
{
_serviceProvider = serviceProvider;
}

public IReadOnlyList<IState> GetAllStates()
{
_serviceProvider.GetService<IAddressRepository>();

// other logic removed
}
}

我在 Startup.ConfigureServices() 中尝试了以下内容:

services.AddTransient<IAddressService>(s => new AddressService(HttpContext.RequestServices, Environment.UserName));

我遇到的问题是我无法在 Controller 外部引用 HttpContext.RequestServices。我还没有想出另一种传递 ServiceProvider 实例的方法。

我的问题:

  1. 如何传递当前 ServiceProvider 的引用?
  2. 是否有更好的设计来实现我在多个库中共享 Microsoft.Extensions.DependencyInjection 配置的目标?

最佳答案

防止将 IServiceProvider 注入(inject)到您的应用程序组件中;导致 Service Locator anti-pattern .

相反,您应该仅使用构造函数注入(inject) 来构建应用程序组件。这意味着您的 AddressService 应该需要 IAddressRepository 作为构造函数参数,而不是 IServiceProvider。例如:

public class AddressService : IAddressService
{
private readonly IAddressRepository repo;

public AddressService(IAddressRepository repo, IUserContext userContext)
{
this.repo = repo;
}

public IReadOnlyList<IState> GetAllStates()
{
// other logic removed
}
}

还要尽量避免将原始数据注入(inject)到您的构造函数中。这本身并不是一个坏习惯,但它确实使对象图的构造复杂化。相反,要么将该值包装到一个类中,以防它是一个配置值,要么将它隐藏在抽象背后(如上所示)以防它是一个运行时值。

这两种做法都简化了您的应用程序代码和 Composition Root .

例如,这将是先前 AddressService 重新设计的结果:

services.AddTransient<IAddressRepository, SqlAddressRepository>();
services.AddTransient<IAddressService, AddressService>();
services.AddScoped<IUserContext, UserContext>();
services.AddHttpContextAccessor();

在这里,UserContext 可以定义如下:

public class UserContext : IUserContext
{
private readonly IHttpContextAccessor accessor;
public UserContext(IHttpContextAccessor accessor) => this.accessor = accessor;
public string UserName => this.accessor.HttpContext.User.Identity.Name;
}

关于c# - 在项目之间共享 Microsoft.Extensions.DependencyInjection.ServiceProvider 配置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51087472/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com