第七節: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 : 原創博客請在轉載時保留原文鏈接或在文章開頭加上本人博客地址,否則保留追究法律責任的權利。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM