龙空技术网

让我手把手教你写一个强大、方便使用的 IOC 容器

JAVA互联搬砖工人 160

前言:

此刻咱们对“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