IoC在ASP.NET Web API中的應用
控制反轉(Inversion of Control,IoC),簡單地說,就是應用本身不負責依賴物件的建立和維護,而交給一個外部容器來負責。這樣控制權就由應用轉移到了外部IoC容器,控制權就實現了所謂的反轉。比如在型別A中需要使用型別B的例項,而B例項的建立並不由A來負責,而是透過外部容器來建立。透過IoC的方式實現針對目標HttpController的啟用具有重要的意義。[本文已經同步到《How ASP.NET Web API Works?》]
一、 基於IoC的HttpControllerActivator
將IoC應用於HttpController啟用系統的目的在於讓一個預定義的IoC容器來提供最終的HttpController物件。透過《ASP.NET Web API的Controller是如何被建立的?》的介紹我們知道HttpController的啟用最終由HttpControllerActivator物件來完成,所以將IoC與ASP.NET Web API的HttpController啟用系統進行整合最為直接的方式莫過於自定義一個HttpControllerActivator。
我們透過一個簡單例項來演示如何透過自定義HttpControllerActivator的方式實現與IoC的整合,我們採用的IoC框架是Unity。我們在一個ASP.NET Web API應用中定義了這個UnityHttpControllerActivator型別。UnityHttpControllerActivator具有一個表示Unity容器的屬性UnityContainer,該屬性在建構函式中被初始化。在用於建立的HttpController的Create方法中,我們呼叫此UnityContainer物件的Resolve方法建立目標HttpController物件。
1: public class UnityHttpControllerActivator : IHttpControllerActivator
2: {
3: public IUnityContainer UnityContainer { get; private set; }
4:
5: public UnityHttpControllerActivator(IUnityContainer unityContainer)
6: {
7: this.UnityContainer = unityContainer;
8: }
9:
10: public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
11: {
12: return (IHttpController)this.UnityContainer.Resolve(controllerType);
13: }
14: }
接下來我們定義瞭如下一個繼承自ApiController的ContactsController來管理聯絡人資訊。簡單起見,我們只定義了唯一的Action方法Get用於獲取聯絡人資訊。該方法具有一個可預設的引數id表示希望獲取的聯絡人的ID,如果沒有提供此引數則返回所有聯絡人列表。
1: public class ContactsController : ApiController
2: {
3: public IContactRepository Repository { get; private set; }
4: public ContactsController(IContactRepository repository)
5: {
6: this.Repository = repository;
7: }
8: public IEnumerableGet(string id = "")
9: {
10: return this.Repository.GetContacts(contact =>
11: string.IsNullOrEmpty(id) || id == contact.Id);
12: }
13: }
14:
15: public class Contact
16: {
17: public string Id { get; set; }
18: public string Name { get; set; }
19: public string PhoneNo { get; set; }
20: public string EmailAddress { get; set; }
21: public string Address { get; set; }
22: }
Action方法利用Repository屬性返回的物件來實施聯絡人的查詢工作,這個IContactRepository介面型別的屬性在建構函式中初始化。我們利用IContactRepository介面來抽象對聯絡人資料的儲存,如下面的程式碼片斷所示,我們在此介面中僅定義了唯一的GetContacts方法根據指定的新增來篩選對應的聯絡人列表。
1: public interface IContactRepository
2: {
3: IEnumerableGetContacts(Predicate predicate);
4: }
我們定義瞭如下一個DefaultContactRepository型別作為IContactRepository介面的預設實現者,簡單起見,我們採用一個靜態字典來儲存聯絡人列表。
1: public class DefaultContactRepository : IContactRepository
2: {
3: private static Listcontacts = new List
4: {
5: new Contact{ Id="001", Name = "張三", PhoneNo="123", EmailAddress = "zhangsan@gmail.com"},
6: new Contact{ Id="002", Name = "李四", PhoneNo="456",EmailAddress = "lisi@gmail.com"}
7: };
8:
9: public IEnumerableGetContacts(Predicate predicate)
10: {
11: return contacts.Where(contact=>predicate(contact));
12: }
13: }
我們在Global.asax中對自定義的UnityHttpControllerActivator進行了註冊。如下面的程式碼片斷所示,我們在Application_Start方法中建立了一個UnityContainer物件,並透過呼叫泛型方法RegisterType
1: public class WebApiApplication: System.Web.HttpApplication
2: {
3: protected void Application_Start()
4: {
5: //其他操作
6: IUnityContainer unityContainer = new UnityContainer();
7: unityContainer.RegisterType();
8: GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new UnityHttpControllerActivator(unityContainer));
9: }
10: }
當此ASP.NET Web API應用執行之後,我們可以直接在瀏覽器中輸入相應的地址獲取所有聯絡人列表(“/api/contacts”)和針對某個ID為“001”(“/api/contacts/001”)的聯絡人資訊,相應的聯絡人資訊會以如下圖所示的形式出現在瀏覽器上。
二、基於IoC的DependencyResolver
由於預設的DefaultHttpControllerActivator會先利用當前註冊的DependencyResolver物件去啟用目標HttpController,所以除了利用自定義的HttpControllerActivator將IoC引入HttpController啟用系統之外,另一個有效的方案就是註冊自定義的DependencyResolver。
接下來將要自定義的DependencyResolver基於另一個叫作“Ninject”的IoC框架。較之Unity,Ninject是一個更加輕量級的IoC框架。篇幅所限,我們不便對這個IoC框架作過多的介紹,有興趣的讀者可以訪問其官網(“”)瞭解Ninject。
1: public class NinjectDependencyResolver : IDependencyResolver
2: {
3: private ListdisposableServices = new List ();
4: public IKernel Kernel { get; private set; }
5:
6: public NinjectDependencyResolver(NinjectDependencyResolver parent)
7: {
8: this.Kernel = parent.Kernel;
9: }
10:
11: public NinjectDependencyResolver()
12: {
13: this.Kernel = new StandardKernel();
14: }
15:
16: public void Register() where TTo : TFrom
17: {
18: this.Kernel.Bind().To ();
19: }
20:
21: public IDependencyScope BeginScope()
22: {
23: return new NinjectDependencyResolver(this);
24: }
25:
26: public object GetService(Type serviceType)
27: {
28: return this.Kernel.TryGet(serviceType);
29: }
30:
31: public IEnumerable
32: {
33: foreach (var service in this.Kernel.GetAll(serviceType))
34: {
35: this.AddDisposableService(service);
36: yield return service;
37: }
38: }
39:
40: public void Dispose()
41: {
42: foreach (IDisposable disposable in disposableServices)
43: {
44: disposable.Dispose();
45: }
46: }
47:
48: private void AddDisposableService(object servie)
49: {
50: IDisposable disposable = servie as IDisposable;
51: if (null != disposable && !disposableServices.Contains(disposable))
52: {
53: disposableServices.Add(disposable);
54: }
55: }
56: }
我們建立瞭如上一個型別為NinjectDependencyResolver的自定義DependencyResolver。NinjectDependencyResolver的核心是型別為IKernel的只讀屬性Kernel,用於獲取服務例項的GetService和GetServices方法分別透過呼叫此Kernel屬性的TryGet和GetAll方法來實現。BeginScope方法返回一個新的NinjectDependencyResolver物件,它與自身擁有同一個Kernel物件。我們定義了額外的方法Register
現在我們將這個自定義的NinjectDependencyResolver應用到上一個演示例項中。我們只需要將Global.asax中針對自定義HttpControllerActivator的註冊替換成針對NinjectDependencyResolver的註冊即可。執行此ASP.NET Web API應用後透過瀏覽器試圖獲取聯絡人資訊,我們依然會得到如上圖所示的結果。
1: public class MvcApplication : System.Web.HttpApplication
2: {
3: protected void Application_Start()
4: {
5: //其他操作
6: NinjectDependencyResolver dependencyResolver = new NinjectDependencyResolver();
7: dependencyResolver.Register();
8: GlobalConfiguration.Configuration.DependencyResolver = dependencyResolver;
9: }
10: }
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2558/viewspace-2810982/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 在asp.net web api 2 (ioc autofac) 使用 Serilog 記錄日誌ASP.NETWebAPI
- 聊聊asp.net中Web Api的使用ASP.NETWebAPI
- ASP.NET Web API 應用教程(一) ——資料流使用ASP.NETWebAPI
- ASP.NET Web API 應用教程(一) ——資料流使用ASP.NETWebAPI
- WEB應用是如何運用Spring的?#①Spring的IOC容器如何在WEB中建立?WebSpring
- BurpSuite在非Web應用測試中的應用UIWeb
- 在 Laravel 應用中構建 GraphQL APILaravelAPI
- ASP.NET Web API與Rest web api(一)ASP.NETWebAPIREST
- 建立以 API 為中心的 Web 應用APIWeb
- 在 Node.js 上執行 Flutter Web 應用和 APINode.jsFlutterWebAPI
- ASP.NET Web API 特性ASP.NETWebAPI
- ASP.NET Web API 路由ASP.NETWebAPI路由
- 在asp.net web api中利用過濾器設定輸出快取ASP.NETWebAPI過濾器快取
- MVC模式在Java Web應用程式中的實現MVC模式JavaWeb
- Redis 在 Web 專案中的應用與實踐RedisWeb
- Redis在Web專案中的應用與實踐RedisWeb
- 【ASP.NET Web API教程】2 建立各種Web APIASP.NETWebAPI
- gRPC在 ASP.NET Core 中應用學習RPCASP.NET
- API介面在電商商品資料獲取中的應用API
- API資料介面在電子商務中的應用API
- 商品API資料在電商中的應用與實現API
- 前沿探索|AI 在 API 開發測試中的應用AIAPI
- IOC技術在前端專案中的應用前端
- ASP.NET MVC4中呼叫WEB API的四個方法ASP.NETMVCWebAPI
- 讓ASP.NET Web API的Action方法ASP.NETWebAPI
- rss在web開發過程中的全方位應用Web
- 用Web API Client 呼叫 Web APIWebAPIclient
- 在Docker容器中執行ASP.NET MVC應用程式DockerASP.NETMVC
- 使用ASP.NET Web API構建RESTful APIASP.NETWebAPIREST
- 在Web應用中動態建立PDF檔案Web
- 淘寶詳情API介面在各種應用中的作用性API
- 在Scala中構建Web API的4大框架WebAPI框架
- 【asp.net core 系列】14 .net core 中的IOCASP.NET
- 支付處理器 API :將你的支付應用帶到 Web 中來APIWeb
- web開發實戰教程:Apache Shiro在web專案中的應用WebApache
- Web API中的EventWebAPI
- ASP.NET Web API中通過ETag實現快取ASP.NETWebAPI快取
- 淺談canvas在web開發中的應用與優化CanvasWeb優化