如何在多项目解决方案中使用.net核心依赖项注入?

如何在多项目解决方案中使用.net核心依赖项注入?

问题描述:

我是asp.net核心的新手。

我想做的是构建多项目解决方案,并使用依赖注入在项目之间传递接口。

我知道的是,在ASP.NET核心项目中,我们在 startup.cs 文件中具有 ConfigureServices 方法来注册我们的接口及其实现如下:

I'm new to asp.net core.
What I'm trying to do is to build multi projects solution and use dependency injection to pass interfaces between projects.
What I know is that in ASP.NET core project we have ConfigureServices method in startup.cs file to register our interfaces and their implementations like this:

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

如果您有课程,这很好全部都在同一个项目中,但是如果我有多个项目怎么办?

通常,我要做的是使用安装程序(Windsor安装程序)创建单独的项目,以注册所需的接口及其实现。

This is good if you have classes all in the same project, but what if I have multi projects ?
Usually what I'll do is create separate project with installers (Windsor installers) to register the needed interfaces and their implementations.

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

In .net core we can do this by creating static ServiceCollection(); and get from it static IServiceProvider to use it any time to get any service you register:

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>();
}

现在我们调用 RegisterationMethod 从较弱的启动项目开始,并继续照常进行开发,并始终在此类中注册服务。

这种方法的问题是,如果我在ASP.NET核心项目中使用它,则有两个地方可以在具有 ConfigureServices(IServiceCollection services) startup.cs 文件中注册一个服务和一个服务。 br>
您可能会说,

Now we call RegisterationMethod from ower startup project and continue to develop as usual with always registering the services in this class.
The problem in this approach is if I used it in ASP.NET core project I'll have two places to register the services, this one and the one in the startup.cs file which has ConfigureServices(IServiceCollection services) .
You may say,


OK pass IServiceCollection ConfigureServices(IServiceCollection服务)到以前创建的 RegisterationMethod 的方式中,这样您将使用相同的服务集合

OK pass IServiceCollection you had in ConfigureServices(IServiceCollection services) to the RegisterationMethod you previously created, in this way you're using the same services collection that ASP.NET using.

但是通过这种方式,我将与 .net核心。

But in this way I'll be tight coupled to the dependency injection module of the .net core.

有没有更清洁的方法?还是我应该用 Windsor 替换默认的DI?例如?

Is there more clean way to do this ? or should I have replace the default DI with Windsor for example ?


...在ASP.NET核心项目中,我们具有ConfigureServices ...以注册我们的接口及其实现...如果您在同一项目中都具有类,那么这很好,但是如果我有多个项目怎么办?

...in ASP.NET core project[s] we have ConfigureServices... to register our interfaces and their implementations... This is good if you have classes all in the same project, but what if I have multi projects?

不要紧,您有多个项目。遵循相同的原则:

It doesn't matter that you have multi projects. The same principle applies:

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

让我们假设您有一个引用多个类库的应用程序。在应用程序的启动类中,使用 ConfigureServices 注册所有依赖项。在每个类库项目中,使用构造函数注入。没关系,您的类是否位于相同或不同的项目中。

Lets assume that you have a single application that references several class libraries. In your application's Startup class, use ConfigureServices to register all of the dependencies. In each of the class library projects, use constructor injection. It does not matter whether your classes live in the same or in different projects.


OK将您在ConfigureServices(IServiceCollection services)中拥有的IServiceCollection传递给以前创建的RegisterationMethod,以这种方式,您正在使用与ASP.NET相同的服务集合。

OK pass IServiceCollection you had in ConfigureServices(IServiceCollection services) to the RegisterationMethod you previously created, in this way you're using the same services collection that ASP.NET using.

是的,做到的方式。这是来自github的示例.com / aspnet / logging存储库

Yes, that's the way to do it. Here is 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;
}



根据您的评论...



...听起来您正在尝试避免使用 合成根 。合成根是我们在依赖项注入容器中注册依赖项的单个位置。合成根目录放置在尽可能靠近应用程序入口点的位置(例如 ConfigureServices 方法),并且它属于应用程序而不是其库中。

Based on your comments...

...it sounds like you are trying to avoid having a composition root in your application. The composition root is the single location where we register dependencies with the dependency injection container. The composition root is placed as close as possible to the application's entry point (the ConfigureServices method, for instance) and it belongs in the application not in its libraries.