如何在.net核心库项目中将一个类注入另一个类? 我应该在哪里配置DI,就像在API项目中的Startup Class ConfigureServices中完成的那样?
答案 0 :(得分:3)
经过大量的搜索后,我无法找到有关此问题的完整示例。这是在类库中使用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();
}
答案 1 :(得分:2)
如何管理此问题有很多思考过程,最终,呼叫者将需要为您注册DI流程。
如果您查看Microsoft和其他公司使用的方法,通常将定义一个扩展方法,该方法使用IAddCollection的扩展方法定义为“ AddMyCustomLibrary”之类的方法。 上有一些讨论。
答案 2 :(得分:1)
依赖注入配置在组合根,基本上是应用程序入口点。如果您无法控制应用程序入口点,则无法强制任何人对您的类库使用依赖注入。但是,您可以使用基于接口的编程并创建帮助程序类来为各种组合根场景注册库中的每种类型,这将允许人们使用 IOC 来实例化您的服务,而不管他们正在创建什么类型的程序。
你可以做的是让你的类库中的服务依赖于你库中其他服务的接口,这样使用它们的自然方法就是将你的服务注册到正在使用的容器中,并允许更高效单元测试。
答案 3 :(得分:0)
您可以使用Hosting Startup程序集类库来从调用程序集中显式注册它们。
[assembly: HostingStartup(typeof(HostingStartupLibrary.ServiceKeyInjection))]
namespace HostingStartupLibrary
{
public class Startup : IHostingStartup
{
public void Configure(IWebHostBuilder builder)
{
builder.ConfigureServices((context, services) => {
services.AddSingleton<ServiceA>();
});
}
}
}
答案 4 :(得分:0)
我不确定我是否完全理解您的意图...但也许您可以让您的实现旋转自己的私有 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
访问某些服务,您可以创建一些东西将它们绑定在一起:
public static void BindParentProvider(IServiceProvider parent) {
_services.AddSingleton<SomeService>(() => parent.GetRequiredService<SomeService>());
}
不过,我很确定有更好的方法来创建嵌套的 ServiceProvider
。