• 10分钟 Castle.Windsor 适配 Asp.Net Core 3.0


    Asp.Net Core 3.0以上,不再能通过修改Starup.ConfigureServices返回值(IServiceProvider),所以只能调用IHostBuilder.UseServiceProviderFactory修改最外层的IServiceProviderFactory,达到替换DI容器的目的。
    流程是IHostBuilder.UseServiceProviderFactory->IHostBuilder.ConfigureServices->Starup.ConfigureServices,而且IHostBuilder.UseServiceProviderFactory不支持依赖注入,所以只能实例化了,不能取巧的IHostBuilder.ConfigureServices内注册IServiceProviderFactory

    配置Windsor注册模块

    public interface IWindsorContainerModule
    {
      void Configure(WindsorContainer container);
    }
    

    这块不支持依赖注入,详情参考上文

    自定义DI容器

    核心模块 WindsorRegistrationHelper.CreateServiceProvider ,引用Nuget Castle.Windsor.MsDependencyInjection

    internal class WindsorContainerFactory : IServiceProviderFactory<IServiceCollection>
    {
      private WindsorContainer container;
      private IServiceCollection services;
    
      public WindsorContainerFactory(IWindsorContainerModule containerModule)
      {
        container = new WindsorContainer();
        containerModule.Configure(container);
      }
    
      public IServiceCollection CreateBuilder(IServiceCollection services)
      {
        this.services = services;
        return services;
      }
    
      public IServiceProvider CreateServiceProvider(IServiceCollection containerBuilder)
      {
        return WindsorRegistrationHelper.CreateServiceProvider(container, services);
      }
    }
    

    这里完成将WindsorMS DI注册,统一转换为根节点的IServiceProvider,内部流程独立走Windsor,对外则是MS DI的流程。

    IHostBuilder扩展方法

    为了调用更简洁易懂,在IHostBuilder上扩展一个UseWindsorContainer方法.

    public static IHostBuilder UseWindsorContainer<TWindsorContainerModule>(this IHostBuilder hostBuilder, TWindsorContainerModule containerModule)
    where TWindsorContainerModule : class, IWindsorContainerModule
    {
      return hostBuilder
        .UseServiceProviderFactory(new WindsorContainerFactory(containerModule))
        .ConfigureServices(services =>
        {
          services.AddSingleton<IWindsorContainerModule, TWindsorContainerModule>();
        });
    }
    

    编写示例代码

    internal class Sample : IWindsorContainerModule
    {
      public void Configure(WindsorContainer container)
      {
        Console.WriteLine("IWindsorContainerModule Instance Name:sample");
    
        container.Register(Component.For(typeof(IHelloInterface)).ImplementedBy(typeof(HelloInterface)).LifestyleSingleton());
      }
    }
    
    public interface IHelloInterface
    {
      void Show();
    }
    
    internal class HelloInterface : IHelloInterface
    {
      public void Show()
      {
        Console.WriteLine(nameof(HelloInterface));
      }
    }
    

    修改Program.CreateHostBuilder

    public static IHostBuilder CreateHostBuilder(string[] args) =>
      Host.CreateDefaultBuilder(args)
        .UseWindsorContainer(new Sample()) //新增
        .ConfigureWebHostDefaults(webBuilder =>
        {
          webBuilder
            .UseStartup<Startup>();
    });
    

    修改Controllers.WeatherForecastController.Get

    public IEnumerable<WeatherForecast> Get()
    {
        Console.WriteLine(_helloInterface.GetType().FullName); //打印接口实际实现,验证是否代理到Castle.Windsor
        _helloInterface.Show(); //接口调用方法
     
         var rng = new Random();
         return Enumerable.Range(1, 5).Select(index => new WeatherForecast
         {
           Date = DateTime.Now.AddDays(index),
           TemperatureC = rng.Next(-20, 55),
           Summary = Summaries[rng.Next(Summaries.Length)]
         })
         .ToArray();
    }
    


    后记

    感谢Lemon大人的指点~关于 IHostBuilder.UseServiceProviderFactory到IHostBuilder.ConfigureServices的细节和最初的预估差异不小,最早的代码实现版本是IHostBuilder.ConfigureServices内注册了IServiceProviderFactory,希望更优雅的实现替换DI容器,现实是这块是不可以的~

    如果对于内容有交流和学习的,欢迎加 .Net应用程序框架交流群,群号386092459

  • 相关阅读:
    dolphin以root身份打开
    linux ACL权限
    PIT中断与外设时钟配置
    GPT定时器定时
    I.MX RT 时钟控制模块(CCM)
    OLED屏显示功能的实现
    RT1052 A/D数据采集
    滴答时钟与延时
    局域网 访问mac前端项目
    js 加减乘除取余运算
  • 原文地址:https://www.cnblogs.com/NCoreCoder/p/13425603.html
Copyright © 2020-2023  润新知