欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

自定義的ControllerFactory接口如何實(shí)現(xiàn)支持Area

這篇文章將為大家詳細(xì)講解有關(guān)自定義的ControllerFactory接口如何實(shí)現(xiàn)支持Area,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關(guān)知識有一定的了解。

成都創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),桐廬企業(yè)網(wǎng)站建設(shè),桐廬品牌網(wǎng)站建設(shè),網(wǎng)站定制,桐廬網(wǎng)站建設(shè)報(bào)價,網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,桐廬網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競爭力。可充分滿足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時我們時刻保持專業(yè)、時尚、前沿,時刻以成就客戶成長自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。

幾個星期之前,有個朋友對我說,他的項(xiàng)目中需要將前后臺區(qū)分開來,也就是類似分Area的功能。不過Area只在MVC 2中出現(xiàn),因此現(xiàn)在想在1.0版本中先實(shí)現(xiàn)類似的功能了。他打算,根據(jù)Route中捕獲的內(nèi)容(如“area”),然后去找對應(yīng)命名空間下的Controller。這樣看來不難,似乎只要在Route上做點(diǎn)配置,而默認(rèn)的DefaultControllerFactory已經(jīng)對命名空間的查詢提供支持了(可惜有線程安全的問題)。

不過他說,發(fā)現(xiàn)似乎這塊功能不是他想象的那樣,因此希望我可以看看到底是什么問題。由于當(dāng)時沒有擴(kuò)展ASP.NET MVC的需求,后來我事情一多就忘了,現(xiàn)在先說聲抱歉。最近開始對ASP.NET MVC動手動腳了,發(fā)現(xiàn)這樣一個Area的功能非常有用,而且巧合的是,我也打算把Area和命名空間對應(yīng)起來。

只是我選擇的路和那位兄弟不一樣,我打算自己寫一個簡單的ControllerFactory來替換掉默認(rèn)的DefaultControllerFactory。這么做的主要原因是:我不知道DefaultControllerFactory已經(jīng)提供對命名空間的支持了,微軟默默地實(shí)現(xiàn)了卻沒有對外公開過,我也是后來閱讀代碼時才發(fā)現(xiàn)的。同時又意識到線程安全的問題,于是就還是打算自己寫了。

好在ASP.NET MVC從設(shè)計(jì)之初就提供了擴(kuò)展的能力,每個組件粒度都很小,大部分組件都是可以獨(dú)立拔插的(Controller類除外,如果你使用自己的IController實(shí)現(xiàn),就會發(fā)現(xiàn)大部分功能,如各Filter都失效了)。而要實(shí)現(xiàn)一個Controller Factory,只要實(shí)現(xiàn)一個簡單的IControllerFactory就可以了(我喜歡接口):

public interface IControllerFactory  {      IController CreateController(RequestContext requestContext, string controllerName);      void ReleaseController(IController controller);  }

于是構(gòu)建一個AreaControllerFactory也大致只需要以下一些代碼:

public class AreaControllerFactory : IControllerFactory  {      public IController CreateController(RequestContext requestContext, string controllerName)      {          ...      }       public void ReleaseController(IController controller)      {          IDisposable disposable = controller as IDisposable;          if (disposable != null)          {              disposable.Dispose();          }      }  }

然后按照慣例,還是一步步談起。首先是構(gòu)造函數(shù),我們的策略是根據(jù)不同的Area加載不同命名空間下的Controller類型。方便起見,我選擇“基礎(chǔ)命名空間”和“擴(kuò)展部分”兩塊,它們從構(gòu)造函數(shù)中傳入:

private Dictionary<string, string> m_areaPartMapping = new Dictionary<string, string>();   public string NamespaceBase { get; private set; }   public AreaControllerFactory(string namespaceBase)      : this(namespaceBase, null)  { }   public AreaControllerFactory(string namespaceBase, IDictionary<string, string> areaPartMapping)  {      this.NamespaceBase = namespaceBase.EndsWith(".") ? namespaceBase : namespaceBase + ".";       if (areaPartMapping != null)      {          foreach (var pair in areaPartMapping)          {              this.m_areaPartMapping.Add(pair.Key.ToLowerInvariant(), pair.Value);          }      }  }

于是我們就可以這樣使用:

var controllerFactory = new AreaControllerFactory("MyApp.Controllers");  ControllerBuilder.Current.SetControllerFactory(controllerFactory);

如果在需要的時候,還可以指定Area與特定命名空間“部分”的映射關(guān)系。因此,我們需要從Area來獲取這個“Part”:

