0
点赞
收藏
分享

微信扫一扫

IOC扩展Autofac根据注解或接口自动注入相关资源 | DotNetExtensions知识点摘要(三)

流沙雨帘 2022-03-12 阅读 24

  部分内容请参考前一篇文章如何自定义一个自己的IOC容器 | DotNetExtensions知识点摘要(二

  支持泛型注入和反转Class<Type1,Type2,...>,使用的是Autofac的RegisterGeneric方法

using System;
using System.Collections.Generic;
using System.Linq;
using DotNetExtensions.Core.IOC;
using Autofac;
using ContainerBuilder = Autofac.ContainerBuilder;
using System.Reflection;
using System.IO;

namespace DotNetExtensions.Core.Autofac
{
    public static class AutofacBuilderExtensions
    {
        public static void RegistTypes(
             this ContainerBuilder builder, Action<BuilderOption> option)
        {
            BuilderOption builderOptions = new BuilderOption();
            option?.Invoke(builderOptions);

            if (!builderOptions.Assemblies.Any())
            {
                builderOptions.Assemblies.AddRange(AppDomain.CurrentDomain.GetAssemblies().ToList());
            }

            // load assemblies from pattern
            if (builderOptions.Pattern.Any())
            {
                string execAssemblyPath = Assembly.GetExecutingAssembly().Location;
                if (Directory.Exists(execAssemblyPath))
                {
                    List<string> assemblyFiles = new List<string>();
                    foreach (var pattern in builderOptions.Pattern)
                    {
                        string[] files = Directory.GetFiles(execAssemblyPath, pattern);
                        if (files != null && files.Length > 0) assemblyFiles.AddRange(files);
                    }
                    if (assemblyFiles.Any())
                    {
                        builderOptions.Assemblies.AddRange(assemblyFiles.Distinct().Select(file => Assembly.LoadFrom(file)));
                    }
                }
            }

            List<Type> types = builderOptions.Assemblies.SelectMany(a => a.GetTypes()).Distinct().ToList();
            // interface | if inherit IAutoInject or use AutoInjectAttribute
            List<Type> autoInjectFromInheritTypes = types.Where(t => t.IsInterface && t.GetInterfaces().Contains(typeof(IAutoInject))).Distinct().ToList();
            List<Type> autoInjectFormAttrTypes = types.Where(t => t.IsInterface && t.GetCustomAttribute<AutoInjectAttribute>() != null).Distinct().ToList();

            if (autoInjectFromInheritTypes.Any() || autoInjectFormAttrTypes.Any())
            {
                List<Type> autoInjectTypes = autoInjectFromInheritTypes.Union(autoInjectFormAttrTypes).Distinct().ToList();
                builderOptions.Filters.AddRange(autoInjectTypes.Select(type => new InjectTypeFilter { Kind = type.GetCustomAttribute<AutoInjectAttribute>()?.Kind ?? InjectKind.Typed, Type = type }));
            }

            // class | use AutoInjectAttribute
            List<Type> autoInjectClassTypes = types.Where(t => t.IsClass && t.GetCustomAttribute<AutoInjectAttribute>() != null).Distinct().ToList();
            if (autoInjectClassTypes.Any())
            {
                builderOptions.Filters.AddRange(autoInjectClassTypes.Select(type => new InjectTypeFilter { Kind = type.GetCustomAttribute<AutoInjectAttribute>().Kind, Type = type }));
            }
            foreach (var item in builderOptions.Filters)
            {
                if (item.Type == typeof(IAutoInject)) continue;
                if (item.Type == typeof(IDisposable)) continue;
                if (item.Type == typeof(object)) continue;

                List<Type> subs = null;
                if (item.Type.IsClass)
                {
                    // if class | use self
                    subs = new List<Type> { item.Type };
                }
                else if (item.Type.IsInterface)
                {
                    subs = types.Where(t => t.IsClass && t.GetInterfaces().Contains(item.Type)).ToList();
                }

                foreach (var type in subs)
                {
                    var @inject = type.GetCustomAttribute<InjectAttribute>();
                    if (@inject == null) @inject = new InjectAttribute();

                    if (!type.IsGenericType && !type.ContainsGenericParameters && !type.GetGenericArguments().Any())
                    {
                        if (item.Kind == InjectKind.Named && @inject.Scope == InjectScope.Instance)
                        {
                            RegistInstance(builder, @inject.Named, type, item.Type);
                        }
                        else if (item.Kind == InjectKind.Named && @inject.Scope == InjectScope.Scoped)
                        {
                            RegistScoped(builder, @inject.Named, type, item.Type);
                        }
                        else if (item.Kind == InjectKind.Named && @inject.Scope == InjectScope.Single)
                        {
                            RegistSingle(builder, @inject.Named, type, item.Type);
                        }
                        else if (item.Kind == InjectKind.Typed && @inject.Scope == InjectScope.Instance)
                        {
                            RegistInstance(builder, type, item.Type);
                        }
                        else if (item.Kind == InjectKind.Typed && @inject.Scope == InjectScope.Scoped)
                        {
                            RegistScoped(builder, type, item.Type);
                        }
                        else if (item.Kind == InjectKind.Typed && @inject.Scope == InjectScope.Single)
                        {
                            RegistSingle(builder, type, item.Type);
                        }
                    }
                    else
                    {
                        // 增加泛型支持
                        if (item.Kind == InjectKind.Named && @inject.Scope == InjectScope.Instance)
                        {
                            RegistInstanceGeneric(builder, @inject.Named, type, item.Type);
                        }
                        else if (item.Kind == InjectKind.Named && @inject.Scope == InjectScope.Scoped)
                        {
                            RegistScopedGeneric(builder, @inject.Named, type, item.Type);
                        }
                        else if (item.Kind == InjectKind.Named && @inject.Scope == InjectScope.Single)
                        {
                            RegistSingleGeneric(builder, @inject.Named, type, item.Type);
                        }
                        else if (item.Kind == InjectKind.Typed && @inject.Scope == InjectScope.Instance)
                        {
                            RegistInstanceGeneric(builder, type, item.Type);
                        }
                        else if (item.Kind == InjectKind.Typed && @inject.Scope == InjectScope.Scoped)
                        {
                            RegistScopedGeneric(builder, type, item.Type);
                        }
                        else if (item.Kind == InjectKind.Typed && @inject.Scope == InjectScope.Single)
                        {
                            RegistSingleGeneric(builder, type, item.Type);
                        }
                    }
                }

            }
        }

        public static void RegistSingle(ContainerBuilder builder, Type implType, Type type)
        {
            builder.RegisterType(implType)
                     .As(type)
                     .AsImplementedInterfaces()
                     .SingleInstance()
                     .PropertiesAutowired();
        }
        public static void RegistSingleGeneric(ContainerBuilder builder, Type implType, Type type)
        {
            builder.RegisterGeneric(implType)
                     .As(type)
                     .AsImplementedInterfaces()
                     .SingleInstance()
                     .PropertiesAutowired();
        }

        public static void RegistInstance(ContainerBuilder builder, Type implType, Type type)
        {
            builder.RegisterType(implType)
                       .As(type)
                       .AsImplementedInterfaces()
                       .InstancePerDependency()
                       .PropertiesAutowired();
        }
        public static void RegistInstanceGeneric(ContainerBuilder builder, Type implType, Type type)
        {
            builder.RegisterGeneric(implType)
                       .As(type)
                       .AsImplementedInterfaces()
                       .InstancePerDependency()
                       .PropertiesAutowired();
        }

        public static void RegistScoped(ContainerBuilder builder, Type implType, Type type)
        {
            builder.RegisterType(implType)
                       .As(type)
                       .AsImplementedInterfaces()
                       .InstancePerLifetimeScope()
                       .PropertiesAutowired();
        }
        public static void RegistScopedGeneric(ContainerBuilder builder, Type implType, Type type)
        {
            builder.RegisterGeneric(implType)
                       .As(type)
                       .AsImplementedInterfaces()
                       .InstancePerLifetimeScope()
                       .PropertiesAutowired();
        }

        public static void RegistSingle(ContainerBuilder builder, string named, Type implType, Type type)
        {
            builder.RegisterType(implType)
                    .Named(named, type)
                    .AsImplementedInterfaces()
                    .SingleInstance()
                    .PropertiesAutowired();

            builder.RegisterType(type)
                    .AsSelf()
                    .AsImplementedInterfaces()
                    .SingleInstance()
                    .PropertiesAutowired();
        }
        public static void RegistSingleGeneric(ContainerBuilder builder, string named, Type implType, Type type)
        {
            builder.RegisterGeneric(implType)
                    .Named(named, type)
                    .AsImplementedInterfaces()
                    .SingleInstance()
                    .PropertiesAutowired();

            builder.RegisterGeneric(type)
                    .AsSelf()
                    .AsImplementedInterfaces()
                    .SingleInstance()
                    .PropertiesAutowired();
        }
        public static void RegistInstance(ContainerBuilder builder, string named, Type implType, Type type)
        {
            builder.RegisterType(implType)
                             .Named(named, type)
                             .AsImplementedInterfaces()
                             .InstancePerDependency()
                             .PropertiesAutowired();

            builder.RegisterType(type)
               .AsSelf()
               .AsImplementedInterfaces()
               .InstancePerDependency()
               .PropertiesAutowired();
        }
        public static void RegistInstanceGeneric(ContainerBuilder builder, string named, Type implType, Type type)
        {
            builder.RegisterGeneric(implType)
                             .Named(named, type)
                             .AsImplementedInterfaces()
                             .InstancePerDependency()
                             .PropertiesAutowired();

            builder.RegisterGeneric(type)
               .AsSelf()
               .AsImplementedInterfaces()
               .InstancePerDependency()
               .PropertiesAutowired();
        }

        public static void RegistScoped(ContainerBuilder builder, string named, Type implType, Type type)
        {
            builder.RegisterType(implType)
                           .Named(named, type)
                           .AsImplementedInterfaces()
                           .InstancePerLifetimeScope()
                           .PropertiesAutowired();

            builder.RegisterType(type)
               .AsSelf()
               .AsImplementedInterfaces()
               .InstancePerLifetimeScope()
               .PropertiesAutowired();
        }

        public static void RegistScopedGeneric(ContainerBuilder builder, string named, Type implType, Type type)
        {
            builder.RegisterGeneric(implType)
                           .Named(named, type)
                           .AsImplementedInterfaces()
                           .InstancePerLifetimeScope()
                           .PropertiesAutowired();

            builder.RegisterGeneric(type)
               .AsSelf()
               .AsImplementedInterfaces()
               .InstancePerLifetimeScope()
               .PropertiesAutowired();
        }
    }
}

 

using Autofac.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Builder;
using System;
using System.Collections.Generic;
using System.Text;

namespace DotNetExtensions.Core.Autofac
{
    public static class AutofacExtensions
    {
        public static IApplicationBuilder UseAutofac(this IApplicationBuilder app, RegistTypeResolver resolver)
        {
            resolver.LifetimeScope = app.ApplicationServices.GetAutofacRoot();
            return app;
        }
    }
}

 在Startup.cs文件中添加以下代码

覆盖NetCore自身的IOC容器工厂类Program.cs

using Autofac;
using Autofac.Core;
using System;
using System.Collections.Generic;
using System.Text;

namespace DotNetExtensions.Core.Autofac
{
    public class RegistTypeResolver : Singleton<RegistTypeResolver>
    {

        private RegistTypeResolver() { }

        public ILifetimeScope LifetimeScope { get; set; }
        public T Resolve<T>()
        {
            if (LifetimeScope == null || !LifetimeScope.IsRegistered(typeof(T))) throw new Exception($"Type [{typeof(T)}] not registed");
            return LifetimeScope.Resolve<T>();
        }
        public object Resolve(Type type)
        {
            if (LifetimeScope == null || !LifetimeScope.IsRegistered(type)) throw new Exception($"Type [{type.FullName}] not registed");
            return LifetimeScope.Resolve(type);
        }
        public object Resolve(Type type, params Parameter[] parameters)
        {
            if (LifetimeScope == null || !LifetimeScope.IsRegistered(type)) throw new Exception($"Type [{type.FullName}] not registed");
            return LifetimeScope.Resolve(type, parameters);
        }
        public object ResolveNamed(string name, Type type)
        {
            if (LifetimeScope == null || !LifetimeScope.IsRegisteredWithName(name, type)) throw new Exception($"Named [{name}] with type [{type.FullName}] not registed");
            return LifetimeScope.ResolveNamed(name, type);
        }
        public object ResolveNamed(string name, Type type, params Parameter[] parameters)
        {
            if (LifetimeScope == null || !LifetimeScope.IsRegisteredWithName(name, type)) throw new Exception($"Named [{name}] with type [{type.FullName}] not registed");
            return LifetimeScope.ResolveNamed(name, type, parameters);
        }
        public T ResolveNamed<T>(string name) where T : class, new()
        {
            if (LifetimeScope == null || !LifetimeScope.IsRegisteredWithName(name, typeof(T))) throw new Exception($"Named [{name}] with type [{typeof(T).FullName}] not registed");
            return (T)LifetimeScope.ResolveNamed(name, typeof(T));
        }
        
        public T ResolveNamed<T>(string name, params Parameter[] parameters) where T : class, new()
        {
            if (LifetimeScope == null || !LifetimeScope.IsRegisteredWithName(name, typeof(T))) throw new Exception($"Named [{name}] with type [{typeof(T).FullName}] not registed");
            return (T)LifetimeScope.ResolveNamed(name, typeof(T), parameters);
        }

        public T Resolve<T>(params Parameter[] parameters)
        {
            if (LifetimeScope == null || !LifetimeScope.IsRegistered(typeof(T))) throw new Exception($"Type [{typeof(T)}] not registed");
            return LifetimeScope.Resolve<T>(parameters);
        }
    }
}

 最后只需要在要注入的类或者接口上添加[AutoInject]注解即可

using DotNetExtensions.Core.IOC;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace CoreSimple.IOC
{
    public class IOC_Simple
    {
        public IOC_Simple()
        {

            var start = DateTime.Now;

            ContainerBuilder builder = ContainerBuilder.Default;

            builder.RegistTypes(option =>
            {
                option.Assemblies.AddRange(AppDomain.CurrentDomain.GetAssemblies());
                option.Filters.Add(new InjectTypeFilter
                {
                    Kind = InjectKind.Named,
                    Type = typeof(IProvider)
                });
            });

            Console.WriteLine($"{(DateTime.Now -start).TotalMilliseconds}/ms");

            Timer timer = new Timer(new TimerCallback(obj =>
            {
                var provider = builder.Resolve<IProvider>();
                provider.Write();
                var provider2 = builder.Resolve<IProvider2>();
                provider2.Write();
                //var provider3 = builder.Resolve<Provider3>();
                //provider3.Write();
                var provider31 = builder.ResolveNamed<Provider3>("CoreSimple.IOC.Provider3");
                provider31.Write();
                // 如果不指定名称 则使用类全名称 = typeof(Provider1).FullName
                //var provider2 = builder.ResolveNamed<IProvider>("Provider1");
                //provider2.Write();

                //var provider1 = builder.ResolveNamed<IProvider>("Provider2");
                //provider1.Write();
            }), null, 1000, 1000);
        }
    }
    public interface IProvider : IAutoInject
    {
        void Write();
    }
    
    [AutoInject(Kind = InjectKind.Typed)]
    public interface IProvider2
    {
        void Write();
    }

    public class Provider1 : IProvider
    {
        public void Write()
        {
            Console.WriteLine("I'm is provider 1");
        }
    }
    
    public class Provider2 : IProvider2
    {
        public void Write()
        {
            Console.WriteLine("I'm is provider 2");
        }
    }
    
    [AutoInject(InjectKind.Named)]
    public class Provider3
    {
        public void Write()
        {
            Console.WriteLine("I'm is provider 3");
        }
    }
}
举报

相关推荐

0 条评论