.Net Core 3.1 通过Autofac实现全局注入

.NET Core 中 提供了一套依赖注入容器,但需要手工注入。随着业务增长,需要注入的实现增多,会出现忘记注入的情况。

 

Autofac 自动注入

 

1.添加Autofac 引用

Install-Package Autofac -Version 5.2.0

2.添加Autofac.Extensions.DependencyInjection 引用

Install-Package Autofac.Extensions.DependencyInjection-Version 6.0.0

3.定义生命周期相关接口

/// <summary>
    /// 请求单例
    /// </summary>
    public interface IScope
    {
        
    }
   

    /// <summary>
    /// 单例
    /// </summary>
    public interface ISingleton
    {
        
    }

    /// <summary>
    /// 瞬态
    /// </summary>
    public interface ITransient
    {
        
    }

    /// <summary>
    /// 注入接口忽略
    /// </summary>
    public interface IDependencyInterfaceIgnore
    {
        
    }

4.注入相关类型

using Autofac;
using Autofac.Builder;
using Autofac.Core;
using Autofac.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using EasyFx.Core.Utils;

namespace EasyFx.Core.DependencyInjection
{
    public class AutofacConfigure : IDisposable
    {
        public static IContainer ApplicationContainer { get; private set; }



        private static void RegisterTypes(ContainerBuilder builder, List<Type> types, ServiceLifetime lifetime, bool asSelf, bool isGeneric)
        {
            if (!types.Any())
            {
                return;
            }

            if (isGeneric)
            {
                foreach (var item in types)
                {
                    IRegistrationBuilder<object, ReflectionActivatorData, DynamicRegistrationStyle> typeBuilder;
                    var interfaceType = item.GetInterfaces().FirstOrDefault(p => p.IsGenericType);
                    if (interfaceType != null)
                    {
                        typeBuilder = builder.RegisterGeneric(item).As(interfaceType).PropertiesAutowired();
                    }
                    else
                    {
                        typeBuilder = builder.RegisterGeneric(item).PropertiesAutowired();
                    }
                    SetLifetime(typeBuilder, lifetime);
                }
            }
            else
            {
                var typeBuilder = builder.RegisterTypes(types.ToArray()).PropertiesAutowired();
                if (asSelf)
                {
                    typeBuilder.AsSelf();
                }
                else
                {
                    typeBuilder.AsImplementedInterfaces();
                }
                SetLifetime(typeBuilder, lifetime);
            }
        }

        private static void SetLifetime<TReflectionActivatorData>(IRegistrationBuilder<object, TReflectionActivatorData, DynamicRegistrationStyle> typeBuilder, ServiceLifetime lifetime)
        where TReflectionActivatorData : ReflectionActivatorData
        {

            switch (lifetime)
            {
                case ServiceLifetime.Scoped:
                    typeBuilder.InstancePerDependency();
                    break;

                case ServiceLifetime.Singleton:
                    typeBuilder.SingleInstance();
                    break;

                case ServiceLifetime.Transient:
                    typeBuilder.InstancePerLifetimeScope();
                    break;
            }
        }
        private static void RegisterTypes(ContainerBuilder builder, List<Type> types, ServiceLifetime lifetime)
        {
            if (!types.Any())
            {
                return;
            }

            var group = types.Select(it => new
            {
                AsSelf = it.GetInterfaces().Contains(typeof(IDependencyInterfaceIgnore)),
                IsGeneric = it.IsGenericType,
                Type = it
            })
            .GroupBy(it => new
            {
                it.AsSelf,
                it.IsGeneric
            });

            foreach (var item in group)
            {
                RegisterTypes(builder, item.Select(it => it.Type).ToList(), lifetime, item.Key.AsSelf, item.Key.IsGeneric);
                RegisterTypes(builder, item.Select(it => it.Type).ToList(), lifetime, item.Key.AsSelf, item.Key.IsGeneric);
            }
        }

        public static IServiceProvider BuildServiceProvider(IServiceCollection services, params IModule[] modules)
        {
            var builder = new ContainerBuilder();

            if (modules != null && modules.Any())
            {
                foreach (var module in modules)
                {
                    builder.RegisterModule(module);
                }
            }

            var types = ReflectionHelper.GetApplicationTypes();

            //singleton
            var singletonTypes = types.FindAll(t => t.GetInterfaces().Contains(typeof(ISingleton)) && !t.IsInterface);
            RegisterTypes(builder, singletonTypes, ServiceLifetime.Singleton);
            //scope
            var scopeTypes = types.FindAll(t => t.GetInterfaces().Contains(typeof(IScope)) && !t.IsInterface);
            RegisterTypes(builder, scopeTypes, ServiceLifetime.Scoped);
            //transient
            var transientTypes = types.FindAll(t => t.GetInterfaces().Contains(typeof(ITransient)) && !t.IsInterface);
            RegisterTypes(builder, transientTypes, ServiceLifetime.Transient);

            builder.Populate(services);

            ApplicationContainer = builder.Build();
            return new AutofacServiceProvider(ApplicationContainer);
        }

        /// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
        public void Dispose()
        {
            ApplicationContainer?.Dispose();
        }
    }
}

5.替换ServiceProviderFactory

using Autofac.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;

namespace EasyFx.Sample.Web
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .UseServiceProviderFactory(context=>new AutofacServiceProviderFactory())
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}

 

相关依赖代码

1.ReflectionHelper 提供了只包括项目框架的类型
using Microsoft.Extensions.DependencyModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;

namespace EasyFx.Core.Utils
{
    public class ReflectionHelper
    {

       public static List<Type> GetApplicationTypes()
        {
            var context = DependencyContext.Default;
            return context.CompileLibraries
                .Where(lib => !lib.Serviceable && lib.Type != "package")
                .SelectMany(lib =>
                    AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(lib.Name)).GetTypes())
                .ToList();

        }


        public static List<Assembly> GetApplicationAssemblies()
        {
            var context = DependencyContext.Default;
            return context.CompileLibraries
                .Where(lib => !lib.Serviceable && lib.Type != "package")
                .Select(lib => AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(lib.Name)))
                .ToList();

        }
    }
}

 

posted @ 2020-07-16 16:51  SevenNineteen  阅读(875)  评论(0编辑  收藏  举报