发现AspectCore.Injector的IOC框架写的特别简单,解析服务只有两个方法:Resolve和ResolveMany
有个需求,需要通过Key值来得到某个服务,它是支持不了的,因为注册和解析服务都没有Key值这个参数
为了实现这个功能,对IServiceResolver这个接口的AddType和Resolve的方法进行了重载,添加Key值的参数
大致思想是,用个全局变量存储他Key值的顺序,根据Key值索引得到解析的服务对象,以下是具体代码:
1 public static class ServiceExtension 2 { 3 #region Members 4 public static ConcurrentDictionary<string, List<string>> Container { get; private set; } = new ConcurrentDictionary<string, List<string>>(); 5 #endregion 6 7 #region Extend Methods 8 #region AddType 9 public static IServiceContainer AddType<TService, TImplementation>(this IServiceContainer serviceDefinitions, string key, Lifetime lifetime = Lifetime.Scoped) where TImplementation : TService 10 { 11 var result = serviceDefinitions.AddType<TService, TImplementation>(lifetime); 12 AddContainer<TService>(key); 13 return result; 14 } 15 16 public static IServiceContainer AddType<TService>(this IServiceContainer serviceDefinitions, string key, Lifetime lifetime = Lifetime.Scoped) 17 { 18 var result = serviceDefinitions.AddType<TService>(lifetime); 19 AddContainer<TService>(key); 20 return result; 21 } 22 23 public static IServiceContainer AddType(this IServiceContainer serviceDefinitions, Type serviceType, Type implementationType, string key, Lifetime lifetime = Lifetime.Scoped) 24 { 25 var result = serviceDefinitions.AddType(serviceType, implementationType, lifetime); 26 AddContainer(key, serviceType); 27 return result; 28 } 29 30 public static IServiceContainer AddType(this IServiceContainer serviceDefinitions, Type serviceType, string key, Lifetime lifetime = Lifetime.Scoped) 31 { 32 var result = serviceDefinitions.AddType(serviceType, lifetime); 33 AddContainer(key, serviceType); 34 return result; 35 } 36 #endregion 37 38 #region AddInstance 39 public static IServiceContainer AddInstance<TService>(this IServiceContainer serviceDefinitions, TService implementation, string key) 40 { 41 var result = serviceDefinitions.AddInstance<TService>(implementation); 42 AddContainer<TService>(key); 43 return result; 44 } 45 46 public static IServiceContainer AddInstance(this IServiceContainer serviceDefinitions, Type serviceType, object implementation, string key) 47 { 48 var result = serviceDefinitions.AddInstance(serviceType, implementation); 49 AddContainer(key, serviceType); 50 return result; 51 } 52 #endregion 53 54 #region Resolve 55 public static T Resolve<T>(this IServiceResolver serviceResolver, string key) where T : class 56 { 57 if (key.IsNull()) 58 { 59 return serviceResolver.Resolve<T>(); 60 } 61 62 var typeName = typeof(T)?.FullName ?? string.Empty; 63 if (!Container.ContainsKey(typeName)) 64 { 65 return null; 66 } 67 68 var list = Container[typeName]; 69 var index = list.FindIndex(t => t == key); 70 if (index < 0) 71 { 72 return null; 73 } 74 75 if (list.Count() == 1) 76 { 77 return serviceResolver.Resolve<T>(); 78 } 79 80 var array = serviceResolver.ResolveMany<T>(); 81 if (index >= array.Count()) 82 { 83 return null; 84 } 85 86 return array.ToArray()[index]; 87 } 88 #endregion 89 #endregion 90 91 #region Private Methods 92 private static void AddContainer(string key, Type type) 93 { 94 if (key.IsNull()) 95 { 96 return; 97 } 98 99 var typeName = type?.FullName ?? string.Empty; 100 if (Container.ContainsKey(typeName)) 101 { 102 var list = Container[typeName]; 103 list.Add(key); 104 } 105 else 106 { 107 var list = new List<string> { key }; 108 Container[typeName] = list; 109 } 110 } 111 112 private static void AddContainer<TService>(string key) 113 { 114 AddContainer(key, typeof(TService)); 115 } 116 #endregion 117 }