2、实例对象注册( Instance Components ),Demo代码所示:var output = new StringWriter();builder.RegisterInstance(output).As().ExternallyOwned(); , 其中方法 ExternallyOwned 可以忽略容器对 实例对象的释放控制,同时也可以注册 单例对象 使用,且需要注意注册单例实例对象释放应该由开发人员控制而不是容器 。
3、Lambda 表达式组件注册 ( Lambda Expression Components ),builder.Register(c => new A(c.Resolve()));,其中表达式的灵活性和性能优化,是官方推荐的注册方式,分别体现在 利用表达式可以自定义解析依赖项和传递需要的构造函数( 也包含注册依赖的属性和根据参数自定义注册流程 )等等,其次就是表达式对于性能有一定的提升相对于反射而言。
4、泛型组件注册 (Open Generic Components):
builder.RegisterGeneric(typeof(NHibernateRepository<>)).As(typeof(IRepository<>)).InstancePerLifetimeScope();这个便是我们经常使用的API了,也就是我们对仓储服务的注册,但是我们实体有很多,所以这里就 需要泛型注册可以批量注入到容器中去,而且需要单独对某一个具体类型例如 NHibernateRepository 注册就会覆盖泛型的注入,同理解析服务的时候也会实例具体对象的服务实例。
其他备注注意事项:
关于 组件与服务 的注意点:当一个组件如下注册为服务的时候 :
如果 需要解析组件本身需要加上AsSelf() ,关键的 AsSelf 来表示,不然注册为服务会覆盖掉组件本身的注册结果。
默认注册情况下, 多个组件注册同一个接口,以最后一个为准,除非使用 Named 支持多组件同一个服务注册关系,且如果使用API:PreserveExistingDefaults ,可以是的第一个注册为默认项。
条件注册:主要API,OnlyIf 方法提供Lambda表达式表示指定条件下发生,IfNotRegistered 方法同理注定没注册条件下发生。
将 参数传递给组件作为注册需求 ,通过 表达式注册或者显示使用 WithParameter 方法传递即可,同样也可以在解析的传递参数也是可以的。
属性注册:通过表达式或者利用OnActivated事件来主动解析,如果注册的是反射组件需要使用 PropertiesAutowired 来突出属性的注入,同样提供了 WithProperty 来主动注入对应属性名的依赖项。
程序集扫描注册:RegisterAssemblyTypes 可以自定义扫描程序集逻辑指定类型注册,可以使用 Except 排除不需要的类型,AsImplementedInterfaces 注册为类型对应的公开接口服务类型,RegisterAssemblyModules 注册自定义module,实现批量套件式注册,注意如果宿主程序使用iis,如果使用iis回收,触发程序集重载,需要使用 var assemblies = BuildManager.GetReferencedAssemblies().Cast();获取最新加载的程序集扫描
解析主要的方法便是 Resolve ,解析可以通过 NamedParameter 、TypedParameter 、ResolvedParameter 三种方式传递解析组件所需要的参数依赖,关于容器中的不同关系类型的不同解析方式有所不同,具体参考:,其实官方提供这么多重载或者API函数只是为了广大玩家的易用性,至于平时开发过程中,使用的API数量相对来说还是有限的,那博主自身情况设定,直接依赖和延迟实例化对象用到过了,还有一点:关于可枚举对象服务组件的注册,也就是一个接口多个实现类,解析接口默认如果没有注册回抛出异常,但是如下方式则是为empty,scope.Resolve>();
控制作用域和组件存活生命周期根据官方的说法,其中有两点是值得开发人员注意的:
1、生命周期范围是可嵌套的,它们控制组件如何共享。例如,单例服务可能从根生存期范围解决,而单个工作单元可能需要自己的其他服务实例,你可以通过在注册时设置其实例范围来确定组件的共享方式。例如 UserService 需要 RoleRepository 需要它们的scope处于处于同一个层次
2、using scope会主动追踪范围内组件,并在释放范围内组件在scope结束的时候。例如,如果您有一个实现了IDisposable的组件,并且您可以从scope范围内解析出来,则该scope范围将为你处理该对象的释放工作,自动处理让使用者不必知道底层实现。但是如果不需要自动管理,你可以控制此行为或添加新的处置行为。
始终从scope范围内解析服务而非根容器,这一点很重要。由于生命周期范围的跟踪特性,如果您从跟容器中解析了大量的一次性组件,则可能会无意中造成内存泄漏,因为根容器将持有对那些一次性组件的引用(通常是应用程序的生命周期)。如果Autofac检测到单例或共享组件的使用情况,它会自动将其放入适当的跟踪范围。所以上诉的情况,可以理解为尽量使用自建scope来解析服务组件,而跟容器就应该注册类似单例服务,与容器和应用程序本属于一个生命周期的东西