private string GetNamespacePart(string area)  {      if (String.IsNullOrEmpty(area)) return "";       string part;      if (this.m_areaPartMapping.TryGetValue(area.ToLowerInvariant(), out part))      {          return part;      }       return area;  }

這里我選擇“配置”和“約定”相結(jié)合的方式。得到一個Area之后,我們會在映射表里進(jìn)行查找Part,如果沒有,則Area本身便是Part。根據(jù)Part和Controller名稱,我們便可以獲得Controller的類型:

private ReaderWriterLockSlim m_rwLock = new ReaderWriterLockSlim();  private Dictionary<string, Type> m_controllerTypes = new Dictionary<string, Type>();   private Type GetControllerType(string area, string controllerName)  {      string part = this.GetNamespacePart(area);       string typeName = String.IsNullOrEmpty(part) ?          this.NamespaceBase + controllerName.ToLowerInvariant() + "Controller" :          this.NamespaceBase + part + "." + controllerName.ToLowerInvariant() + "Controller";       Type type;       this.m_rwLock.EnterReadLock();      try     {          if (this.m_controllerTypes.TryGetValue(typeName, out type))          {              return type;          }      }      finally     {          this.m_rwLock.ExitReadLock();      }       type = Type.GetType(typeName, false, true);       if (type != null)      {          this.m_rwLock.EnterWriteLock();          try         {              this.m_controllerTypes[typeName] = type;          }          finally         {              this.m_rwLock.ExitWriteLock();          }      }       return type;  }

由于我選擇在應(yīng)用程序中使用同一個AreaControllerFactory對象,因此線程安全是一定要有保證的。這里我們用到了讀寫鎖,不過請注意,紅色那句話并不保證對于每個相同的typeName只執(zhí)行一次,也不保證相同的typeName對于m_controllerTypes字典只會進(jìn)行一次寫操作(所以我沒有Add,而是使用了下標(biāo)操作)。不過,由于這些“重復(fù)”不會造成問題,因此就沒有去涉及太多這方面的考慮。

***,便是那CreateControlle方法:

public IController CreateController(RequestContext requestContext, string controllerName)  {      Type controllerType;      object area;      if (requestContext.RouteData.Values.TryGetValue("area", out area))      {          controllerType = this.GetControllerType(area.ToString(), controllerName);      }      else     {          controllerType = this.GetControllerType(null, controllerName);      }       if (controllerType == null)      {          throw new HttpException(404,              String.Format(                  "Controller of path {0} not found.",                  requestContext.HttpContext.Request.Path));      }       try     {          return (IController)Activator.CreateInstance(controllerType);      }      catch (Exception ex)      {          string message = String.Format("Error creating controller {0}" + controllerType);          throw new InvalidOperationException(message, ex);      }  }

似乎沒有什么可談的:我們從RouteData中獲取出area對應(yīng)的值,并且調(diào)用GetControllerType方法獲得Controller的類型,并使用Activator.CreateInstance創(chuàng)建對象。在不合法的情況下,拋出合適的異常即可。

至此,AreaControllerFactory就完成了,很容易,不是嗎?很顯然,這個組件的功能非常有限,例如為什么所有的Controller一定要在同一個命名空間下?沒錯,它其實(shí)只是符合“我要求”的一個東西。但是,在項(xiàng)目中很多東西都是如此,我只實(shí)現(xiàn)我夠用的功能。例如,我可能不會向?qū)ν夤_的API那樣,嚴(yán)格檢查每個問題,拋出嚴(yán)謹(jǐn)?shù)漠惓!N铱赡軆A向于在項(xiàng)目中使用接口,而不是使用抽象類。因?yàn)槭俏业捻?xiàng)目,我可以快速反饋,需要修改的時候就修改吧。

同樣的,如果DefaultControllerFactory真在某些特別情況下有問題,或者支持的有些復(fù)雜。那么不如我們就自己動手吧。一次性投入,而且這樣的小組件也花不了多少時間。

關(guān)于自定義的ControllerFactory接口如何實(shí)現(xiàn)支持Area就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

當(dāng)前文章:自定義的ControllerFactory接口如何實(shí)現(xiàn)支持Area
轉(zhuǎn)載來于:http://chinadenli.net/article2/gshiic.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供靜態(tài)網(wǎng)站網(wǎng)站策劃虛擬主機(jī)網(wǎng)站營銷外貿(mào)建站外貿(mào)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都做網(wǎng)站