ibcadmin 发表于 2019-9-26 09:21:34

ASP.NET Core 3.0 原生DI拓展实现IocManager

<p>昨天<strong>.NET Core 3.0</strong> 正式发布,创建一个项目运行后发现:原来利用的Autofac在ConfigureServices返回IServiceProvider的这种写法已经不再支持。当然Autofac官方也给出了示例。</p>
<p>.NET Core 自己内置DI,我决定不再利用Autofac,就利用原生DI,拓展IServiceCollection实现一个IocManager,</p>
<p>实现批量注入,静态获取实例功能。</p>
<h2 id="一autofac官方文档">一、Autofac官方文档</h2>
<h3 id="program-class">Program Class</h3>
<p><strong>Hosting changed in ASP.NET Core 3.0</strong> and requires a slightly different integration. This is for ASP.NET Core 3+ and the .NET Core 3+ generic hosting support:</p>
<code>public class Program
{
public static void Main(string[] args)
{
    // ASP.NET Core 3.0+:
    // The UseServiceProviderFactory call attaches the
    // Autofac provider to the generic hosting mechanism.
    var host = Host.CreateDefaultBuilder(args)
      .UseServiceProviderFactory(new AutofacServiceProviderFactory())
      .ConfigureWebHostDefaults(webHostBuilder => {
          webHostBuilder
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseIISIntegration()
            .UseStartup<Startup>();
      })
      .Build();

    host.Run();
}
}</code>
<h3 id="startup-class">Startup Class</h3>
<p>In your Startup class (which is basically the same across all the versions of ASP.NET Core) you then use <code>ConfigureContainer</code> to access the Autofac container builder and register things directly with Autofac.</p>
<code>public class Startup
{
public Startup(IHostingEnvironment env)
{
    // In ASP.NET Core 3.0 env will be an IWebHostingEnvironment, not IHostingEnvironment.
    var builder = new ConfigurationBuilder()
      .SetBasePath(env.ContentRootPath)
      .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
      .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
      .AddEnvironmentVariables();
    this.Configuration = builder.Build();
}

public IConfigurationRoot Configuration { get; private set; }

public ILifetimeScope AutofacContainer { get; private set; }

// ConfigureServices is where you register dependencies. This gets
// called by the runtime before the ConfigureContainer method, below.
public void ConfigureServices(IServiceCollection services)
{
    // Add services to the collection. Don&#39;t build or return
    // any IServiceProvider or the ConfigureContainer method
    // won&#39;t get called.
    services.AddOptions();
}

// ConfigureContainer is where you can register things directly
// with Autofac. This runs after ConfigureServices so the things
// here will override registrations made in ConfigureServices.
// Don&#39;t build the container; that gets done for you. If you
// need a reference to the container, you need to use the
// "Without ConfigureContainer" mechanism shown later.
public void ConfigureContainer(ContainerBuilder builder)
{
      builder.RegisterModule(new AutofacModule());
}

// Configure is where you add middleware. This is called after
// ConfigureContainer. You can use IApplicationBuilder.ApplicationServices
// here if you need to resolve things from the container.
public void Configure(
    IApplicationBuilder app,
    ILoggerFactory loggerFactory)
{
    // If, for some reason, you need a reference to the built container, you
    // can use the convenience extension method GetAutofacRoot.
    this.AutofacContainer = app.ApplicationServices.GetAutofacRoot();

    loggerFactory.AddConsole(this.Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();
    app.UseMvc();
}
}</code>
<h2 id="二iocmanager实现">二、IocManager实现</h2>
<h3 id="创建iocmanager">1、创建IocManager</h3>
<code>public interface IIocManager
{
    IServiceProvider ServiceProvider { get; set; }
}</code>
<code>public class IocManager : IIocManager
{
    static IocManager()
    {
      Instance = new IocManager();
    }
    public static IocManager Instance { get; private set; }
    public IServiceProvider ServiceProvider { get; set; }
}</code>
<h3 id="创建生命周期接口">2、创建生命周期接口</h3>
<code>    /// <summary>
    ///    标记依赖项生命周期的接口
    ///   <see cref="ILifetimeScopeDependency" />,
    ///   <see cref="ITransientDependency" />,
    ///   <see cref="ISingletonDependency" />
    /// </summary>
    public interface ILifetime { }
    /// <summary>
    /// 确定接口或类的生存期
    /// 作用域模式,服务在每次哀求时被创建,整个哀求过程中都贯穿利用这个创建的服务。
    /// </summary>
    public interface ILifetimeScopeDependency : ILifetime { }
    /// <summary>
    /// 确定接口或类的生存期
    /// 作用域模式,服务在每次哀求时被创建,整个哀求过程中都贯穿利用这个创建的服务。
    /// </summary>
    public interface ILifetimeScopeDependency : ILifetime { }
    /// <summary>
    /// 确定接口或类的生存期
    /// 瞬态模式,每次哀求时都会创建。
    /// </summary>
    public interface ITransientDependency : ILifetime { }</code>
<h3 id="拓展iservicecollection">3、拓展IServiceCollection</h3>
<code>/// <summary>
/// .NET Core 依赖注入拓展
/// </summary>
public static class DependencyInjectionExtensions
{
    /// <summary>
    /// 注册步伐集组件
    /// </summary>
    /// <param name="services"></param>
    /// <param name="assemblies"></param>
    /// <returns></returns>
    public static IServiceCollection AddAssembly(this IServiceCollection services, params Assembly[] assemblies)
    {
      if (assemblies==null||assemblies.Count()==0)
      {
            throw new Exception("assemblies cannot be empty.");
      }
      foreach (var assembly in assemblies)
      {
            RegisterDependenciesByAssembly<ISingletonDependency>(services, assembly);
            RegisterDependenciesByAssembly<ITransientDependency>(services, assembly);
            RegisterDependenciesByAssembly<ILifetimeScopeDependency>(services, assembly);
      }
      return services;
    }

    public static void RegisterDependenciesByAssembly<TServiceLifetime>(IServiceCollection services, Assembly assembly)
    {            
      var types = assembly.GetTypes().Where(x => typeof(TServiceLifetime).GetTypeInfo().IsAssignableFrom(x) && x.GetTypeInfo().IsClass && !x.GetTypeInfo().IsAbstract && !x.GetTypeInfo().IsSealed).ToList();
      foreach (var type in types)
      {
            var itype = type.GetTypeInfo().GetInterfaces().FirstOrDefault(x => x.Name.ToUpper().Contains(type.Name.ToUpper()));
            if (itype!=null)
            {
                var serviceLifetime = FindServiceLifetime(typeof(TServiceLifetime));
                services.Add(new ServiceDescriptor(itype, type, serviceLifetime));
            }
      }
    }

    private static ServiceLifetime FindServiceLifetime(Type type)
    {
      if (type == typeof(ISingletonDependency))
      {
            return ServiceLifetime.Singleton;
      }
      if (type == typeof(ITransientDependency))
      {
            return ServiceLifetime.Singleton;
      }
      if (type == typeof(ILifetimeScopeDependency))
      {
            return ServiceLifetime.Singleton;
      }

      throw new ArgumentOutOfRangeException($"Provided ServiceLifetime type is invalid. Lifetime:{type.Name}");
    }

    /// <summary>
    /// 注册IocManager
    /// 在ConfigureServices方法最后一行利用
    /// </summary>
    /// <param name="services"></param>
    public static void AddIocManager(this IServiceCollection services)
    {
      services.AddSingleton<IIocManager, IocManager>(provide =>
      {
            IocManager.Instance.ServiceProvider = provide;
            return IocManager.Instance;
      });
    }
}</code>
<h3 id="iocmanager利用实例">4、IocManager利用实例:</h3>
<h4 id="示例步伐集">4.1、示例步伐集</h4>
<code>namespace Service
{
    public interface IUserService
    {
      string GetUserNameById(string Id);
    }
    public interface UserService:IUserService,ISingletonDependency
    {
      public string GetUserNameById(string Id)
      {
         return "刘大大";
      }
    }
}</code>
<h4 id="为步伐集写一个拓展类">4.2、为步伐集写一个拓展类</h4>
<code>public static class ServiceExtensions
{
    public static IServiceCollection UseService(this IServiceCollection services)
    {
      var assembly = typeof(ServiceExtensions).Assembly;
      services.AddAssembly(assembly);
      return services;
    }
}</code>
<h4 id="web层利用">4.3、Web层利用</h4>
<h5 id="startup-class-1">Startup class</h5>
<code>       public void ConfigureServices(IServiceCollection services)
      {
         services.UseService();
         
         services.AddControllersWithViews();
         
         services.AddIocManager();
      }</code>
<h5 id="controller">Controller</h5>
<p>IIocManager实现了单例模式,可以通过构造器注入获取实例,也可以通过通过<code>IocManager.Instance</code>获取实例</p>
<code>    public class HomeController : Controller
    {
      private readonly IIocManager _iocManager;
      public HomeController(IIocManager iocManager)
      {
            _iocManager = iocManager;
      }
      public string test1()
      {
         //通过注入获取IocManager实例
         var _userService=_iocManager.ServiceProvider.GetService<IUserService>();
         var userName=_userService.GetUserNameById("1");
         return userName;
      }
      
      public string test2()
      {
         //通过IocManager获取IIocManager实例
         var _userService=IocManager.Instance.ServiceProvider.GetService<IUserService>();
         var userName=_userService.GetUserNameById("1");
         return userName;
      }
      
      public string test3(IUserService _userService)
      {
         //通过注入获取Service实例
         var userName=_userService.GetUserNameById("1");
         return userName;
      }
}</code>
<p><div align="center"></div></p><br><br/><br/><br/><br/><br/>来源:<a href="https://www.cnblogs.com/lwc1st/archive/2019/09/25/11582662.html" target="_blank">https://www.cnblogs.com/lwc1st/archive/2019/09/25/11582662.html</a>
页: [1]
查看完整版本: ASP.NET Core 3.0 原生DI拓展实现IocManager