在.net core中实现字段和属性注入的示例代码
副问题[/!--empirenews.page--]
简朴来说,行使Ioc模式必要两个步调,第一是把处事注册到容器中,第二是从容器中获取处事,我们一个一个接头并演化。这里不会思量行使如Autofac等级三方的容器来取代默认容器,只是提供一些简质朴用的小要领用于简化应用层的开拓。 将处事注入到容器 asp.netcore官方给出的在容器中注册处事要领是,要在Startup类的ConfigureServices要领中添加处事,如下所示: public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddSingleton(typeof(UserService)); services.AddSingleton(typeof(MsgService)); services.AddSingleton(typeof(OrderService)); } AddMvc要领添加了mvc模块内部用到的一些处事,这个是封装好的,一句话就行了,其他第三方组件也都提供了相同的Add要领,把本身内部必要的处事都封装好注册进去了。可是我们应用开拓职员行使的类,照旧必要一个一个写进去的,各人最常见的三层架构中的数据会见层和营业逻辑层即是此类处事,上面代码中我插手了三个营业处事类。这显然不是持久之计,我想各人在开拓中也会针对此题目做一些处理赏罚,这里说下我的,仅供参考吧。 办理要领就是批量注册!说到批量,就必要一个对象来标识一批对象,然后用这一个对象来节制这一批对象。在.net措施的天下中,有两个可选的脚色,一个是接口Interface,另一个是特征Attribute。 假如行使接口作为标识来行使,限定就远古板了,一个标识的信息不是绝对的单一,是不保举行使接口的,由于也许必要引入多个接谈锋气配合完成,以是我选择特征作为标识。特征相较与接口有什么特点呢?特征在运行时是类的实例,以是可以存储更多的信息。 下面我们简质朴现一个AppServiceAttribute: /// <summary> /// 标志处事 /// </summary> [AttributeUsage(AttributeTargets.Class, Inherited = false)] public class AppServiceAttribute : Attribute { } 这个特征类取名AppService有两个来由,一是指定是应用层的处事类,二是停止行使Service这样的通用定名和其他类库斗嘴。 有了标识,就可以批量处理赏罚了,我们在一个新的类中给IServiceCollection提供一个扩展要领,用来批量添加标志有AppService特征的处事到容器中。 public static class AppServiceExtensions { /// <summary> /// 注册应用措施域中全部有AppService特征的处事 /// </summary> /// <param></param> public static void AddAppServices(this IServiceCollection services) { foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { foreach (var type in assembly.GetTypes()) { var serviceAttribute = type.GetCustomAttribute<AppServiceAttribute>(); if (serviceAttribute != null) { services.AddSingleton(type); } } } } } 我们遍历应用措施中全部措施集,然后嵌套遍历每个措施齐集的全部范例,判定范例是否有AppService特征,假若有的话就添加到容器中,这里有点不自信哦,为什么呢,由于我是行使AddSingleton要领以单例模式将处事添加到容器中的,固然三层中的数据会见层和营业逻辑层绝大部门都可以行使单例,可是我们但愿更通用一些,各人都知道netcore自带的Ioc容器支持三种生命周期,以是我们修改AppServiceAttribute,添加一个Lifetime属性: [AttributeUsage(AttributeTargets.Class, Inherited = false)] public class AppServiceAttribute : Attribute { /// <summary> /// 生命周期 /// </summary> public ServiceLifetime Lifetime { get; set; } = ServiceLifetime.Singleton; } Lifetime的默认值我们配置成ServiceLifetime.Singleton是较量吻合的,由于大部门处事我们都但愿行使单例注册,一个公道的默认配置可以节减行使者许多代码,新手也许还会乐于复制粘贴,但老同道必定都深有领会。 有了Lifetime这个信息,我们就可以改造AddAppServices要领了,在判定serviceAttribute不为null后,行使下面的代码替代services.AddSingleton(type): switch (serviceAttribute.Lifetime) { case ServiceLifetime.Singleton: services.AddSingleton(serviceType, type); break; case ServiceLifetime.Scoped: services.AddScoped(serviceType, type); break; case ServiceLifetime.Transient: services.AddTransient(serviceType, type); break; default: break; } 此刻我们可以注册差异生命周期的处事了,只是该节制是在类的界说中,按理说,处事工具注册到容器中的生命周期,是不该该在类的界说中确定的,由于一个类的界说是独立的,界说好之后,行使者可以用任何一种容器支持的生命周期来注册实例。可是此时这样的计划是较量公道的,由于我们要办理的是应用层处事的批量注册,这类处事一样平常在界说的时辰就已经确定了行使方法,并且许多时辰处事的开拓者就是该处事的行使者!以是我们可以把这个当成公道的反范式计划。 今朝这样子,对付我来说,根基已经够用了,由于在应用层,我都是依靠实现编程的😀(哈哈,会不会许多人说咦......呢?)。计划模式说:“要依靠于抽象,不要依靠于详细”,这点我还没做到,我抽闲检修(呵呵,谁信呢!)。以是呢,我们的批量注入要支持那些优越的同窗。 从上面的代码不难发明,假如界说接口IA和着实现A:IA,并在A上添加AppService特征是不可的: public interface IA { } [AppService] public class A : IA { } 这个时辰我们并不能依靠IA编程,由于我们注册的处事类是A,实现类是A,我们必要注册成处事类是IA,实现类是A才可: public class HomeController : Controller { private IA a; public HomeController(IA a) { this.a = a; //这里a是null,不能行使 } } 让我继承改造,在AppServiceAttribute中,我们插手处事范例的信息: [AttributeUsage(AttributeTargets.Class, Inherited = false)] public class AppServiceAttribute : Attribute { /// <summary> /// 生命周期 /// </summary> public ServiceLifetime Lifetime { get; set; } = ServiceLifetime.Singleton; /// <summary> /// 指定处事范例 /// </summary> public Type ServiceType { get; set; } /// <summary> /// 是否可以从第一个接口获取处事范例 /// </summary> public bool InterfaceServiceType { get; set; } = true; } 我们从两个方面入手来办理处事范例的题目,一个是指定ServiceType,这个就毫无疑问了,在A的AppService中可以明晰指定IA为其处事类: [AppService(ServiceType = typeof(IA))] public class A : IA { } (编辑:湖南网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |