您好,登錄后才能下訂單哦!
這篇文章主要講解了“ASP.NET MVC示例項目分析”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“ASP.NET MVC示例項目分析”吧!
在這個ASP.NET MVC 示例:Suteki.Shop中,未使用微軟自已的Unity框架來實現IOC,而是使用了大名鼎鼎Castle Windsor。因為引用了Windsor,就有必要簡要介紹一下。而我的理解,這個IOC容器(Container)包括下面幾個重要概念:
容器(Container):Windsor是一個反轉控制容器。它創建在一個微內核的基礎之上,這個微內
核能夠掃描類并且試圖找到這些類用到哪些對象引用、對象依賴,然后把這些依賴信息提供給類使用。
組件(Component):也就是我們通常所說的業務邏輯單元及相應的功能實現,組件是一個可復
用的代碼單元。它應該實現并暴露為一個服務。組件是實現一個服務或接口的類。
服務(Service) :也就是相應的組件接口或N個Component按業務邏輯組合而成的業務邏輯接口。
接口是服務的規范,它創建一個抽象層,你可以輕松的替換服務的實現。
擴張單元插件(Facilities):提供(可擴張)容器以管理組件。
我們可以直接使用組件(會在下面的內容中提到),也可以把組件轉換成相應的服務接口來使用。
還記得上一篇文章中提到的Service嗎? 說白了,它就是一個服務。而Suteki.Shop做的更“夸張”,要是帶有業務邏輯性質的功能代碼都可以被視為Component或服務,比如說前幾篇文章中所提到的Filter,ModelBinder。甚至是服務組件初始化的輔助類(WindsorServiceLocator)也一并拿下。
為了便于理解,下面就到Suteki.Shop中看一下其是如何做的
首先我們看一下整個Suteki.Shop項目啟動的入口,同時這也是Windsor IOC容器初始化的起點。而這塊功能代碼是放在了Global.asax(Suteki.Shop\Global.asax)中的Application_Start方法中實現的,下面是該方法的聲明:
ASP.NET MVC 示例代碼
protected void Application_Start(object sender, EventArgs e) { RouteManager.RegisterRoutes(RouteTable.Routes); InitializeWindsor(); }
代碼中的RouteManager.RegisterRoutes是實現對Route規則的綁定,而規則的內容是被硬編碼到RouteManager中實現的。關于Route的資料網上有不少,園子里也有不少朋友寫過,這里就不做說明了。
接就上面方法就會運行InitializeWindsor(),這就是Windsor容器初始化的方法:
ASP.NET MVC 示例代碼
/// < summary> /// This web application uses the Castle Project's IoC container, Windsor see: /// http://www.castleproject.org/container/index.html /// < /summary> protected virtual void InitializeWindsor() { if (container == null) { // create a new Windsor Container container = ContainerBuilder.Build("Configuration\\Windsor.config"); WcfConfiguration.ConfigureContainer(container); ServiceLocator.SetLocatorProvider(() => container.Resolve< IServiceLocator>()); // set the controller factory to the Windsor controller factory (in MVC Contrib) System.Web.Mvc.ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(container)); } }
注:“Configuration\\Windsor.config”中的內容較長,主要是一些XML配置節點。大家可以抽時間閱讀一下即可。
這個方法是今天講解的主要內容,下面就介紹一下其中的代碼。
首先是判斷container(IWindsorContainer類型)是否為空,如果容器為空則創建并初始化該容器。也就是調用ContainerBuilder(Suteki.Shop\ContainerBuilder)類的Build方法來從外部的config文件中加載默認信息。我們這里就看一下Build方法的實現:
ASP.NET MVC 示例代碼:
public static IWindsorContainer Build(string configPath) { var container = new WindsorContainer(new XmlInterpreter(configPath)); // register handler selectors container.Kernel.AddHandlerSelector(new UrlBasedComponentSelector( typeof(IBaseControllerService), typeof(IImageFileService), typeof(IConnectionStringProvider) )); // automatically register controllers container.Register(AllTypes .Of< Controller>() .FromAssembly(Assembly.GetExecutingAssembly()) .Configure(c => c.LifeStyle.Transient.Named(c.Implementation.Name.ToLower()))); container.Register( Component.For< IUnitOfWorkManager>().ImplementedBy< LinqToSqlUnitOfWorkManager>().LifeStyle.Transient, Component.For< IFormsAuthentication>().ImplementedBy< FormsAuthenticationWrapper>(), Component.For< IServiceLocator>().Instance(new WindsorServiceLocator(container)), Component.For< AuthenticateFilter>().LifeStyle.Transient, Component.For< UnitOfWorkFilter>().LifeStyle.Transient, Component.For< DataBinder>().LifeStyle.Transient, Component.For< LoadUsingFilter>().LifeStyle.Transient, Component.For< CurrentBasketBinder>().LifeStyle.Transient, Component.For< ProductBinder>().LifeStyle.Transient, Component.For< OrderBinder>().LifeStyle.Transient, Component.For< IOrderSearchService>().ImplementedBy< OrderSearchService>().LifeStyle.Transient, Component.For< IEmailBuilder>().ImplementedBy< EmailBuilder>().LifeStyle.Singleton ); return container; }
首先是讀入指定配置文件的XML結點信息,將構造一個 WindsorContainer實現,同時在其微內核中添加“容器處理組件”的方式(AddHandlerSelector),注意這種處理方式是按我們在業務邏輯中規定的方式處理的。
緊跟著又向該容器中注冊了Controller,而且配置屬性的LifeStyle被指定為Transient類型,這里有必要介紹一下Castle容器的組件生存周期,主要有如下幾種:
Singleton : 容器中只有一個實例將被創建
Transient : 每次請求創建一個新實例
PerThread: 每線程中只存在一個實例
PerWebRequest : 每次web請求創建一個新實例
Pooled :使用"池化"方式管理組件,可使用PooledWithSize方法設置池的相關屬性。
可以看到在本項目中,組件的生命周期基本上都被指定成為Transient類型,即當請求發生時創建,在處理結束后銷毀。
接著再看一下該方法的其余代碼,也就是對ModelBinder,Filter,Service這類業務邏輯的組件注冊。同時我們看到有的組類在進行接口注冊的同時還被綁定了默認的實現類,其這種硬編碼的方法是是一種“可選”方式。
說完了Build方法之前,再回到Global.asax文件中的InitializeWindsor方法,看一下其余的代碼。我們看到這樣一行:
WcfConfiguration.ConfigureContainer(container);
類WcfConfiguration的ConfigureContainer方法就是繼續向當前創建的容器中添加組件,而這次要加入的組件是Windows Live Writer的IMetaWeblog接口實現類,如下:
public static class WcfConfiguration { public static void ConfigureContainer(IWindsorContainer container) { var returnFaults = new ServiceDebugBehavior { IncludeExceptionDetailInFaults = true }; container.AddFacility< WcfFacility>(f => { f.Services.AspNetCompatibility = AspNetCompatibilityRequirementsMode.Required; f.DefaultBinding = new XmlRpcHttpBinding(); }) .Register( Component.For< IServiceBehavior>().Instance(returnFaults), Component.For< XmlRpcEndpointBehavior>(), Component.For< IMetaWeblog>().ImplementedBy< MetaWeblogWcf>().Named("metaWebLog").LifeStyle.Transient ); } }
如前面所說的,擴張單元插件(Facilities)可以在不更改原有組件的基礎上注入你所需要的功能代碼,這里就使用了其AddFacility方法來添加擴展單元來注冊并管理我們的Windows Live Writer組件。
下面繼分析InitializeWindsor方法中的其余代碼,看完了ConfigureContainer方法,接著就是下面這一行代碼了:
ServiceLocator.SetLocatorProvider(() => container.Resolve< IServiceLocator>());
剛看到這一行讓我感覺似曾相識,記得以前在看Oxite的Global.asax中也看過類似的這樣一行代碼。
ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(container));
只不過那個項目中用的是 Unity而不是Castle Windsor。但實際的功能是一樣的。即完成對容器中服務地址的解析綁定。有了它,就可以通過Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase中所定義的方法如:DoGetInstance或DoGetAllInstances 來獲取相應的服務組件(集合)的實例。
比如本項目中的DoGetInstance及DoGetAllInstances()實現代碼如下:
(ASP.NET MVC 示例代碼:Suteki.Common\Windsor\WindsorServiceLocator.cs):
protected override object DoGetInstance(Type serviceType, string key) { if (key != null) return container.Resolve(key, serviceType); return container.Resolve(serviceType); } /// < summary> /// When implemented by inheriting classes, this method will do the actual work of /// resolving all the requested service instances. /// < /summary> /// < param name="serviceType">Type of service requested.< /param> /// < returns> /// Sequence of service instance objects. /// < /returns> protected override IEnumerable< object> DoGetAllInstances(Type serviceType) { return (object[])container.ResolveAll(serviceType); }
注,對該WindsorServiceLocator類的IOC綁定在ContainerBuilder.Build中,如下:
container.Register( Component.For< IUnitOfWorkManager>().ImplementedBy< LinqToSqlUnitOfWorkManager>().LifeStyle.Transient, Component.For< IFormsAuthentication>().ImplementedBy< FormsAuthenticationWrapper>(), Component.For< IServiceLocator>().Instance(new WindsorServiceLocator(container)),
而InitializeWindsor方法中的***一行代碼如下:
System.Web.Mvc.ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(container));
這里要說明的是WindsorControllerFactory這個類是在 MvcContrib項目中提供的,用于構造一個Castle項目類型的Controller工廠。
感謝各位的閱讀,以上就是“ASP.NET MVC示例項目分析”的內容了,經過本文的學習后,相信大家對ASP.NET MVC示例項目分析這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。