在ASP.NET Core - 依賴注入這篇文章裏面,咱們知道了如何利用ASP.NET Core原生的容器來實現依賴注入的,那咱們爲何要替換掉默認的 IoC容器呢?從ASP.NET Core - 依賴注入這篇文章來看的話,默認的IoC容器對於一些小型的項目基本夠用,它提供了基本的AddXXXX方法來綁定實例關係,可是對於大型項目來講,仍是挺困難的,大型的項目須要的是通用的註冊,不可能手動添加每一個對象的解析關係,這纔是咱們面臨的痛點。html
這裏不打算詳解Castle的內容,專一於如何使用Castle實現通用註冊和替換掉原生的IoC容器。api
首先咱們須要一個通用的註冊類,是基於咱們自定義規則來註冊的,好比說在程序集中知足繼承ITransientDependency的話咱們會給實現類註冊爲Transient的生命週期,ISingletonDependency會給實現類註冊爲Singleton的生命週期。框架
/// <summary> /// 經過輸入的程序集來註冊知足約定的全部類 /// </summary> public class BasicConventionalRegistrar { private readonly WindsorContainer _container = new WindsorContainer(); /// <summary> /// 註冊程序集中知足約定的類 /// </summary> /// <param name="assemblies"></param> /// <returns></returns> public WindsorContainer RegisterAssembly(List<Assembly> assemblies) { foreach (var assembly in assemblies) { //Transient _container.Register( Classes.FromAssembly(assembly) .IncludeNonPublicTypes() .BasedOn<ITransientDependency>() .If(type => !type.GetTypeInfo().IsGenericTypeDefinition) .WithService.Self() .WithService.DefaultInterfaces() .LifestyleTransient() ); //Singleton _container.Register( Classes.FromAssembly(assembly) .IncludeNonPublicTypes() .BasedOn<ISingletonDependency>() .If(type => !type.GetTypeInfo().IsGenericTypeDefinition) .WithService.Self() .WithService.DefaultInterfaces() .LifestyleSingleton() ); } return _container; } }
有個這個類,咱們須要把各個程序集中知足條件的類註冊進來,首先須要在NuGet下載Castle.Windsor.MsDependencyInjection包,而且在ConfigureServices方法中修改返回類型爲IServiceProvider,而後經過RegistBasicConventionalRegistrar把各個須要註冊的程序集註冊進來。ide
這裏須要很是注意的是,在ASP.NET Core - 依賴注入這篇文章裏面提到ConfigureServices是能夠返回一個IServiceProvider對象的,這裏是基於這個返回對象引入了第三方容器替換。post
public IServiceProvider ConfigureServices(IServiceCollection services) { services.AddMvc(); var container = RegistBasicConventionalRegistrar(); //替換容器 return WindsorRegistrationHelper.CreateServiceProvider(container, services); } //通用規則註冊 private WindsorContainer RegistBasicConventionalRegistrar() { var list = new List<Assembly>(); list.Add(Assembly.GetExecutingAssembly ()); list.Add(yourProjectAssembly); ... return BasicConventionalRegistrar.RegisterAssembly(list); }
上面的代碼咱們能夠看到,主要是利用了WindsorRegistrationHelper這個類實現註冊到Windsor Castle容器中,且核心方法RegistBasicConventionalRegistrar是基於程序集註冊的。在正式的應用場景中,咱們是很是可能須要把多個程序集都按約定來註冊的,我的建議的作法是,在每一個須要註冊的程序集中添加一個標誌該程序集的基類,好比說我會在Service這個程序集中添加一個IServiceBase接口,這樣就能夠經過typeof(IServiceBase).Assembly獲取到這個程序集進而用來註冊this
在咱們的service業務層(或者任何須要註冊的地方),把須要註冊的類繼承通用註冊接口(生命週期本身選擇)spa
public interface IPostBlogService : ITransientDependency {
Result Post(BlogDto dto); } public class PostBlogService : IPostBlogService { public Result Post(BlogDto dto)
{
//todo: post this blog
} }
在任何須要的地方經過構造方法注入(或屬性注入)版本控制
[ApiController]
[Route("api/Blog")]
public class BlogController: Controller { public readonly IBlogService _blogService; public BlogController(IBlogService blogService) { _blogService = blogService; } [HttpPost] public Result PostBlog(BlogDto dto) { return _blogService.Post(dto); } }
這樣就實現了完整的通用註冊解析流程,在實際應用中,我的建議把這些通用解析方法放在基礎設施模塊,由於這樣不只本項目能夠用,還能夠把基礎設施抽離出來做爲基礎框架,經過nuget使用版本控制做爲公司全部項目的通用註冊礎框架。code
讓我知道若是你有更好的想法或建議!htm