• 第七节:WebApi与Unity整合进行依赖注入和AOP的实现


    一. IOC和DI

    1. 通过Nuget引入Unity程序集。

        PS:【版本:5.8.6】

    2. 新建DIFactory类,用来读取Unity的配置文件并创建Unity容器,需要注意的是DIFactory类需要声明成单例。

    PS:这里采用静态构造函数(必须是无参的)的形式来实现单例,MVC框架的那个框架采用的是 双if+lock锁的形式实现的单例,结果都一样。

    代码分享:

     1      /// <summary>
     2     /// 依赖注入工厂(单例的 采用静态构造函数)
     3     /// 读取Unity的配置文件,并创建Unity容器
     4     /// 需要引入程序集“System.Configuration”
     5     /// </summary>
     6     public class DIFactory
     7     {
     8         private static IUnityContainer _Container = null;
     9         static DIFactory()
    10         {
    11             //1. 固定的4行代码读取配置文件
    12             ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
    13             fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\UnityConfig.xml");//找配置文件的路径
    14             Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
    15             UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
    16             //2. Unity层次的步骤
    17             _Container = new UnityContainer();
    18             //加载节点的名称为"apiContainer"
    19             section.Configure(_Container, "apiContainer");
    20         }
    21         
    22         /// <summary>
    23         /// 对外开放函数,用来获取Unity容器
    24         /// </summary>
    25         /// <returns></returns>
    26         public static IUnityContainer GetContainer()
    27         {
    28             return _Container;
    29         }
    30     }

    3. 新建UnityDependencyResolver类,用来自定义控制器实例化工厂.

    特别注意:该类这里实现的是IDependencyResolver接口,来自WebApi下的程序集,而非MVC,所以和MVC下的写法有区别.

    代码分享:

     1   public class UnityDependencyResolver : IDependencyResolver
     2     {
     3         private IUnityContainer _IUnityContainer = null;
     4         public UnityDependencyResolver(IUnityContainer unityContainer)
     5         {
     6             this._IUnityContainer = unityContainer;
     7         }
     8 
     9         /// <summary>
    10         /// 获取单个服务
    11         /// </summary>
    12         /// <param name="serviceType"></param>
    13         /// <returns></returns>
    14         public object GetService(Type serviceType)
    15         {
    16             try
    17             {
    18                 return this._IUnityContainer.Resolve(serviceType);
    19             }
    20             catch (ResolutionFailedException ex)//因为会累计构造多个对象,很多是没有去扩展,直接null就行
    21             {
    22                 return null;
    23             }
    24         }
    25 
    26         public IEnumerable<object> GetServices(Type serviceType)
    27         {
    28             try
    29             {
    30                 return this._IUnityContainer.ResolveAll(serviceType);
    31             }
    32             catch (ResolutionFailedException)
    33             {
    34                 return new List<object>();
    35             }
    36         }
    37 
    38         public IDependencyScope BeginScope()//每次请求
    39         {
    40             var child = this._IUnityContainer.CreateChildContainer();
    41             return new UnityDependencyResolver(child);
    42         }
    43 
    44         public void Dispose()
    45         {
    46             this._IUnityContainer.Dispose();
    47         }
    48     }
    UnityDependencyResolver

    4. 新建CfgFiles文件夹和UnityConfig.xml文件,该xml文件需要改属性为“始终复制”。

    代码分享:

    <configuration>
      <configSections>
        <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration"/>
      </configSections>
      <unity>
        <!-- unity容器配置注册节点-->
        <containers>
          <container name="apiContainer">
            <!--  type中的两个参数分别是:类型名称和DLL程序集的名称 -->
            <!--  mapTo中的两个参数分别是:类型名称和DLL程序集的名称 -->
            <!--
              分析:这里我们需要使用的是TestService,但不直接使用它,而是使用它的接口,即将【mapTo】里的类型注册给【type】里的类型
            -->
            <register type="WebApiBasic.Interface.ITestService,01-WebApiBasic" mapTo="WebApiBasic.Service.TestService,01-WebApiBasic"/>
            <register type="WebApiBasic.Interface.ITestService2,01-WebApiBasic" mapTo="WebApiBasic.Service.TestService2,01-WebApiBasic"/>
          </container>
        </containers>
      </unity>
    </configuration>

    5. 在WebApiConfig文件中进行配置,把webapi的DependencyResolver换成自己的Unity版本的

    config.DependencyResolver = new UnityDependencyResolver(DIFactory.GetContainer());

    6. 新建Service文件夹和Interface文件夹,分别创建TestService类和ITestService接口,并去UnityConfig.xml文件中进行注册(上述xml里已经注册好了)。

    代码如下:

    1  public class TestService : ITestService
    2     {
    3         public string GetInfor()
    4         {
    5             return "我是ypf";
    6         }
    7     }
    1  public interface ITestService
    2     {
    3         string GetInfor();
    4     }

    7. 在控制器中进行构造函数的注入,注入TestService对象。

    public class EighthController : ApiController
        {
            private ITestService _ITestService = null;
            public EighthController(ITestService testService)
            {
                this._ITestService = testService;
            }
            [HttpGet]
            public string GetInfor()
            {
                var result = _ITestService.GetInfor();
                return result;
            }
        }

    8. 利用PostMan进行测试 http://localhost:2131/api/Eighth/GetInfor, 测试成功。

     

    二. AOP

    1. 通过Nuget引入Unity.Interception程序集,同时会自动把它依赖的Unity.Abstractions程序集引入。

    PS:【版本:5.5.3】

    2. 新增TestService2类和ITestService2接口,用来测试AOP。

    代码如下:

     1  public interface ITestService2
     2     {
     3         string GetInfor2();
     4     }
     5 public class TestService2 : ITestService2
     6     {
     7         public string GetInfor2()
     8         {
     9             return "我是ypf2";
    10         }
    11     }

    3. 新建AOP文件夹,并新建LogBeforeBehavior类,实现IInterceptionBehavior接口,在Invoke中写AOP相关的代码。

     1     /// <summary>
     2     /// Unity为我们提供了一个IInterceptionBehavior接口需要实现这个接口
     3     /// 接口为我们提供了三个方式(GetRequiredInterfaces、Invoke、WillExecute)实现
     4     /// WillExecute表示是否执行该行为,如果是false这个方法被调用时,不会被捕捉。因为我们总是要执行的,所以为true
     5     /// GetRequiredInterfaces将你想要的接口类型和行为联系起来,我们暂时不需要,所以返回Type.EmptyTypes
     6     /// Invoke执行方式接口,我们主要使用它
     7     /// </summary>
     8     public class LogBeforeBehavior : IInterceptionBehavior
     9     {
    10         public bool WillExecute
    11         {
    12             get { return true; }
    13         }
    14 
    15         public IEnumerable<Type> GetRequiredInterfaces()
    16         {
    17             return Type.EmptyTypes;
    18         }
    19 
    20         public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
    21         {
    22             Console.WriteLine("我是方法执行前执行的业务");
    23 
    24             //下面这句话表示这里执行方法
    25             var result = getNext()(input, getNext);
    26             return result;
    27         }
    28     }

    4. 在UnityConifig.xml文件中配置AOP相关的代码,并且给TestService2注入的代码配置AOP相关的LogAopBehavior类。

    代码分享:

     1 <configuration>
     2   <configSections>
     3     <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration"/>
     4   </configSections>
     5   <unity>
     6     <!--Unity的AOP的相关配置-->
     7     <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration"/>
     8     <!-- unity容器配置注册节点-->
     9     <containers>
    10       <container name="apiContainer">
    11         <!--Unity的AOP的相关配置-->
    12         <extension type="Interception"/>
    13         <!--  type中的两个参数分别是:类型名称和DLL程序集的名称 -->
    14         <!--  mapTo中的两个参数分别是:类型名称和DLL程序集的名称 -->
    15         <!--
    16           分析:这里我们需要使用的是TestService,但不直接使用它,而是使用它的接口,即将【mapTo】里的类型注册给【type】里的类型
    17         -->
    18         <register type="WebApiBasic.Interface.ITestService,01-WebApiBasic" mapTo="WebApiBasic.Service.TestService,01-WebApiBasic"/>
    19         <register type="WebApiBasic.Interface.ITestService2,01-WebApiBasic" mapTo="WebApiBasic.Service.TestService2,01-WebApiBasic">
    20           <interceptor type="InterfaceInterceptor"/>
    21           <interceptionBehavior type="WebApiBasic.AOP.LogBeforeBehavior,01-WebApiBasic"/>
    22         </register>
    23       </container>
    24     </containers>
    25   </unity>
    26 </configuration>
    View Code

    5. 用PostMan进行测试 http://localhost:2131/api/Eighth/GetInfor2 ,通过加断点,发现:执行方法前,先进入了LogBeforeBehavior类中进行执行了。

    !

    • 作       者 : Yaopengfei(姚鹏飞)
    • 博客地址 : http://www.cnblogs.com/yaopengfei/
    • 声     明1 : 本人才疏学浅,用郭德纲的话说“我是一个小学生”,如有错误,欢迎讨论,请勿谩骂^_^。
    • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
     
  • 相关阅读:
    Stochastic Gradient Descent
    混合高斯模型(Mixtures of Gaussians)和EM算法
    支持向量机通俗导论(理解SVM的三层境界)
    第十二课、计算器的核心解析算法(上)------------------狄泰软件学院
    第十一课、Qt中的字符串类------------------狄泰软件学院
    第十课、初探Qt的消息处理------------------狄泰软件学院
    第九课、计算器界面代码重构------------------狄泰软件学院
    第八课、启航!第一个应用程序------------------狄泰软件学院
    第七课、Qt中的坐标系统------------------狄泰软件学院
    第六课、窗口组件及窗口类型------------------狄泰软件学院
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/10410255.html
Copyright © 2020-2023  润新知