问题引入
在 ASP.NET Core - 依赖注入这篇文章里面, 我们知道了如何利用 ASP.NET Core 原生的容器来实现依赖注入的, 那我们为什么要替换掉默认的 IoC 容器呢? 从 ASP.NET Core - 依赖注入这篇文章来看的话, 默认的 IoC 容器对于一些小型的项目基本够用, 它提供了基本的 AddXXXX 方法来绑定实例关系, 但是对于大型项目来说, 还是挺困难的, 大型的项目需要的是通用的注册, 不可能手动添加每个对象的解析关系, 这才是我们面临的痛点.
解决方案
这里不打算详解 Castle 的内容, 专注于如何使用 Castle 实现通用注册和替换掉原生的 IoC 容器.
首先我们需要一个通用的注册类, 是基于我们自定义规则来注册的, 比如说在程序集中满足继承 ITransientDependency 的话我们会给实现类注册为 Transient 的生命周期
- /// <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 把各个需要注册的程序集注册进来.
这里需要非常注意的是, 在 ASP.NET Core - 依赖注入这篇文章里面提到 ConfigureServices 是可以返回一个 IServiceProvider 对象的, 这里是基于这个返回对象引入了第三方容器替换.
- 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 容器中, 这样在我们的 service 业务层, 利用通用规则注册 (这里有一点是需要注意的, 就是我们的这个 RegistBasicConventionalRegistrar 方法是基于程序集注册的, 个人建议在每个需要注册的程序集中添加一个标志该程序集的基类, 比如说我会在 Service 这个程序集中添加一个 IServiceBase 接口, 这样就可以通过 typeof(IServiceBase).Assembly 获取到这个程序集进而用来注册)
- 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);
- }
- }
让我知道如果你有更好的想法或建议!
来源: https://www.cnblogs.com/lex-wu/p/10604767.html