【问题标题】:How to use .net core dependency injection in multiprojects solution?如何在多项目解决方案中使用 .net 核心依赖注入?
【发布时间】:2016-10-22 19:55:06
【问题描述】:

我是 asp.net core 的新手。
我要做的是构建多项目解决方案并使用依赖注入在项目之间传递接口。
我所知道的是,在 ASP.NET 核心项目中,我们在 startup.cs 文件中有 ConfigureServices 方法来注册我们的接口及其实现,如下所示:

 public void ConfigureServices(IServiceCollection services)
 {
   // Add framework services.
   services.AddMvc();
   services.AddTransient<IMyInterface,MyImplementation>();
   .....
 }

如果您的课程都在同一个项目中,这很好,但是如果我有多个项目呢?
通常我要做的是使用安装程序(Windsor 安装程序)创建单独的项目来注册所需的接口及其实现。

在 .net 核心中,我们可以通过创建静态 ServiceCollection(); 并从中获取静态 IServiceProvider 来随时使用它来获取您注册的任何服务:

public static IServiceCollection _serviceCollection { get; private set; }
public static IServiceProvider serviceProvider { get; private set; }
public static RegisterationMethod() {
   _serviceCollection = new ServiceCollection();

   _serviceCollection.AddSingleton<IMyInterface,MyImplementation>();
   .....
   serviceProvider = _serviceCollection.BuildServiceProvider();
}

public T GetService<T>() where T : class
{
   return serviceProvider.GetService<T>();
}

现在我们从 ower 启动项目中调用RegisterationMethod 并继续照常开发,始终在此类中注册服务。
这种方法的问题是,如果我在 ASP.NET 核心项目中使用它,我将有两个地方来注册服务,这个和 startup.cs 文件中的一个具有 ConfigureServices(IServiceCollection services)
你可能会说,

好的,将ConfigureServices(IServiceCollection services) 中的IServiceCollection 传递给您之前创建的RegisterationMethod,这样您就可以使用与 ASP.NET 相同的服务集合。

但是通过这种方式,我将与.net core 的依赖注入模块紧密耦合。

有没有更干净的方法来做到这一点?或者我应该用 Windsor 替换默认 DI 吗?

【问题讨论】:

    标签: dependency-injection asp.net-core castle-windsor .net-core


    【解决方案1】:

    ...在 ASP.NET 核心项目[s]中,我们有 ConfigureServices... 来注册我们的接口及其实现...如果您在同一个项目中都有类,这很好,但是如果我有多个项目?

    拥有多个项目并不重要。同样的原则也适用:

    将您的组合根放在您的应用程序中,尽可能靠近入口点。

    假设您有一个引用多个类库的应用程序。在应用程序的Startup 类中,使用ConfigureServices 注册所有依赖项。在每个类库项目中,使用构造函数注入。您的课程是在同一个项目中还是在不同的项目中并不重要。

    好的,将您在 ConfigureServices(IServiceCollection services) 中的 IServiceCollection 传递给您之前创建的 RegisterationMethod,这样您就可以使用与 ASP.NET 相同的服务集合。

    是的,就是这样做的。这里是an example from the github.com/aspnet/logging repository

    public static IServiceCollection AddLogging(this IServiceCollection services)
    {
        if (services == null)
        {
            throw new ArgumentNullException(nameof(services));
        }
    
        services.TryAdd(ServiceDescriptor.Singleton<ILoggerFactory, LoggerFactory>());
        services.TryAdd(ServiceDescriptor.Singleton(typeof(ILogger<>), typeof(Logger<>)));
    
        return services;
    }
    

    根据您的 cmets...

    ...听起来您正试图避免在您的应用程序中使用composition root。组合根是我们向依赖注入容器注册依赖的唯一位置。组合根尽可能靠近应用程序的入口点(例如 ConfigureServices 方法),它属于应用程序而不是其库。

    【讨论】:

    • 我有 asp.net 核心项目,和多层:(服务,存储库,..),你建议的方式是在这个 web 项目中引用我所有的接口和实现,我没有这是一个好方法吗?这就是为什么我想创建单独的项目来注册所有这些。
    • 是的,正确,所以MyApp 实际上只会引用MyServices 来获取\设置数据,而MyServices 只会引用MyRepositories ...
    • 我认为这不是一个好习惯,这样您就可以访问MyRepositories 实现,那么为什么需要存储库层?以前我曾经有一个核心项目,它注册所有层并仅从我的启动项目中调用注册方法。
    • 抱歉,这不是我想要的,我需要一种方法来在另一个项目中获取服务集合,而无需创建新项目。
    • @Dabbas:应用程序是您连接 DI 的地方,因为从应用程序到应用程序,您使用它的方式可能会有所不同,因此不可能让库自己处理/引导。 ASP.NET Core 库通常将其抽象为 AddXxx() 方法和 .UseXxx(中间件注册),因此您可以在 Startup 类中执行 services.AddMyAppBusinessServices() 等。没有像 Unity 或 Windsor 那样开箱即用的模块支持,您必须编写扩展方法或自己的模块系统或使用 3rd 方 IoC 容器
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-14
    • 1970-01-01
    • 2017-09-07
    • 1970-01-01
    • 1970-01-01
    • 2019-02-16
    • 1970-01-01
    相关资源
    最近更新 更多