Fork me on GitHub

通过反射实现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里面的类型,判断类型的自定义特性,获取名称和注入周期,然后写进服务注册里面

posted @ 2021-02-25 19:12  雪山玉龙  阅读(760)  评论(0编辑  收藏  举报