netcore依賴注入通過反射簡化
阿新 • • 發佈:2021-09-03
aspnetcore裡面用到許多的service,好多業務程式碼都要通過Service.AddScoped、Singleton、Transient等注入進去,類太多了寫起來和管理起來都很麻煩,所以借鑑了一下github上面的專案稍微刪減了一下下,最後會給出參考連結和git原始碼。
專案結構如下,
這裡面有些約定的東西一定要遵守,否則會出錯,還有webapi必須要引用business和ibusiness,只引用ibusiness是不行的。
核心程式碼如下:
1 using Microsoft.Extensions.DependencyInjection; 2 using System;3 using System.Collections.Generic; 4 using System.Linq; 5 using System.Text; 6 using System.Threading.Tasks; 7 using My.Project.Ioc.Core.IService; 8 9 namespace My.Project.Ioc.Core.Extensions 10 { 11 public static partial class ServiceExtensions 12 { 13 /// <summary> 14 ///自動注入擁有ITransientDependency,IScopeDependency或ISingletonDependency的類 15 /// </summary> 16 /// <param name="services">服務集合</param> 17 /// <returns></returns> 18 public static IServiceCollection AddFxServices(this IServiceCollection services) 19 {20 Dictionary<Type, ServiceLifetime> lifeTimeMap = new Dictionary<Type, ServiceLifetime> 21 { 22 { typeof(ITransientDependency), ServiceLifetime.Transient}, 23 { typeof(IScopedDependency),ServiceLifetime.Scoped}, 24 { typeof(ISingletonDependency),ServiceLifetime.Singleton} 25 }; 26 27 GlobalData.AllFxTypes.ForEach(aType => 28 { 29 lifeTimeMap.ToList().ForEach(aMap => 30 { 31 var theDependency = aMap.Key; 32 if (theDependency.IsAssignableFrom(aType) && theDependency != aType && !aType.IsAbstract && aType.IsClass) 33 { 34 //注入實現 35 services.Add(new ServiceDescriptor(aType, aType, aMap.Value)); 36 37 var interfaces = GlobalData.AllFxTypes.Where(x => x.IsAssignableFrom(aType) && x.IsInterface && x != theDependency).ToList(); 38 //有介面則注入介面 39 if (interfaces.Count > 0) 40 { 41 interfaces.ForEach(aInterface => 42 { 43 services.Add(new ServiceDescriptor(aInterface, serviceProvider => serviceProvider.GetService(aType), aMap.Value)); 44 }); 45 } 46 //無介面則注入自己 47 else 48 { 49 services.Add(new ServiceDescriptor(aType, aType, aMap.Value)); 50 } 51 } 52 }); 53 }); 54 55 return services; 56 } 57 } 58 }
1 using System; 2 using System.Collections.Generic; 3 using System.IO; 4 using System.Linq; 5 using System.Reflection; 6 using System.Text; 7 using System.Threading.Tasks; 8 9 namespace My.Project.Ioc.Core 10 { 11 public static class GlobalData 12 { 13 static GlobalData() 14 { 15 string rootPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); 16 AllFxAssemblies = Directory.GetFiles(rootPath, "*.dll") 17 .Where(x => new FileInfo(x).Name.Contains(FXASSEMBLY_PATTERN)) 18 .Select(x => Assembly.LoadFrom(x)) 19 .Where(x => !x.IsDynamic) 20 .ToList(); 21 22 AllFxAssemblies.ForEach(aAssembly => 23 { 24 try 25 { 26 AllFxTypes.AddRange(aAssembly.GetTypes()); 27 } 28 catch 29 { 30 31 } 32 }); 33 } 34 35 /// <summary> 36 /// 解決方案程式集匹配名 37 /// </summary> 38 public const string FXASSEMBLY_PATTERN = "My.Project.Ioc"; 39 40 /// <summary> 41 /// 解決方案所有程式集 42 /// </summary> 43 public static readonly List<Assembly> AllFxAssemblies; 44 45 /// <summary> 46 /// 解決方案所有自定義類 47 /// </summary> 48 public static readonly List<Type> AllFxTypes = new List<Type>(); 49 } 50 }
非核心程式碼如下:
參考專案Coldairarrow/Colder.Admin.AntdVue: Admin Fx Based On .NET 5 + Ant Design Vue (github.com),有興趣的可以研究下非常不錯。當然裡面關於aop和快取方面我有另外的專案例子可以加進去改造exercise/netcore.demo/AspNetCoreEntityFrameWork at master · liuzhixin405/exercise (github.com)