利用.net Core 對程序集中的類 進行統一依賴注入


1.創建特性 用於標注依賴注入

using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;

namespace Util.Attributes
{
    /// <summary>
    /// 標注要運用DI的類 被此屬性標注的類 要被注冊到依賴注入容器中 並且可以指定類要映射的接口或者類
    /// 此屬性只能運用於類,並且此屬性不能繼承
    /// </summary>
    [AttributeUsage(AttributeTargets.Class,Inherited =false)]
    public class UseDIAttribute:Attribute
    {
        //Targets用於指示 哪些接口或者類 要被 "被屬性修飾了的類" 進行依賴注入
        public List<Type> TargetTypes=new List<Type>();
        public ServiceLifetime lifetime;
        public UseDIAttribute(ServiceLifetime argLifetime,params Type[] argTargets)
        {
            lifetime = argLifetime;
            foreach (var argTarget in argTargets)
            {
                TargetTypes.Add(argTarget);
            }
        }

        public List<Type> GetTargetTypes()
        {
            return TargetTypes;
        }
        public ServiceLifetime Lifetime
        {
            get
            {
                return this.lifetime;
            }
        }
    }
}

 2.對程序集中要注入的類進行標記

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using System.Linq;
using System.Threading.Tasks;
using User.Domain;
using User.Domain.POCOModels;
using Util.Attributes;

namespace DDD.Repositories.UserRepositories
{
    [UseDI(ServiceLifetime.Scoped,typeof(ILoginRepository))]
    public class LoginEFCoreRepository:ILoginRepository
    {
        private readonly DbContext dbContext;
        public LoginEFCoreRepository(DbContext dbContext)
        {
            this.dbContext = dbContext;
        }

 

3.為IserviceCollection擴展一個方法  可以實現對程序集進行操作

using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Util.Attributes;

namespace Util.DIPlugin
{
    public static class NetCoreDIModuleRegister
    {
        /// <summary>
        /// 自動注冊服務
        /// </summary>
        /// <param name="services">注冊服務的集合(向其中注冊)</param>
        /// <param name="ImplementationType">要注冊的類型</param>
        public static void AutoRegisterService(this IServiceCollection services, Type ImplementationType)
        {
            //獲取類型的 UseDIAttribute 屬性 對應的對象
            UseDIAttribute attr = ImplementationType.GetCustomAttribute(typeof(UseDIAttribute)) as UseDIAttribute;
            ////獲取類實現的所有接口
            //Type[] types = ImplementationType.GetInterfaces();
            List<Type> types = attr.GetTargetTypes();
            var lifetime = attr.Lifetime;
            //遍歷類實現的每一個接口
            foreach (var t in types)
            {
                //將類注冊為接口的實現-----但是存在一個問題,就是擔心 如果一個類實現了IDisposible接口 擔心這個類變成了這個接口的實現
                ServiceDescriptor serviceDescriptor = new ServiceDescriptor(t, ImplementationType, lifetime);
                services.Add(serviceDescriptor);
            }

        }
        /// <summary>
        /// 根據程序集的名字獲取程序集中所有的類型集合
        /// </summary>
        /// <param name="AssemblyName">程序集名字</param>
        /// <returns>類型集合</returns>
        public static Type[] GetTypesByAssemblyName(String AssemblyName)
        {
            Assembly assembly = Assembly.Load(AssemblyName);
            return assembly.GetTypes();
        }


        #region 將程序集中的所有符合條件的類型全部注冊到 IServiceCollection 中 重載1
        /// <summary>
        /// 將程序集中的所有符合條件的類型全部注冊到 IServiceCollection 中
        /// </summary>
        /// <param name="services">IServiceCollection</param>
        /// <param name="AassemblyName">程序集名字</param>
        public static void AutoRegisterServicesFromAssembly(this IServiceCollection services,
            string AassemblyName)
        {
            //根據程序集的名字 獲取程序集中所有的類型
            Type[] types = GetTypesByAssemblyName(AassemblyName);
            //過濾上述程序集 首先按照傳進來的條件進行過濾 接着要求Type必須是類,而且不能是抽象類
            IEnumerable<Type> _types = types.Where(t => t.IsClass && !t.IsAbstract);
            foreach (var t in _types)
            {
                IEnumerable<Attribute> attrs = t.GetCustomAttributes();
                //遍歷類的所有特性
                foreach (var attr in attrs)
                {
                    //如果在其特性中發現特性是 UseDIAttribute 特性 就將這個類注冊到DI容器中去
                    //並跳出當前的循環 開始對下一個類進行循環
                    if (attr is UseDIAttribute)
                    {
                        services.AutoRegisterService(t);
                        break;
                    }
                }
            }
        }
        #endregion


        #region 將程序集中的所有符合條件的類型全部注冊到 IServiceCollection 中 重載2
        /// <summary>
        /// 將程序集中的所有符合條件的類型全部注冊到 IServiceCollection 中
        /// </summary>
        /// <param name="services">IServiceCollection</param>
        /// <param name="AassemblyName">程序集名字</param>
        /// <param name="wherelambda">過濾類型的表達式</param>
        public static void AutoRegisterServicesFromAssembly(this IServiceCollection services,
            string AassemblyName, Func<Type, bool> wherelambda)
        {
            //根據程序集的名字 獲取程序集中所有的類型
            Type[] types = GetTypesByAssemblyName(AassemblyName);
            //過濾上述程序集 首先按照傳進來的條件進行過濾 接着要求Type必須是類,而且不能是抽象類
            IEnumerable<Type> _types = types.Where(wherelambda).Where(t => t.IsClass && !t.IsAbstract);
            foreach (var t in _types)
            {
                IEnumerable<Attribute> attrs = t.GetCustomAttributes();
                //遍歷類的所有特性
                foreach (var attr in attrs)
                {
                    //如果在其特性中發現特性是 UseDIAttribute 特性 就將這個類注冊到DI容器中去
                    //並跳出當前的循環 開始對下一個類進行循環
                    if (attr is UseDIAttribute)
                    {
                        services.AutoRegisterService(t);
                        break;
                    }
                }
            }
        }
        #endregion

    }
}

 4.在webapi的startup.cs類中注冊 需要處理的程序集:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM