通过反射实现Netcore的服务依赖注入
先定义一个Attribute
1 using System; 2 3 namespace FireCloud.Framework 4 { 5 [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)] 6 public class InjectionAttribute: Attribute 7 { 8 public InjectionAttribute(Type name, Microsoft.Extensions.DependencyInjection.ServiceLifetime serviceLifetime) 9 { 10 Name = name; 11 ServiceLifetime = serviceLifetime; 12 } 13 14 public Type Name { get; set; } 15 16 public Microsoft.Extensions.DependencyInjection.ServiceLifetime ServiceLifetime { get; set; } 17 } 18 }
然后定义一个服务扩展方法
1 using Microsoft.Extensions.Configuration; 2 using Microsoft.Extensions.DependencyInjection; 3 using System; 4 using System.Linq; 5 using System.Reflection; 6 7 namespace FireCloud.Framework 8 { 9 public static class InjectionExtension 10 { 11 public static IServiceCollection AddInjections(this IServiceCollection services, IConfiguration configuration) 12 { 13 //配置文件获取注入的类库 14 var injections = configuration.GetSection("Injection").GetChildren(); 15 if(injections != null && injections.Count() > 0) 16 { 17 foreach(var injection in injections) 18 { 19 var assembly = Assembly.LoadFrom(AppDomain.CurrentDomain.BaseDirectory + injection.Value); 20 var types = assembly.GetTypes(); 21 if(types != null && types.Length > 0) 22 { 23 foreach(var type in types) 24 { 25 var attribute = type.GetCustomAttribute(typeof(InjectionAttribute), false); 26 if (attribute is InjectionAttribute) 27 { 28 InjectionAttribute injectionAttribute = attribute as InjectionAttribute; 29 var name = injectionAttribute.Name; 30 var serviceLifetime = injectionAttribute.ServiceLifetime; 31 services = AddInjectionWithLifetime(services, serviceLifetime, name, type); 32 } 33 } 34 } 35 } 36 } 37 return services; 38 } 39 40 private static IServiceCollection AddInjectionWithLifetime(IServiceCollection services, ServiceLifetime serviceLifetime, Type type, Type implementation) 41 { 42 switch (serviceLifetime) 43 { 44 case ServiceLifetime.Scoped: 45 return services.AddScoped(type, implementation); 46 case ServiceLifetime.Singleton: 47 return services.AddSingleton(type, implementation); 48 case ServiceLifetime.Transient: 49 return services.AddTransient(type, implementation); 50 default: 51 return services; 52 } 53 } 54 } 55 }
然后在服务的实现上面添加注入特性
using System; using System.Collections.Generic; using System.Net.Http; using System.Threading.Tasks; namespace FireCloud.Framework.Services { [Injection(typeof(IConsulClientServices), Microsoft.Extensions.DependencyInjection.ServiceLifetime.Scoped)] public class ConsulClientServices : IConsulClientServices { public Task<T> PostData<T>(HttpClient _client, string actionUrl, Dictionary<string, object> dic) { throw new NotImplementedException(); } } }
appsettings配置文件的需要添加使用到的dll
"Injection": [ "FireCloud.Framework.dll", "FireCloud.Web.dll" ]
最后是startup.cs里面的服务调用
public void ConfigureServices(IServiceCollection services)
{ services.AddSignalR(); services.AddControllers(); //services.AddScoped<IConsulClientServices, ConsulClientServices>(); services.Configure<Theme>(Configuration.GetSection("Theme")); services.AddInjections(Configuration); }
建议把定义的特性,扩展方法放在Infrastructure层,因为可以全局引用
个人demo,仅供参考。可以运行试试
原理就是根据appsettings里面配置的dll,拼接运行路径,生成dll的绝对路径,然后通过反射获取dll里面的类型,判断类型的自定义特性,获取名称和注入周期,然后写进服务注册里面