ASP.NET Core本身已经集成了一个轻量级的IOC容器,开发者只需要定义好接口后,在Startup.cs的ConfigureServices方法里使用对应生命周期的绑定方法即可, 常用的有如下三种方法:
services.AddTransient<IApplicationService,ApplicationService>
services.AddScoped<IApplicationService,ApplicationService>
services.AddSingleton<IApplicationService,ApplicationService>
- Transient
Transient 服务在每次请求时被创建,它最好被用于轻量级无状态服务(如我们的Repository和ApplicationService服务) - Scoped
Scoped 服务在每次请求时被创建,生命周期横贯整次请求 - Singleton 顾名思义,Singleton(单例) 服务在第一次请求时被创建(或者当我们在ConfigureServices中指定创建某一实例并运行方法),其后的每次请求将沿用已创建服务。如果开发者的应用需要单例服务情景,请设计成允许服务容器来对服务生命周期进行操作,而不是手动实现单例设计模式然后由开发者在自定义类中进行操作。
但是一旦项目变的大 ,要注入的也就很多了,如果一个个添加会十分麻烦,于是可以利用找到程序集里所有需要注入的接口及其实现实现注入。
首先添加一个 IocRegisterAttribute 特性
using System; namespace DotNetCoreWeb.Attribute { public class IocRegisterAttribute:System.Attribute { public Type RegisterType { get; private set; } public string Name { get; private set; } public IocRegisterAttribute() : this(null, null) { } public IocRegisterAttribute(Type register_type) : this(register_type, null) { } public IocRegisterAttribute(string name) : this(null, name) { } public IocRegisterAttribute(Type registerType, string name) { this.RegisterType = registerType; this.Name = name; } } }
其用法是在指定的类上加上,便于搜素程序集时注入需要注入的实例。
下面写具体的通过程序集名称注入方法:使用扩展方法
/// <summary> /// IServiceCollection扩展 /// </summary> public static class ServiceExtension { /// <summary> /// 用DI批量注入接口程序集中对应的实现类。 /// <para> /// 需要注意的是,这里有如下约定: /// IUserService --> UserService, IUserRepository --> UserRepository. /// </para> /// </summary> /// <param name="service"></param> /// <param name="interfaceAssemblyName">接口程序集的名称(不包含文件扩展名)</param> /// <returns></returns> public static IServiceCollection RegisterAssembly(this IServiceCollection service,string[] IocAssemblyNames) { foreach(var name in IocAssemblyNames){ RegisterType(name,service); } return service; } public static void RegisterType(string assemblyName, IServiceCollection service) { Type[] types = Assembly.Load(assemblyName).GetTypes(); foreach (Type type in types) { System.Attribute[] attrs = System.Attribute.GetCustomAttributes(type); foreach (System.Attribute attr in attrs) { if (attr is IocRegisterAttribute) { var attribute = attr as IocRegisterAttribute; var baseTypes = new List<Type>(); if (attribute.RegisterType != null) { baseTypes.Add(attribute.RegisterType); } else if (type.GetInterfaces().Any()) { baseTypes.AddRange(type.GetInterfaces()); } if (type.BaseType != null && type.BaseType != typeof (Object)) { Type bt = type.BaseType; while (bt.BaseType != null && bt.BaseType != typeof (Object)) bt = bt.BaseType; baseTypes.Add(bt); } if (baseTypes.Count <= 0) throw new Exception(string.Format("类型"{0}"没有基类型", type)); foreach (Type baseType in baseTypes) { service.AddTransient(baseType,type); } } } } } }
只需在Startup中调用
IocAssemblyName在appsettiings中定义,如果多个程序集则用','隔开。