class 库中的 .NET Core 中的依赖注入
Dependency Injection in .NET Core inside a class library
如何在 .NET Core 库项目中将一个 class 注入另一个?
我应该在哪里配置 DI,因为它是在 StartUp Class ConfigureServices in API 项目中完成的?
关于如何管理这个有很多思考过程,因为最终,调用者将需要为您注册您的 DI 过程。
如果您查看 Microsoft 和其他公司使用的方法,您通常会使用 "AddMyCustomLibrary" 等方法定义扩展方法作为 IServiceCollection 的扩展方法。对此有一些讨论。
You can use Hosting Startup assemblies class library as an alternative to explicitly register them from the calling assembly.
[assembly: HostingStartup(typeof(HostingStartupLibrary.ServiceKeyInjection))]
namespace HostingStartupLibrary
{
public class Startup : IHostingStartup
{
public void Configure(IWebHostBuilder builder)
{
builder.ConfigureServices((context, services) => {
services.AddSingleton<ServiceA>();
});
}
}
}
经过大量谷歌搜索后,我无法找到包含此问题示例的全面答案。这是在 Class 库中使用 DI 应该做的事情。
在您的图书馆中:
public class TestService : ITestService
{
private readonly ITestManager _testManager;
public TestService(ITestManager testManager)
{
_testManager = testManager;
}
}
public class TestManager : ITestManager
{
private readonly ITestManager _testManager;
public TestManager()
{
}
}
然后在库中扩展IServiceCollection:
public static class ServiceCollectionExtensions
{
public static void AddTest(this IServiceCollection services)
{
services.AddScoped<ITestManager, TestManager>();
services.AddScoped<ITestService, TestService>();
}
}
最后在主应用启动(API、控制台等)中:
public void ConfigureServices(IServiceCollection services)
{
services.AddTest();
}
依赖注入在组合根配置,基本上是应用程序入口点。如果您无法控制应用程序入口点,则不能强迫任何人对您的 class 库使用依赖注入。但是,您可以使用基于接口的编程并创建帮助程序 classes 来为各种组合根场景注册库中的每种类型,这将允许人们使用 IOC 来实例化您的服务,无论他们正在创建什么类型的程序.
您可以做的是让您的 class 库中的服务依赖于您库中其他服务的接口,以便使用它们的自然方式是向正在使用的容器注册您的服务并允许更有效的单元测试。
我不确定我是否完全理解您的意图...但也许您可以让您的实现自旋它自己的私有 ServiceProvider
,像这样:
using System.IO;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
public class MyBlackBox {
private readonly IServiceProvider _services = BuildServices();
protected MyBlackBox() {}
public static MyBlackBox Create() {
return _services.GetRequiredService<MyBlackBox>();
}
private static void ConfigureServices(IServiceCollection services) {
services.AddTransient<MyBlackBox>();
// insert your dependencies here
}
private static IServiceProvider BuildServices() {
var serviceCollection = new ServiceCollection();
serviceCollection.AddLogging();
serviceCollection.AddOptions();
serviceCollection.AddSingleton(config);
serviceCollection.AddSingleton<IConfiguration>(config);
ConfigureServices(serviceCollection);
return serviceCollection.BuildServiceProvider();
}
private static IConfigurationRoot BuildConfig() {
var path = Directory.GetCurrentDirectory();
var builder = new ConfigurationBuilder().SetBasePath(path).AddJsonFile("appsettings.json");
return builder.Build();
}
}
然后您可以在“父”ServiceProvider 上注册您的实现,并且您的依赖项不会在其上注册。
缺点是您必须重新配置所有内容,主要是日志记录和配置。
如果您需要从父 ServiceProvider
访问一些服务,您可以创建一些东西将它们绑定在一起:
public static void BindParentProvider(IServiceProvider parent) {
_services.AddSingleton<SomeService>(() => parent.GetRequiredService<SomeService>());
}
不过,我很确定有更好的方法来创建嵌套 ServiceProvider
。
你可以看看ServiceCollection扩展模式。
https://dotnetcoretutorials.com/2017/01/24/servicecollection-extension-pattern/
如果你在class库中写这个扩展,你可以在其中注入classes/services。
但不知道这个模式好不好?
这样我就可以调用已附加服务的图书馆,只需使用它们即可。
这对我有用:
public class LibraryBase
{
ctor... (múltiple services)
public static IHostBuilder CreateHostBuilder(IHostBuilder host)
{
return host.ConfigureServices(... services)
}
}
主要:
public class Program
{
Main{... ConfigureServicesAsync()}
private static async Task ConfigureServicesAsync(string[] args)
{
IHostBuilder? host = new HostBuilder();
host = Host.CreateDefaultBuilder(args);
LibraryBase.CreateHostBuilder(host);
host.ConfigureHostConfiguration()
// ... start app
await host.StartAsync();
}
}
如何在 .NET Core 库项目中将一个 class 注入另一个? 我应该在哪里配置 DI,因为它是在 StartUp Class ConfigureServices in API 项目中完成的?
关于如何管理这个有很多思考过程,因为最终,调用者将需要为您注册您的 DI 过程。
如果您查看 Microsoft 和其他公司使用的方法,您通常会使用 "AddMyCustomLibrary" 等方法定义扩展方法作为 IServiceCollection 的扩展方法。对此有一些讨论
You can use Hosting Startup assemblies class library as an alternative to explicitly register them from the calling assembly.
[assembly: HostingStartup(typeof(HostingStartupLibrary.ServiceKeyInjection))]
namespace HostingStartupLibrary
{
public class Startup : IHostingStartup
{
public void Configure(IWebHostBuilder builder)
{
builder.ConfigureServices((context, services) => {
services.AddSingleton<ServiceA>();
});
}
}
}
经过大量谷歌搜索后,我无法找到包含此问题示例的全面答案。这是在 Class 库中使用 DI 应该做的事情。
在您的图书馆中:
public class TestService : ITestService
{
private readonly ITestManager _testManager;
public TestService(ITestManager testManager)
{
_testManager = testManager;
}
}
public class TestManager : ITestManager
{
private readonly ITestManager _testManager;
public TestManager()
{
}
}
然后在库中扩展IServiceCollection:
public static class ServiceCollectionExtensions
{
public static void AddTest(this IServiceCollection services)
{
services.AddScoped<ITestManager, TestManager>();
services.AddScoped<ITestService, TestService>();
}
}
最后在主应用启动(API、控制台等)中:
public void ConfigureServices(IServiceCollection services)
{
services.AddTest();
}
依赖注入在组合根配置,基本上是应用程序入口点。如果您无法控制应用程序入口点,则不能强迫任何人对您的 class 库使用依赖注入。但是,您可以使用基于接口的编程并创建帮助程序 classes 来为各种组合根场景注册库中的每种类型,这将允许人们使用 IOC 来实例化您的服务,无论他们正在创建什么类型的程序.
您可以做的是让您的 class 库中的服务依赖于您库中其他服务的接口,以便使用它们的自然方式是向正在使用的容器注册您的服务并允许更有效的单元测试。
我不确定我是否完全理解您的意图...但也许您可以让您的实现自旋它自己的私有 ServiceProvider
,像这样:
using System.IO;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
public class MyBlackBox {
private readonly IServiceProvider _services = BuildServices();
protected MyBlackBox() {}
public static MyBlackBox Create() {
return _services.GetRequiredService<MyBlackBox>();
}
private static void ConfigureServices(IServiceCollection services) {
services.AddTransient<MyBlackBox>();
// insert your dependencies here
}
private static IServiceProvider BuildServices() {
var serviceCollection = new ServiceCollection();
serviceCollection.AddLogging();
serviceCollection.AddOptions();
serviceCollection.AddSingleton(config);
serviceCollection.AddSingleton<IConfiguration>(config);
ConfigureServices(serviceCollection);
return serviceCollection.BuildServiceProvider();
}
private static IConfigurationRoot BuildConfig() {
var path = Directory.GetCurrentDirectory();
var builder = new ConfigurationBuilder().SetBasePath(path).AddJsonFile("appsettings.json");
return builder.Build();
}
}
然后您可以在“父”ServiceProvider 上注册您的实现,并且您的依赖项不会在其上注册。
缺点是您必须重新配置所有内容,主要是日志记录和配置。
如果您需要从父 ServiceProvider
访问一些服务,您可以创建一些东西将它们绑定在一起:
public static void BindParentProvider(IServiceProvider parent) {
_services.AddSingleton<SomeService>(() => parent.GetRequiredService<SomeService>());
}
不过,我很确定有更好的方法来创建嵌套 ServiceProvider
。
你可以看看ServiceCollection扩展模式。
https://dotnetcoretutorials.com/2017/01/24/servicecollection-extension-pattern/
如果你在class库中写这个扩展,你可以在其中注入classes/services。
但不知道这个模式好不好?
这样我就可以调用已附加服务的图书馆,只需使用它们即可。
这对我有用:
public class LibraryBase
{
ctor... (múltiple services)
public static IHostBuilder CreateHostBuilder(IHostBuilder host)
{
return host.ConfigureServices(... services)
}
}
主要:
public class Program
{
Main{... ConfigureServicesAsync()}
private static async Task ConfigureServicesAsync(string[] args)
{
IHostBuilder? host = new HostBuilder();
host = Host.CreateDefaultBuilder(args);
LibraryBase.CreateHostBuilder(host);
host.ConfigureHostConfiguration()
// ... start app
await host.StartAsync();
}
}