前言:
此刻咱们对“netcore 50”可能比较着重,小伙伴们都需要剖析一些“netcore 50”的相关资讯。那么小编在网络上收集了一些有关“netcore 50””的相关文章,希望大家能喜欢,兄弟们一起来学习一下吧!一、介绍
1、介绍
最近无聊,也没什么事做,没事做总是要给自己找点事情做吧,毕竟人的生活在与折腾。于是,决定自己手动写一个 IOC 的框架。我们知道在 NetCore 的版本里面已经内置了 IOC 容器,它就是 ServiceCollection,一般情况下,该容器还是够用的,但是有时候还会有力不从心的时候,比如:我想要实现属性注入或者方法注入,NetCore 内置的框架就不可以实现。还有情况是,我们要实现对同一接口的多实例注入也没办法实现。当然还有其他情况,比如,没有实现 AOP 的功能。最近正好无事可做,正好利用这段时间,自己亲手写一套 IOC 的框架,当然了,要重写,肯定要比 NetCore 内置的要强,否则,也就没有写的必要了,说干就干。
2、开发环境
1)、操作系统:Windows 10 专业版本。
2)、开发工具:Visual Studio 2019 社区版,16.8.3
3)、开发语言:C#
4)、框架版本:Net 5.0,该版本是跨平台版本,但是不是长期版本,6.0 是 LTS 版本。
3、实现目标
1)、该框架可以实现构造函数注入。
2)、该框架可以实现方法注入。
3)、该框架可以实现属性注入。
4)、该框架可以实现无限层级激活。
5)、该框架可以实现注册服务的多种声明周期,分别是:Transient,Singleton,Scoped,PerThread
6)、该框架可以实现针对同一接口的多实例注册。
7)、当一个类型在实例化的时候可以增加参数。
以上就是该框架的目标,应该还不错吧。毕竟我们自己手写了框架代码,让我们会更加了解 IOC 的定义和实现。
二、手写框架
1、我先把该框架的主要类型的代码贴出来,这个类型是核心类型,实现了我们上面定义的目标。
首先、我们为 IOC 容器定义接口,面向接口编程嘛,可不要忘记了,所以,我们先顶一个接口,类型名称:ICustomContainer。
1 /// <summary> 2 /// 我们定义的 IOC 容器抽象基类型,它定义了 IOC 容器的核心功能。 3 /// </summary> 4 public interface ICustomContainer 5 { 6 /// <summary> 7 /// 提供服务的名称和参数构建实例以 TFrom 类型注册 TTo 实例。 8 /// </summary> 9 /// <typeparam name="TFrom">TTo 的基类类型。</typeparam>10 /// <typeparam name="TTo">TFrom 的子类类型。</typeparam>11 /// <param name="serviceName">要注册服务的名称。</param>12 /// <param name="lifetime">要注册的服务的生命周期。</param> 13 /// <param name="parameterValues">要注册的服务在构建实例时需要的非注入参数。</param>14 void Register<TFrom, TTo>(string serviceName, ServiceLifetime lifetime, params object[] parameterValues) where TTo : TFrom;15 16 /// <summary>17 /// 以指定名称解析该基类型的实例。18 /// </summary>19 /// <typeparam name="TFrom">要解析实例的基类型。</typeparam>20 /// <param name="serviceName">要解析实例的名称。</param>21 /// <returns></returns>22 TFrom Resolve<TFrom>(string serviceName);23 }
再者,就是该接口的实现类型,该类型也是该容器的核心代码。代码不是很难,大家直接看吧。
类型名称:PatrickContainer
1 using System; 2 using System.Collections.Concurrent; 3 using System.Collections.Generic; 4 using System.Linq; 5 using System.Reflection; 6 using System.Threading; 7 8 namespace PatrickLiu.NetCore50.IOCFramework.Container 9 { 10 /// <summary> 11 /// 自定义的IOC容器实现。 12 /// </summary> 13 public sealed class PatrickContainer: ICustomContainer 14 { 15 private readonly IDictionary<string, ServiceMetadata> _Container; 16 private readonly IDictionary<string, object[]> _Parameters; 17 private readonly IDictionary<string, object> _ScopedContainer; 18 19 20 /// <summary> 21 /// 初始化类型的新实例,实例化容器。 22 /// </summary> 23 public PatrickContainer() 24 { 25 _Container = new ConcurrentDictionary<string, ServiceMetadata>(); 26 _Parameters = new ConcurrentDictionary<string, object[]>(); 27 _ScopedContainer = new Dictionary<string, object>(); 28 } 29 30 /// <summary> 31 /// 可以创建子作用域。 32 /// </summary> 33 /// <returns></returns> 34 public PatrickContainer CreateScoped() 35 { 36 return new PatrickContainer(_Container, _Parameters, new Dictionary<string, object>()); 37 } 38 39 /// <summary> 40 /// 通过是有构造函数初始化容器。 41 /// </summary> 42 /// <param name="container"></param> 43 /// <param name="parameters"></param> 44 /// <param name="scopedContainer"></param> 45 private PatrickContainer(IDictionary<string, ServiceMetadata> container, IDictionary<string, object[]> parameters, IDictionary<string, object> scopedContainer) 46 { 47 this._Container = container; 48 this._Parameters = parameters; 49 this._ScopedContainer = scopedContainer; 50 } 51 52 /// <summary> 53 /// 以 TFrom 类型注册 TTo 实例。 54 /// </summary> 55 /// <typeparam name="TFrom">TTo 的基类类型</typeparam> 56 /// <typeparam name="TTo">TFrom 的子类类型。</typeparam> 57 public void Register<TFrom, TTo>() where TTo : TFrom 58 { 59 Register<TFrom, TTo>(null, ServiceLifetime.Transient, null); 60 } 61 62 /// <summary> 63 /// 以 TFrom 类型注册 TTo 实例。 64 /// </summary> 65 /// <typeparam name="TFrom">TTo 的基类类型</typeparam> 66 /// <typeparam name="TTo">TFrom 的子类类型。</typeparam> 67 /// <param name="lifetime">要注册的服务的生命周期。</param> 68 public void Register<TFrom, TTo>(ServiceLifetime lifetime) where TTo : TFrom 69 { 70 Register<TFrom, TTo>(null, lifetime, null); 71 } 72 73 /// <summary> 74 /// 提供服务构建实例所需参数来以 TFrom 类型注册 TTo 实例。 75 /// </summary> 76 /// <typeparam name="TFrom">TTo 的基类类型</typeparam> 77 /// <typeparam name="TTo">TFrom 的子类类型。</typeparam> 78 /// <param name="parameterValues">要注册的服务在构建实例时需要的非注入参数。</param> 79 public void Register<TFrom, TTo>(params object[] parameterValues) where TTo : TFrom 80 { 81 Register<TFrom, TTo>(null, ServiceLifetime.Transient, parameterValues); 82 } 83 84 /// <summary> 85 /// 提供服务的名称构建实例来以 TFrom 类型注册 TTo 实例。 86 /// </summary> 87 /// <typeparam name="TFrom">TTo 的基类类型</typeparam> 88 /// <typeparam name="TTo">TFrom 的子类类型。</typeparam> 89 /// <param name="serviceName">要注册服务的名称。</param> 90 public void Register<TFrom, TTo>(string serviceName) where TTo : TFrom 91 { 92 Register<TFrom, TTo>(serviceName, ServiceLifetime.Transient, null); 93 } 94 95 /// <summary> 96 /// 提供服务的名称构建实例来以 TFrom 类型注册 TTo 实例。 97 /// </summary> 98 /// <typeparam name="TFrom">TTo 的基类类型</typeparam> 99 /// <typeparam name="TTo">TFrom 的子类类型。</typeparam>100 /// <param name="serviceName">要注册服务的名称。</param>101 /// <param name="lifetime">要注册的服务的生命周期。</param>102 public void Register<TFrom, TTo>(string serviceName, ServiceLifetime lifetime) where TTo : TFrom103 {104 Register<TFrom, TTo>(serviceName, lifetime, null);105 }106 107 /// <summary>108 /// 提供服务的名称和参数构建实例以 TFrom 类型注册 TTo 实例。109 /// </summary>110 /// <typeparam name="TFrom">TTo 的基类类型</typeparam>111 /// <typeparam name="TTo">TFrom 的子类类型。</typeparam>112 /// <param name="serviceName">要注册服务的名称。</param>113 /// <param name="lifetime">要注册的服务的生命周期。</param> 114 /// <param name="parameterValues">要注册的服务在构建实例时需要的非注入参数。</param>115 public void Register<TFrom, TTo>(string serviceName, ServiceLifetime lifetime, params object[] parameterValues) where TTo : TFrom116 {117 string key;118 if (string.IsNullOrEmpty(serviceName) || string.IsNullOrWhiteSpace(serviceName))119 {120 key = typeof(TFrom).FullName;121 if (!_Container.ContainsKey(key))122 {123 _Container.Add(key, new ServiceMetadata() { ServiceType = typeof(TTo), Lifetime = lifetime });124 }125 }126 else127 {128 key = string.Format("{0}_{1}", typeof(TFrom).FullName, serviceName);129 if (!_Container.ContainsKey(key))130 {131 _Container.Add(key, new ServiceMetadata() { ServiceType = typeof(TTo), Lifetime = lifetime });132 }133 }134 if (parameterValues != null && parameterValues.Length > 0)135 {136 _Parameters.Add(key, parameterValues);137 }138 }139 140 /// <summary>141 /// 以指定类型解析该类型的实例。142 /// </summary>143 /// <typeparam name="TFrom">要解析实例的基类型。</typeparam>144 /// <returns></returns>145 public TFrom Resolve<TFrom>()146 {147 return Resolve<TFrom>(null);148 }149 150 /// <summary>151 /// 以指定名称解析该基类型的实例。152 /// </summary>153 /// <typeparam name="TFrom">要解析实例的基类型。</typeparam>154 /// <param name="serviceName">要解析实例的名称。</param>155 /// <returns></returns>156 public TFrom Resolve<TFrom>(string serviceName)157 {158 return (TFrom)Create(typeof(TFrom), serviceName);159 }160 161 162 /// <summary>163 /// 通过递归实现解析实例对象。164 /// </summary>165 /// <param name="baseType">服务的基类型。</param>166 /// <param name="serviceName">服务实例的名称。</param>167 /// <returns></returns>168 private object Create(Type baseType, string serviceName = null)169 {170 #region 处理关键字171 172 string keyword;173 174 if (string.IsNullOrEmpty(serviceName) || string.IsNullOrWhiteSpace(serviceName))175 {176 keyword = string.Format("{0}", baseType.FullName);177 }178 else179 {180 keyword = string.Format("{0}_{1}", baseType.FullName, serviceName);181 }182 183 #endregion184 185 Type targetType = null; ServiceLifetime lifetime = ServiceLifetime.Transient;186 if (_Container.ContainsKey(keyword))187 {188 targetType = _Container[keyword].ServiceType;189 lifetime = _Container[keyword].Lifetime;190 }191 else if (keyword.IndexOf('_') != -1)192 {193 if (_Container.ContainsKey(keyword.Split('_')[0]))194 {195 keyword = keyword.Split('_')[0];196 targetType = _Container[keyword].ServiceType;197 lifetime = _Container[keyword].Lifetime;198 }199 }200 else201 {202 throw new Exception("类型还未注册!");203 }204 205 #region 生命周期206 207 switch (lifetime)208 {209 case ServiceLifetime.Transient:210 break;211 case ServiceLifetime.Singleton:212 if (_Container[keyword].SingletonInstance != null)213 {214 return _Container[keyword].SingletonInstance;215 }216 break;217 case ServiceLifetime.Scoped:218 if (_ScopedContainer.ContainsKey(keyword))219 {220 return _ScopedContainer[keyword];221 }222 break;223 case ServiceLifetime.PerThread:224 var objInstance = CallContext.GetData($"{keyword}{Thread.CurrentThread.ManagedThreadId}");225 if (objInstance != null)226 {227 return objInstance;228 }229 break;230 default:231 break;232 }233 234 #endregion235 236 #region 选择构造函数237 238 ConstructorInfo ctor = null;239 240 //1、通过特性约束241 ctor = targetType.GetConstructors().FirstOrDefault(c => c.IsDefined(typeof(SelectedConstructorAttribute), true));242 243 if (ctor == null)244 {245 //2、参数最多的246 ctor = targetType.GetConstructors().OrderByDescending(c => c.GetParameters().Length).First();247 }248 249 #endregion250 251 #region 核心创建对象代码252 253 IList<object> parameters = new List<object>();254 var values = _Parameters.ContainsKey(keyword) ? _Parameters[keyword] : null;255 int index = 0;256 foreach (var parameter in ctor.GetParameters())257 {258 if (values != null && values.Length > 0 && parameter.IsDefined(typeof(ConstantPatameterAttribute), true))259 {260 parameters.Add(values[index++]);261 }262 else263 {264 var parameterType = parameter.ParameterType;265 var instance = Create(parameterType, serviceName);266 parameters.Add(instance);267 }268 }269 object oIntance = Activator.CreateInstance(targetType, parameters.ToArray());270 271 #endregion272 273 #region 属性注入274 275 Type propertyType = null;276 foreach (var property in targetType.GetProperties().Where(p => p.IsDefined(typeof(InjectionPropertyAttribute), true)))277 {278 propertyType = property.PropertyType;279 var propInstance = Create(propertyType);280 property.SetValue(oIntance, propInstance);281 }282 283 #endregion284 285 #region 方法注入286 287 foreach (var methodInfo in targetType.GetMethods().Where(p => p.IsDefined(typeof(InjectionMethodAttribute), true)))288 {289 IList<object> methodParameters = new List<object>();290 values = _Parameters.ContainsKey(keyword) ? _Parameters[keyword] : null;291 index = 0;292 foreach (var parameter in methodInfo.GetParameters())293 {294 if (values != null && values.Length > 0 && parameter.IsDefined(typeof(ConstantPatameterAttribute)))295 {296 methodParameters.Add(values[index++]);297 }298 else299 {300 var methodParaType = parameter.ParameterType;301 var paraInstance = Create(methodParaType, serviceName);302 methodParameters.Add(paraInstance);303 }304 }305 methodInfo.Invoke(oIntance, methodParameters.ToArray());306 }307 308 #endregion309 310 #region 生命周期311 312 switch (lifetime)313 {314 case ServiceLifetime.Transient:315 break;316 case ServiceLifetime.Singleton:317 if (_Container[keyword].SingletonInstance == null)318 {319 _Container[keyword].SingletonInstance = oIntance;320 }321 break;322 case ServiceLifetime.Scoped:323 if (!_ScopedContainer.ContainsKey(keyword))324 {325 _ScopedContainer.Add(keyword, oIntance);326 }327 break;328 case ServiceLifetime.PerThread:329 CallContext.SetData($"{keyword}{Thread.CurrentThread.ManagedThreadId}", oIntance);330 break;331 default:332 break;333 }334 335 #endregion336 337 return oIntance;338 }339 }340 }
当然了,还有一些其他的辅助类型,这么大的框架,还是要需要一些辅助类型的,接下来我们一一介绍。
2、ConstantPatameterAttribute类型
该类型是一个标记特性,用于标注不需要注入而进行传递的参数,可以使用该属性。
1 using System; 2 3 namespace PatrickLiu.NetCore50.IOCFramework.Container 4 { 5 /// <summary> 6 /// 该类型定义了在服务初始化的时候需要从外界出入的参数,如果参数被标注,则说明改参数所需要的参数从外界传入。该类型是密封类型,不可以被继承。 7 /// </summary> 8 [AttributeUsage(AttributeTargets.Parameter|AttributeTargets.GenericParameter,AllowMultiple =false,Inherited =true)] 9 public sealed class ConstantPatameterAttribute:Attribute10 {11 }12 }
3、InjectionMethodAttribute 类型
该类型也是一个标记特性,用于标记方法,可以通过方法实现注入。
1 using System; 2 3 namespace PatrickLiu.NetCore50.IOCFramework.Container 4 { 5 /// <summary> 6 /// 该类型定义了方法注入的特性类型,该类型是密封类型,不可以被继承。它也是一个标识类型。 7 /// </summary> 8 [AttributeUsage(AttributeTargets.Method,AllowMultiple =false,Inherited =true)] 9 public sealed class InjectionMethodAttribute:Attribute10 {11 }12 }
4、InjectionPropertyAttribute 类型。
该类型也是一个标记特性,用于标记正在属性上,可以通过属性实现注入。
1 using System; 2 3 namespace PatrickLiu.NetCore50.IOCFramework.Container 4 { 5 /// <summary> 6 /// 该特性是一个实现属性注入的特性类,该类型是密封的。它是一个标识属性。 7 /// </summary> 8 [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] 9 public sealed class InjectionPropertyAttribute : Attribute10 {11 }12 }
5、SelectedConstructorAttribute 类型
在我们构建类型实例的时候,可以通过该特性选择通过哪个构造函数创建实例。默认情况是选择参数最多的构造函数,也可以通过该特性选择构造函数。
1 using System; 2 3 namespace PatrickLiu.NetCore50.IOCFramework.Container 4 { 5 /// <summary> 6 /// 选择构造函数。 7 /// </summary> 8 [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = true)] 9 public sealed class SelectedConstructorAttribute : Attribute10 {11 }12 }
6、ServiceLifetime 枚举类型。
我们可以实现对注册服务的生命周期的管理,类型简单,不多说了。
1 namespace PatrickLiu.NetCore50.IOCFramework.Container 2 { 3 /// <summary> 4 /// 服务的生命周期。 5 /// </summary> 6 public enum ServiceLifetime 7 { 8 /// <summary> 9 /// 瞬时服务实例。10 /// </summary>11 Transient,12 13 /// <summary>14 /// 单例服务实例。15 /// </summary>16 Singleton,17 18 /// <summary>19 /// 作用域服务实例。20 /// </summary>21 Scoped,22 23 /// <summary>24 /// 线程服务实例。25 /// </summary>26 PerThread27 }28 }
7、ServiceMetadata 类型。
用于定义注册服务的对象。
1 using System; 2 3 namespace PatrickLiu.NetCore50.IOCFramework.Container 4 { 5 /// <summary> 6 /// 该类型定义了注册服务的元数据。 7 /// </summary> 8 public sealed class ServiceMetadata 9 {10 /// <summary>11 /// 获取或者设置注册服务的类型。12 /// </summary>13 public Type ServiceType { get; set; }14 15 /// <summary>16 /// 获取或者设置注册服务的生命周期。17 /// </summary>18 public ServiceLifetime Lifetime { get; set; }19 20 /// <summary>21 /// 获取或者设置单件的服务实例。22 /// </summary>23 public Object SingletonInstance { get; set; }24 }25 }
8、CallContext类型。
在NetCore 环境中,没有CallContext 类型,所以只能自己实现一个,可以实现基于线程来管理注册服务的生命周期。
1 using System.Collections.Concurrent; 2 using System.Threading; 3 4 namespace PatrickLiu.NetCore50.IOCFramework.Container 5 { 6 /// <summary> 7 /// Provides a way to set contextual data that flows with the call and async context of a test or invocation. 8 /// </summary> 9 public static class CallContext10 {11 private static ConcurrentDictionary<string, AsyncLocal<object>> state = new ConcurrentDictionary<string, AsyncLocal<object>>();12 13 /// <summary>14 /// Stores a given object and associates it with the specified name.15 /// </summary>16 /// <param name="name">The name with which to associate the new item in the call context.</param>17 /// <param name="data">The object to store in the call context.</param>18 public static void SetData(string name, object data) =>19 state.GetOrAdd(name, _ => new AsyncLocal<object>()).Value = data;20 21 /// <summary>22 /// Retrieves an object with the specified name from the <see cref="CallContext"/>.23 /// </summary>24 /// <param name="name">The name of the item in the call context.</param>25 /// <returns>The object in the call context associated with the specified name, or <see langword="null"/> if not found.</returns>26 public static object GetData(string name) =>27 state.TryGetValue(name, out AsyncLocal<object> data) ? data.Value : null;28 }29 30 /// <summary>31 /// 可以测试32 /// </summary>33 /// <typeparam name="T"></typeparam>34 public static class CallContext<T>35 {36 static ConcurrentDictionary<string, AsyncLocal<T>> state = new ConcurrentDictionary<string, AsyncLocal<T>>();37 38 /// <summary>39 /// Stores a given object and associates it with the specified name.40 /// </summary>41 /// <param name="name">The name with which to associate the new item in the call context.</param>42 /// <param name="data">The object to store in the call context.</param>43 public static void SetData(string name, T data) =>44 state.GetOrAdd(name, _ => new AsyncLocal<T>()).Value = data;45 46 /// <summary>47 /// Retrieves an object with the specified name from the <see cref="CallContext"/>.48 /// </summary>49 /// <typeparam name="T">The type of the data being retrieved. Must match the type used when the <paramref name="name"/> was set via <see cref="SetData{T}(string, T)"/>.</typeparam>50 /// <param name="name">The name of the item in the call context.</param>51 /// <returns>The object in the call context associated with the specified name, or a default value for <typeparamref name="T"/> if none is found.</returns>52 public static T GetData(string name) =>53 state.TryGetValue(name, out AsyncLocal<T> data) ? data.Value : default(T);54 }55 }
三、测试代码
我们为了更好的测试我们写的IOC容器,我另外建立两个独立的类库项目和一个控制台应用程序。当然了,引用关系别忘记了。
1、我们定义的接口类库,里面包含了测试用到的所有接口类型。很简单,不多说。
以下就是我们接口的代码了。
1 /// <summary>2 /// ServiceA的服务接口3 /// </summary>4 public interface IServiceA5 {6 void Show();7 }
1 public interface IServiceB2 {3 void Show();4 }
1 public interface IServiceC2 {3 void Show();4 }
1 public interface IServiceD2 {3 void Show();4 }
1 public interface IServiceE2 {3 void Show();4 }
1 public interface IServiceF2 {3 void Show();4 }
2、第一步我们定义了接口类库,这里我们定义实现了接口类库的服务类库,很简单,不多说。
以下是实现代码,很简单,不多说。
1 /// <summary> 2 /// 自定义类型的服务。 3 /// </summary> 4 public class MyServiceA : IServiceA 5 { 6 public MyServiceA() 7 { 8 Console.WriteLine("MyServiceA is Created"); 9 } 10 11 /// <summary>12 /// 方法执行13 /// </summary>14 public void Show()15 {16 Console.WriteLine("MyServiceA-show()");17 }18 }
1 /// <summary> 2 /// 自定义类型服务第二版本。 3 /// </summary> 4 public sealed class MyServiceA2 : IServiceA 5 { 6 private IServiceF _IServiceF; 7 8 /// <summary> 9 /// 构造函数10 /// </summary>11 public MyServiceA2()12 {13 Console.WriteLine("MyServiceA2 is created");14 }15 16 /// <summary>17 /// 方法注入。18 /// </summary>19 /// <param name="service"></param>20 [InjectionMethod]21 public void MethodInjection(IServiceF service)22 {23 _IServiceF = service;24 }25 26 /// <summary>27 /// 方法执行。28 /// </summary>29 public void Show()30 {31 Console.WriteLine("MyServiceA2--Show()");32 }33 }
1 public class MyServiceA3 : IServiceA 2 { 3 /// <summary> 4 /// 5 /// </summary> 6 /// <param name="age"></param> 7 /// <param name="name"></param> 8 /// <param name="school"></param> 9 public MyServiceA3([ConstantPatameter]int age, [ConstantPatameter] string name, [ConstantPatameter] string school)10 {11 Console.WriteLine($"{age}{name}{school} MyServiceA3 is created");12 }13 14 15 public void Show()16 {17 Console.WriteLine("MyServiceA3-Show() is executed!");18 }19 }
1 public class MyServiceA4 : IServiceA 2 { 3 private IServiceF _IServiceF; 4 5 public MyServiceA4() 6 { 7 Console.WriteLine(""); 8 } 9 10 /// <summary>11 /// 方法注入12 /// </summary>13 /// <param name="service">注入服务</param>14 /// <param name="age"></param>15 /// <param name="name"></param>16 [InjectionMethod]17 public void MethodInjection(IServiceF service,[ConstantPatameter]int age,[ConstantPatameter]string name)18 {19 _IServiceF = service;20 Console.WriteLine($"{name} 今年 {age} 岁了。");21 }22 23 public void Show()24 {25 Console.WriteLine("MyServiceA4--show() executing");26 }27 }
1 /// <summary> 2 /// 3 /// </summary> 4 public class MyServiceB : IServiceB 5 { 6 /// <summary> 7 /// 8 /// </summary> 9 /// <param name="serviceC"></param>10 /// <param name="serviceE"></param>11 public MyServiceB(IServiceC serviceC,IServiceE serviceE)12 {13 Console.WriteLine("MyServiceB is created");14 }15 16 /// <summary>17 /// 18 /// </summary>19 public void Show()20 {21 Console.WriteLine("MyServiceB-Show()");22 }23 }
1 /// <summary> 2 /// 3 /// </summary> 4 public class MyServiceC : IServiceC 5 { 6 /// <summary> 7 /// 8 /// </summary> 9 /// <param name="serviceD"></param>10 public MyServiceC(IServiceD serviceD)11 {12 Console.WriteLine("MyServiceC is created");13 }14 15 /// <summary>16 /// 17 /// </summary>18 public void Show()19 {20 Console.WriteLine("MyServiceC-Show()");21 }22 }
1 /// <summary> 2 /// 自定义类型的服务。 3 /// </summary> 4 public class MyServiceD : IServiceD 5 { 6 /// <summary> 7 /// 构造函数 8 /// </summary> 9 public MyServiceD()10 {11 Console.WriteLine("MyServiceD is created");12 }13 14 /// <summary>15 /// 方法执行。16 /// </summary>17 public void Show()18 {19 Console.WriteLine("MyServiceD--show()");20 }21 }
1 /// <summary> 2 /// 自定义服务类型。 3 /// </summary> 4 public class MyServiceE : IServiceE 5 { 6 /// <summary> 7 /// 构造函数 8 /// </summary> 9 public MyServiceE()10 {11 Console.WriteLine("MyServiceE is created");12 }13 14 /// <summary>15 /// 属性注入16 /// </summary>17 [InjectionProperty]18 public IServiceF ServiceF { get; set; }19 20 /// <summary>21 /// 方法执行。22 /// </summary>23 public void Show()24 {25 Console.WriteLine("MyServiceE-Show()");26 }27 }
1 /// <summary> 2 /// 自定义类型服务。 3 /// </summary> 4 public sealed class MyServiceF : IServiceF 5 { 6 /// <summary> 7 /// 构造函数 8 /// </summary> 9 public MyServiceF()10 {11 Console.WriteLine("MyServiceF is created!");12 }13 14 /// <summary>15 /// 方法执行。16 /// </summary>17 public void Show()18 {19 Console.WriteLine("MyServiceF--Show()");20 }21 }
3、这个代码就是我们控制台项目,用来做测试的,很简单,不多说了。
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 //最简单版本 6 { 7 PatrickContainer container = new PatrickContainer(); 8 container.Register<IServiceA, MyServiceA>(); 9 10 var instance = container.Resolve<IServiceA>(); 11 instance.Show(); 12 } 13 //可以多层依赖,可以包含属性注入 14 { 15 PatrickContainer container = new PatrickContainer(); 16 container.Register<IServiceA, MyServiceA>(); 17 container.Register<IServiceB, MyServiceB>(); 18 container.Register<IServiceC, MyServiceC>(); 19 container.Register<IServiceD, MyServiceD>(); 20 container.Register<IServiceE, MyServiceE>(); 21 container.Register<IServiceF, MyServiceF>(); 22 23 var instance = container.Resolve<IServiceB>(); 24 instance.Show(); 25 } 26 //单接口多实例,也包含方法注入 27 { 28 PatrickContainer container = new PatrickContainer(); 29 container.Register<IServiceA, MyServiceA>("A"); 30 container.Register<IServiceA, MyServiceA2>("A2"); 31 container.Register<IServiceF, MyServiceF>(); 32 33 var instance = container.Resolve<IServiceA>("A"); 34 instance.Show(); 35 instance = container.Resolve<IServiceA>("A2"); 36 instance.Show(); 37 } 38 //构造函数参数、方法参数 39 { 40 PatrickContainer container = new PatrickContainer(); 41 42 container.Register<IServiceA, MyServiceA3>(20,"zhangfei","涞源第一中学"); 43 44 var instance = container.Resolve<IServiceA>(); 45 instance.Show(); 46 } 47 { 48 PatrickContainer container = new PatrickContainer(); 49 50 container.Register<IServiceA, MyServiceA4>(20, "张飞"); 51 container.Register<IServiceF, MyServiceF>(); 52 53 var instance = container.Resolve<IServiceA>(); 54 instance.Show(); 55 } 56 //声明周期 57 { 58 //单例 59 PatrickContainer container = new PatrickContainer(); 60 container.Register<IServiceA, MyServiceA>(ServiceLifetime.Singleton); 61 62 63 var instance = container.Resolve<IServiceA>(); 64 var instance2 = container.Resolve<IServiceA>(); 65 66 Console.WriteLine(Object.ReferenceEquals(instance,instance2));//True 67 } 68 // 69 { 70 //瞬时 71 PatrickContainer container = new PatrickContainer(); 72 container.Register<IServiceA, MyServiceA>(ServiceLifetime.Transient); 73 74 75 var instance = container.Resolve<IServiceA>(); 76 var instance2 = container.Resolve<IServiceA>(); 77 78 Console.WriteLine(Object.ReferenceEquals(instance, instance2));//False 79 } 80 { 81 //作用域 82 PatrickContainer container = new PatrickContainer(); 83 container.Register<IServiceA, MyServiceA>(ServiceLifetime.Scoped); 84 85 86 var instance = container.Resolve<IServiceA>(); 87 var instance2 = container.Resolve<IServiceA>(); 88 89 Console.WriteLine(Object.ReferenceEquals(instance, instance2));//True 90 91 var container2 = container.CreateScoped(); 92 var objedd=container2.Resolve<IServiceA>(); 93 var objedd2=container2.Resolve<IServiceA>(); 94 95 /Console.WriteLine(Object.ReferenceEquals(objedd, objedd2));//True 96 97 Console.WriteLine(Object.ReferenceEquals(instance, objedd2));//False 98 Console.ReadLine(); 99 }100 {101 //线程102 PatrickContainer container = new PatrickContainer();103 container.Register<IServiceA, MyServiceA>(ServiceLifetime.PerThread);104 105 IServiceA instance = null;106 IServiceA instance2 = null;107 IServiceA instance3 = null;108 IServiceA instance4 = null;109 IServiceA instance5 = null;110 IServiceA instance6 = null;111 112 Task.Run(()=> {113 Console.WriteLine($"instance,当前线程的ID:{Thread.CurrentThread.ManagedThreadId}");114 instance = container.Resolve<IServiceA>();115 });116 117 Task.Run(() => {118 Console.WriteLine($"instance2,当前线程的ID:{Thread.CurrentThread.ManagedThreadId}");119 instance2 = container.Resolve<IServiceA>();120 });121 122 Task.Run(() => {123 Console.WriteLine($"instance3 和 instance4,当前线程的ID:{Thread.CurrentThread.ManagedThreadId}");124 instance3 = container.Resolve<IServiceA>();125 instance4 = container.Resolve<IServiceA>();126 });127 128 Task.Run(() => {129 Console.WriteLine($"instance5,当前线程的ID:{Thread.CurrentThread.ManagedThreadId}");130 instance5 = container.Resolve<IServiceA>();131 }).ContinueWith(t=> {132 Console.WriteLine($"instance6,当前线程的ID:{Thread.CurrentThread.ManagedThreadId}");133 instance6 = container.Resolve<IServiceA>();134 });135 136 Thread.Sleep(1000);137 138 Console.WriteLine(Object.ReferenceEquals(instance, instance2));//False139 Console.WriteLine(Object.ReferenceEquals(instance, instance3));//False140 Console.WriteLine(Object.ReferenceEquals(instance, instance4));//False141 Console.WriteLine(Object.ReferenceEquals(instance2, instance3));//False142 Console.WriteLine(Object.ReferenceEquals(instance2, instance4));//False143 Console.WriteLine(Object.ReferenceEquals(instance3, instance4));//True144 145 Console.WriteLine(Object.ReferenceEquals(instance5, instance6));//False 146 }147 148 Console.Read();149 }150 }
四、结束
好了,今天就写到这里了,实话实说,这个有难度吗?其实没什么难度。这些代码都是可以直接使用的,我经过测试的,(我也有可能没有测试到的),如果大家感觉不错,可以拿去使用,好好的测试一下,也可以增加自己的东西,功能挺强大的,使用挺方便的。不忘初心,继续努力。
天下国家,可均也;爵禄,可辞也;白刃,可蹈也;中庸不可能也
标签: #netcore 50