.net-coredependency injection

我有一个Generic存储库,我想注册DI,它实现了一个接口IRepository。

通常我会像这样创建一个它的实例:

IRepository repo = new Repository(); 

但是我试图在发布之前加速.net 5,并希望将其与DI一起使用,我采用了以下方法:

 services.AddTransient<DAL.IRepository, DAL.Repository>(); 

但这感觉不对,我不希望在我的模型中的每个类中都有50多行…

我在网上找不到任何关于此的内容,我知道它可能与其他ioc容器有关..但由于这是一个学习项目,我不想使用另一个容器,我的目标是用.net5s本机容器来完成所有这些。

您应该能够注册开放通用

 services.AddTransient(typeof(IRepository<>), typeof(Repository<>)); 

在对其他答案的评论中进行了一些回复和转发后,我有一个有效的解决方案,它可能不是最好的方式,但它有效。 如果我找到更好的方法来实现这个,我会再次更新。

我遇到的两个问题是:需要注册一个通用接口,这里的问题是我的注意力集中。我注册了一个通用类型的语法错误当然是:

 services.AddTransient(typeof(IRepository<>), typeof(Repository<>)); 

第二个问题是我有一个包含50多个我想要注册的不同模型的程序集。我解决这个问题的方法是编写一个方法,我可以将程序集列表与我想要注册的Namespace一起传递给它迭代任何符合条件的类型,并将它们注册到DI容器中。

 public void RegisterModels(IServiceCollection services, string[] Assemblies, string @NameSpace) { foreach (var a in Assemblies) { Assembly loadedAss = Assembly.Load(a); var q = from t in loadedAss.GetTypes() where t.IsClass && !t.Name.Contains("<") && t.Namespace.EndsWith(@NameSpace) select t; foreach (var t in q.ToList()) { Type.GetType(t.Name); services.AddTransient(Type.GetType(t.FullName), Type.GetType(t.FullName)); } } } 

然后从startup.cs方法ConfigureServices调用它:

 public void ConfigureServices(IServiceCollection services) { // Add framework services. services.AddEntityFramework() .AddSqlServer() .AddDbContext(options => options.UseSqlServer(@"Server=LOCALHOST\SQLEXPRESS;Database=Test;Trusted_Connection=True;")); services.AddMvc(); RegisterModels(services, new string[] { "UI" }, "UI.Models"); services.AddTransient(typeof(IRepository<>), typeof(Repository<>)); } 

可能有更好的方法来做到这一点,肯定有使用不同的DI容器,如果有人提供改进请告诉我。

您可以使用基于会议的注册库,如Scrutor 。

Scrutor是一个小型开源库,它提供了一个流畅的API,可以根据约定在Microsoft.Extensions.DependencyInjection容器中注册服务(类似于Autofac的RegisterAssemblyTypes方法,StructureMap的Scan方法和Ninject的约定包)。

这将允许您执行以下操作:

 services.Scan(scan => scan .FromAssemblies(<>.GetTypeInfo().Assembly) .AddClasses(classes => classes.Where(x => { var allInterfaces = x.GetInterfaces(); return allInterfaces.Any(y => y.GetTypeInfo().IsGenericType && y.GetTypeInfo().GetGenericTypeDefinition() == typeof(IRepository<>))); })) .AsSelf() .WithTransientLifetime() ); 

您可以做的是创建一个扩展方法来封装所有需要注册的单个项目。

这与Microsoft正在使用的技术相同,例如您只在启动时使用它:

 services.AddMvc(); 

但这是一种扩展方法,在幕后你可以打赌它正在注册一堆它需要的东西。

所以你可以像这样创建自己的扩展方法:

 using Microsoft.Extensions.DependencyInjection; public static IServiceCollection AddMyFoo(this IServiceCollection services) { services.AddTransient, DAL.Repository>(); //.... return services; } 

并通过使该方法返回IServiceCollection,你可以使它流畅,所以你可以做

 services.AddMyFoo().AddSomeOtherFoo(); 

根据评论更新

另一种减少注册的技术是,当你的依赖项本身没有依赖项时,你可以使构造函数的默认值为null,这样你仍然可以解耦并在以后传递一个不同的但是DI不会抛出错误而你如果没有传入,你可以实例化你需要的东西。

 public class MyFoo(IFooItemDependency myItem = null) { private IFooItemDependency internalItem; public MyFoo(IFooItemDependency myItem = null) { internalItem = myItem ?? new FooItemItem(); } } 

我不是100%肯定你的问题我认为你不想拥有

 services.AddTransient, DAL.Repository>(); services.AddTransient, DAL.Repository>(); services.AddTransient, DAL.Repository>(); 

等等

我之前做过这个(用ninject)

 Bind(typeof(IRepository<>)).To(typeof(Repository<>)).InRequestScope(); 

我想,对于Unity你可以做类似的事情

 services.AddTransient, typeof(Repository<>)(); 

然后在服务中使用它

 public OrderService(IRepository orderRepository) { this.orderRepository = orderRepository; } 

编辑

正如OP指出的那样,正确的语法是:

 services.AddTransient(typeof(IRepository<>), typeof(Repository<>));