• .net5


     方式一:自定义【在调试是加载时间过长】

    NuGet包:

    Microsoft.Extensions.DependencyModel
    Microsoft.Extensions.Options

    XXX.Common项目下新建文件夹【DependencyInjection】

    新建类:RuntimeHelper、ServiceExtension

    using Microsoft.Extensions.DependencyModel;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    using System.Runtime.Loader;
    
    namespace NetFive.Common.DependencyInjection
    {
        public class RuntimeHelper
        {
            /// <summary>
            /// 获取项目程序集,排除所有的系统程序集(Microsoft.***、System.***等)、Nuget下载包
            /// </summary>
            /// <returns></returns>
            public static IList<Assembly> GetAllAssemblies()
            {
                var list = new List<Assembly>();
                var deps = DependencyContext.Default;
                var libs = deps.CompileLibraries.Where(lib => !lib.Serviceable && lib.Type != "package");//排除所有的系统程序集、Nuget下载包
                foreach (var lib in libs)
                {
                    try
                    {
                        var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(lib.Name));
                        list.Add(assembly);
                    }
                    catch (Exception)
                    {
                    }
                }
                return list;
            }
    
            public static Assembly GetAssembly(string assemblyName)
            {
                return GetAllAssemblies().FirstOrDefault(assembly => assembly.FullName.Contains(assemblyName));
            }
    
            public static IList<Type> GetAllTypes()
            {
                var list = new List<Type>();
                foreach (var assembly in GetAllAssemblies())
                {
                    var typeInfos = assembly.DefinedTypes;
                    foreach (var typeInfo in typeInfos)
                    {
                        list.Add(typeInfo.AsType());
                    }
                }
                return list;
            }
    
            public static IList<Type> GetTypesByAssembly(string assemblyName)
            {
                var list = new List<Type>();
                var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(assemblyName));
                var typeInfos = assembly.DefinedTypes;
                foreach (var typeInfo in typeInfos)
                {
                    list.Add(typeInfo.AsType());
                }
                return list;
            }
    
            public static Type GetImplementType(string typeName, Type baseInterfaceType)
            {
                return GetAllTypes().FirstOrDefault(t =>
                {
                    if (t.Name == typeName &&
                        t.GetTypeInfo().GetInterfaces().Any(b => b.Name == baseInterfaceType.Name))
                    {
                        var typeInfo = t.GetTypeInfo();
                        return typeInfo.IsClass && !typeInfo.IsAbstract;
                    }
                    return false;
                });
            }
        }
    }
    
    using Microsoft.Extensions.DependencyInjection;
    using System;
    using System.Linq;
    using System.Reflection;
    
    namespace NetFive.Common.DependencyInjection
    {
        /// <summary>
        /// IServiceCollection扩展
        /// </summary>
        public static class ServiceExtension
        {
            /// <summary>
            /// 注册服务
            /// </summary>
            /// <param name="services"></param>
            /// <param name="interfaceAssemblyName">定义业务接口的程序集名称</param>
            /// <param name="implementAssemblyName">实现业务接口的程序集名称(默认 interfaceAssemblyName)</param>
            public static void RegisterService(this IServiceCollection service, string interfaceAssemblyName, string implementAssemblyName)
            {
                if (string.IsNullOrEmpty(implementAssemblyName))
                {
                    RegisterAssembly(service, interfaceAssemblyName);
                }
                else
                {
                    RegisterAssembly(service, interfaceAssemblyName, implementAssemblyName);
                }
            }
    
            /// <summary>
            /// 批量注入接口程序集中对应的实现类。
            /// <para>
            /// 需要注意的是,这里有如下约定:
            /// IUserService --> UserService, IUserRepository --> UserRepository.
            /// </para>
            /// </summary>
            /// <param name="service"></param>
            /// <param name="interfaceAssemblyName">接口程序集的名称(不包含文件扩展名)</param>
            /// <returns></returns>
            internal static IServiceCollection RegisterAssembly(this IServiceCollection service, string interfaceAssemblyName)
            {
                if (service == null)
                { 
                    throw new ArgumentNullException(nameof(service));
                }
                if (string.IsNullOrEmpty(interfaceAssemblyName))
                {
                    throw new ArgumentNullException(nameof(interfaceAssemblyName));
                }
                var assembly = RuntimeHelper.GetAssembly(interfaceAssemblyName);
                if (assembly == null)
                {
                    throw new DllNotFoundException($"the dll "{interfaceAssemblyName}" not be found");
                }
                //过滤掉非接口及泛型接口
                var types = assembly.GetTypes().Where(t => t.GetTypeInfo().IsInterface);
                foreach (var type in types)
                {
                    var implementTypeName = type.Name.Substring(1);
                    var implementType = RuntimeHelper.GetImplementType(implementTypeName, type);
                    if (implementType != null)
                        service.AddScoped(type, implementType);
                }
                return service;
            }
    
            /// <summary>
            /// 用DI批量注入接口程序集中对应的实现类。
            /// </summary>
            /// <param name="service"></param>
            /// <param name="interfaceAssemblyName">接口程序集的名称(不包含文件扩展名)</param>
            /// <param name="implementAssemblyName">实现程序集的名称(不包含文件扩展名)</param>
            /// <returns></returns>
            internal static IServiceCollection RegisterAssembly(this IServiceCollection service, string interfaceAssemblyName, string implementAssemblyName)
            {
                if (service == null)
                    throw new ArgumentNullException(nameof(service));
                if (string.IsNullOrEmpty(interfaceAssemblyName))
                    throw new ArgumentNullException(nameof(interfaceAssemblyName));
                if (string.IsNullOrEmpty(implementAssemblyName))
                    throw new ArgumentNullException(nameof(implementAssemblyName));
                var interfaceAssembly = RuntimeHelper.GetAssembly(interfaceAssemblyName);
                if (interfaceAssembly == null)
                {
                    throw new DllNotFoundException($"the dll "{interfaceAssemblyName}" not be found");
                }
                var implementAssembly = RuntimeHelper.GetAssembly(implementAssemblyName);
                if (implementAssembly == null)
                {
                    throw new DllNotFoundException($"the dll "{implementAssemblyName}" not be found");
                }
                //过滤掉非接口及泛型接口
                var types = interfaceAssembly.GetTypes().Where(t => t.GetTypeInfo().IsInterface);
                foreach (var type in types)
                {
                    //过滤掉抽象类、泛型类以及非class
                    var implementType = implementAssembly.DefinedTypes
                        .FirstOrDefault(t => t.IsClass && !t.IsAbstract &&
                                             t.GetInterfaces().Any(b => b.Name == type.Name));
                    if (implementType != null)
                    {
                        service.AddScoped(type, implementType.AsType());
                    }
                }
                return service;
            }
        }
    }
    

     Startup注册:

                #region IOC依赖注入自定义
                services.RegisterService("NetFive.Repository", string.Empty);
                services.RegisterService("NetFive.Command", string.Empty);
                services.RegisterService("NetFive.Query", string.Empty);
                services.RegisterService("NetFive.Service", string.Empty);
                #endregion
    

      

     方式二:Autofac简单

     NuGet包:

    Autofac
    Autofac.Extensions.DependencyInjection
    

     Program.cs

    .UseServiceProviderFactory(new AutofacServiceProviderFactory())//添加Autofac服务
    

     Startup类添加 ConfigureContainer() 方法,必须添加在Startup类里面没有细研究其他方法

    /// <summary>
    /// 这段代码必须放在Startup类里面
    /// </summary>
    /// <param name="builder"></param>
    public void ConfigureContainer(ContainerBuilder builder)
    {
        
    }
    

     构造函数注入:

    //构造函数注入
    builder.RegisterType<EmployeeService>().As<IEmployeeService>();

     构造函数使用:

     属性注入:

    builder.RegisterType<EmployeeService>().As<IEmployeeService>().PropertiesAutowired();//只能在当前的EmployeeService类,使用属性注入
    

     属性注入使用:

    方法注入:

     

    //方法注入
    builder.RegisterType<EmployeeQry>().As<IEmployeeQry>();
    builder.RegisterType<EmployeeService>().OnActivated(e => e.Instance.Qry(e.Context.Resolve<IEmployeeQry>())).As<IEmployeeService>();
    

     方法注入使用:

    方式2:Autofac批量

    需要 using 命名空间 System.Reflection

    修改 Straup.cs 文件中的 ConfigureContainer() 方法

    约定接口(Interface)和实现(class)都是以 Service 【或者其他】结尾的。

            /// <summary>
            /// 这段代码必须放在Startup类里面
            /// </summary>
            /// <param name="builder"></param>
            public void ConfigureContainer(ContainerBuilder builder)
            {
                //批量注入//加载程序集
                //var urpIService = Assembly.Load("NetFive.Service"); //接口层
                //var urpService = Assembly.Load("NetFive.Service");  //实现层
                //根据名称约定(服务层的接口和实现均以Service结尾),实现服务接口和服务实现的依赖
                //builder.RegisterAssemblyTypes(urpIService, urpService).Where(t => t.Name.EndsWith("Service")).AsImplementedInterfaces().PropertiesAutowired();
    
                //泛型注册
                builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>));
    
                //批量注入
                var repository = Assembly.Load("NetFive.Repository");
                builder.RegisterAssemblyTypes(repository).Where(t => t.Name.EndsWith("UnitOfWorks") || t.Name.EndsWith("DbContext")).AsImplementedInterfaces();
    
                var qry = Assembly.Load("NetFive.Query");
                builder.RegisterAssemblyTypes(qry).Where(t => t.Name.EndsWith("Qry")).AsImplementedInterfaces();
    
                var cmd = Assembly.Load("NetFive.Command");
                builder.RegisterAssemblyTypes(cmd).Where(t => t.Name.EndsWith("Cmd")).AsImplementedInterfaces();
    
                //批量注入//加载程序集
                var urpIService = Assembly.Load("NetFive.Service");
                //因为接口层和实现层都在一起,所以只用写一个
                builder.RegisterAssemblyTypes(urpIService).Where(t => t.Name.EndsWith("Service")).AsImplementedInterfaces().PropertiesAutowired();
            }
    

     使用:

     方式2:Autofac控制器注入

    #region 指定控制器的实例由容器来创建
    services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());
    #endregion
    

                #region 注册所有控制器的关系及控制器实例化所需要的组件
    
                var controllersTypesInAssembly = typeof(Startup).Assembly.GetExportedTypes()
                    .Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray();
    
                builder.RegisterTypes(controllersTypesInAssembly)
                    .PropertiesAutowired();
    
                #endregion 

     使用:

     扩展:自己控制哪些属性需要做依赖注入(默认是让控制器中的属性都依赖注入)

     

    using System;
    
    namespace NetFive.WebApi.Custom.Autofacs
    {
        [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
        public class AutowaredAttribute : Attribute { }
    }
    
    using Autofac.Core;
    using System.Linq;
    using System.Reflection;
    
    namespace NetFive.WebApi.Custom.Autofacs
    {
        public class PropertySelector : IPropertySelector
        {
            public bool InjectProperty(PropertyInfo propertyInfo, object instance)
            {
                return propertyInfo.CustomAttributes.Any(ca => ca.AttributeType == typeof(AutowaredAttribute));
            }
        }
    }
    

    添加特性才能使用:

     

     方式2:Autofac泛型注入
    //方式1.以泛型方式注册
    builder.RegisterGeneric(typeof(UnitOfWork<>)).As(typeof(IUnitOfWork<>)).SingleInstance();
    builder.RegisterGeneric(typeof(DatabaseFactory<>)).As(typeof(IDatabaseFactory<>)).SingleInstance();
    //方式2.以普通的方式注册
    //builder.RegisterType<UnitOfWork<AutofacDBEntities>>().As<IUnitOfWork<AutofacDBEntities>>().SingleInstance();
    //builder.RegisterType<DatabaseFactory<AutofacDBEntities>>().As<IDatabaseFactory<AutofacDBEntities>>().SingleInstance();
    
     方式2:Autofac生命周期

     1、InstancePerDependency :默认模式,每次调用,都会重新实例化对象;每次请求都创建一个新的对象;

    builder.RegisterType<TestServiceA>().As<ITestServiceA>().InstancePerDependency();
    

     2、SingleInstance :单例模式,每次调用,都会使用同一个实例化的对象;每次都用同一个对象;

    builder.RegisterType<TestServiceA>().As<ITestServiceA>().SingleInstance();
    

     3、InstancePerLifetimeScope : 同一个生命周期域中,每次调用,都会使用同一个实例化的对象;每次都用同一个对象;且每个不同的生命周期域中的实例是唯一的,不共享的。

    builder.RegisterType<TestServiceA>().As<ITestServiceA>().InstancePerLifetimeScope();
    

     4、InstancePerMatchingLifetimeScope : 同一个匹配的生命周期域中,每次调用,都会使用同一个实例化的对象;每次都用同一个对象;且每个不匹配的生命周期域中的实例是唯一的,不共享的。

    builder.RegisterType<TestServiceA>().As<ITestServiceA>().InstancePerMatchingLifetimeScope();
    

     5、InstancePerOwned : 在一个所拥有的实例创建的生命周期中,每次调用,都会使用同一个实例化的对象;每次都用同一个对象;(较少使用)

     6、InstancePerHttpRequest : 同一次Http请求上下文中,每次调用,都会使用同一个实例化的对象;每次都用同一个对象;仅适用于 ASP.NET (CORE) MVC 或 WebForm 应用程序

  • 相关阅读:
    Android为TV端助力 转载:RecyclerView分页加载
    Android 最简单的测试UI卡顿
    Android为TV端助力 使用shared注意事项
    Android为TV端助力 电影栏目移动到底部或者顶部时抖动动画
    Android为TV端助力转载:码农小阿飞(SpannableString)
    Android为TV端助力 监听APK卸载,替换,完成的广播
    Android 为TV端助力
    Android为TV端助力 进制互相转换
    Android为TV端助力linux命令
    Android为TV端助力 集成第三方播放器,实现全屏播放
  • 原文地址:https://www.cnblogs.com/gygtech/p/14491364.html
Copyright © 2020-2023  润新知