<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      samesite


      【ASP.Net MVC3 】使用Unity 實現依賴注入

      家人身體不太好,好幾天沒在園子里發帖了。

      新項目還是要用MVC3,team 計劃使用 Unity。看了一下網上的資料,都是比較老的了,官網也沒什么好的指引。MVC也在更新,Unity也在更新。花了1天半時間去MSDN,P&P查資料,整理了一下分享給大家。言歸正傳:


      什么是Unity?

      Unity是一個輕量級的可擴展的依賴注入容器,支持構造函數,屬性和方法調用注入。Unity可以處理那些從事基于組件的軟件工程的開發人員所面對的問題。構建一個成功應用程序的關鍵是實現非常松散的耦合設計。松散耦合的應用程序更靈活,更易于維護。這樣的程序也更容易在開發期間進行測試。你可以模擬對象,具有較強的具體依賴關系的墊片(輕量級模擬實現),如數據庫連接,網絡連接,ERP連接,和豐富的用戶界面組件。例如,處理客戶信息的對象可能依賴于其他對象訪問的數據存儲,驗證信息,并檢查該用戶是否被授權執行更新。依賴注入技術,可確保客戶類正確實例化和填充所有這些對象,尤其是在依賴可能是抽象的 。

       

      如何得到Unity?

      您可以訪問http://unity.codeplex.com/releases得到最新版本的Unity現在。當然,如果您在您的visual studio 中安裝了Nuget 包管理器,你可以直接在Nuget中獲取到最新版本的Unity。

       

      API

       

      UnityContainer.RegisterType<ITFrom,TTO>();

      UnityContainer.RegisterType< ITFrom, TTO >();

      UnityContainer.RegisterType< ITFrom, TTO >("keyName");

      IEnumerable<T> databases = UnityContainer.ResolveAll<T>();

      IT instance = UnityContainer.Resolve<IT>();

      T instance = UnityContainer.Resolve<T>("keyName");

      UnitContainer.RegisterInstance<T>("keyName",new T());

      UnityContainer.BuildUp(existingInstance);

      IUnityContainer childContainer1 = parentContainer.CreateChildContainer();

       

       

      代碼舉例

      在開始之前我們要先做一些準備工作。首先創建一個控制臺應用程序。使用Nuget 添加Unity到當前項目中。我們可以發現,dll引用中多了3個dll:Microsoft.Practices.ServiceLocation, Microsoft.Practices.Unity和Microsoft.Practices.Configuation。

      示例1:根據接口依賴創建類

       

      上邊簡單介紹了Unity的API。如果在沒有注冊的情況下Resolve一個類型會發生什么呢?

      假設我們需要對日志進行處理。我們先聲明一個接口ILogger:

       

        public interface ILogger
      {
      void Write(string log);

      }

       

      我們可以有多種方法實現這個接口,我們假設希望寫日志到文件中:

        public class FileLogger:ILogger
      {

      #region ILogger Members

      public void Write(string log)
      {
      Console.WriteLine("Write log in file.");
      }

      #endregion
      }

      我們在實際生活中對數據庫的選擇也是多種多樣的。我們創建一個數據庫的基類:

      public class Database
      {
      }

      創建一個派生類:

      public class CustomerDatabase : Database
      {
      private ILogger _logger;
      public CustomerDatabase(ILogger logger)
      {
      _logger = logger;
      }
      }

      注意它的構造器的參數是ILogger類型。首先我們要創建一個Unity 容器:

      UnityContainer container = new UnityContainer();

      接下來我們需要在容器中注冊一種類型,它是一個類型的映射,接口類型是ILogger,我希望返回的類型是FileLogger:

      container.RegisterType<ILogger, FileLogger>();

      然后我們使用Resolve 方法:

      Database database = container.Resolve<CustomerDatabase>();

      經過調試我們可以發現,如果在容器中沒有注冊的類型。執行Resolv方法后,Unity嘗試創建該類型,會執行該類的構造器。最后database變量的類型就是CustomerDatabase,而且它的私有字段ILogger的當前實例也為FileLogger。

      示例2:類型映射

       

      我們希望返回一個日志類的實例,無論它是哪個實現類。我們可以直接在Resolve的類型中指定類型為接口ILogger:

      UnityContainer container = new UnityContainer();
      container.RegisterType<ILogger, FileLogger>();
      ILogger logger = container.Resolve<ILogger>();

      每一次 container都會給我們返回一個新的logger實例。

      示例3:單例模式的注冊

      如果我們想告訴Unity,我們想控制生命周期,我們想用單例模式。RegisterType方法包含一個重載,將使用LifetimeManager。每次我們在想獲得到database實例時,unity總是會返回第一次我創建的CustomerDatabase。

      UnityContainer container = new UnityContainer();
      container.RegisterType<Database, CustomerDatabase>
      (new ContainerControlledLifetimeManager());

      示例4:注冊時附帶key

      在我們向容器里注冊時,可以附帶一個string 類型的Key值。

      UnityContainer container = new UnityContainer();
      container.RegisterType<Database, SQLDatabase>("SQL");
      container.RegisterType<Database, ORACLEDatabase>("ORACLE");
      IEnumerable<Database> databases = container.ResolveAll<Database>();
      Database database = container.Resolve<Database>("SQL");

      我們分別向容器中注冊了名為“SQL“和”ORACLE“的Database。當我們使用ResolverAll方法是。容器會返回容器中所有類型為Database的類。

      這時我們如果僅僅想回去SQL的實例,我們可以使用container.Resolve<Database>("SQL");

      示例5:注冊已經存在的實例

       

      通過下邊方式我們可以在container中注冊一個實例:

        UnityContainer container = new UnityContainer();
      container.RegisterInstance<Database>(new SQLDatabase());
      container.RegisterInstance<Database>("Oracle", new ORACLEDatabase());
      Database database = container.Resolve<Database>();
      Database oracleDatabase = container.Resolve<Database>("Oracle");

      看起來和上邊的方式沒什么不同。重要的是,當我們使用RegisterInstance方法時,Unity會注冊一個單例。

      我們還有一種方法可以把已經存在的實例注入到容器中。

                   UnityContainer container = new UnityContainer();
      container.RegisterType<ILogger, FileLogger>();
      SQLDatabase existDatabase = new SQLDatabase();
      container.BuildUp(existDatabase);
      container.RegisterInstance<Database>(existDatabase);
      Database database = container.Resolve<Database>();

      就如上邊代碼中,我們已經存在一個database 是DB2Database。你希望Unity做的是把依賴注入到容器中。

      我們用BuildUp方法告訴Unity我們的想法。這時候Unity回去DB2Database 類,如果他發現了[Dependency]這個特性。他就自動的把我們前邊注冊的FileLogger注入到DB2Database的Logger字段中。

      以下是DB2Database類:

      public class DB2Database:Database
      {
      [Dependency]
      public ILogger Logger { get; set; }
      }

      使用配置文件來實現關系映射

       

      我們也可以再web.config里配置 文件的依賴關系映射。首先我打開web.config文件。按照如下結構添加section。這里我只是簡單的映射了ILogger 接口和FileLogger。并且指定了生命周期是單例。

      <configuration>
      <configSections>
      <section name="unity"
      type
      ="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
      Microsoft.Practices.Unity.Configuration"
      />
      </configSections>
      <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
      <container name="containerOne">
      <types>
      <type type="UnityDemo_ConsoleApplication.ILogger" mapTo="UnityDemo_ConsoleApplication.FileLogger"
      lifeTime
      ="Singleton"/>
      </types>

      </container>

      </unity>
      ...
      ...
      </configuration>

      如果你想更詳細的了解元素和屬性的使用,可以看以下Unity xml中配置的結構圖:



      更詳細了解,請參見:

      http://msdn.microsoft.com/en-us/library/ff647848.aspx

      http://msdn.microsoft.com/zh-cn/library/dd203230.aspx

       

      如何讀取配置 并加載

      Unity同樣支持我們在配置文件里寫設定映射關系。

      首先我們要引入命名空間: Microsoft.Practices.Unity.Configuration;

       

      在Unity2.0以上版本,已經廢棄了以前的方法。現在我們有2種方式可以讀取配置。

      第一種,我們使用configurationManager:

      引用命名空間:System.Configuration

                  IUnityContainer myContainer = new UnityContainer();

      myContainer.LoadConfiguration("containerOne ");
      UnityConfigurationSection section
      = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
      section.Configure(myContainer, "containerOne");

      第二種,我們可以直接用容器讀取配置信息:

      IUnityContainer myContainer = new UnityContainer();
      myContainer.LoadConfiguration("containerName");

       

      通過 Injection API 指定依賴

       

      假設我們有一個類GenericDatabase:



       

      public class GenericDatabase:Database
      {
      private string _connectionString;
      public ILogger Logger { get; set; }

      public GenericDatabase(string connectionString)
      {
      _connectionString = connectionString;
      }
      }

      在這里我們要通過Injection API 來為這個類注入connectionString 和 Logger。

      首先我們還和前邊的一樣注冊映射關系:

       

                  IUnityContainer container = new UnityContainer();
      container.RegisterType<ILogger, FileLogger>();
      container.RegisterType<Database, GenericDatabase>();

       

      然后通過Injection API 為GenericDatabase注入ConnectionStrings和Logger:

      container.Configure<InjectedMembers>()
      .ConfigureInjectionFor<GenericDatabase>(
      new InjectionConstructor(
      ConfigurationManager.ConnectionStrings["ConnectionStrings"] == null
      ? "defaultConnectionString" : ConfigurationManager.ConnectionStrings["ConnectionStrings"].ConnectionString),
      new InjectionProperty("Logger")
      );
      Database database = container.Resolve<Database>();

      這樣我們最后獲得的database 就包含了connection 和 Logger。

      嵌套式容器

      容器是可以嵌套的,獲取實例時遵循的規則是,如果子容器里不包含需要的對象,則會去父容器獲取。如果有,則從自己里獲取。

      一旦父容器銷毀,子容器也隨之銷毀。

      UnityContainer parentContainer = new UnityContainer();
      IUnityContainer childContainer1 = parentContainer.CreateChildContainer();
      IUnityContainer childContainer2 = parentContainer.CreateChildContainer();
      parentContainer.RegisterType<ILogger, FileLogger>(new ContainerControlledLifetimeManager());
      childContainer1.RegisterType<ILogger, EventLogger>(new ContainerControlledLifetimeManager());
      //應該從parentContainer得到FileLogger
      ILogger logger = childContainer2.Resolve<ILogger>();
      logger.Write("Test");
      //應該從自己本身得到eventLogger

      ILogger logger2 = childContainer1.Resolve<ILogger>();

       

      在MVC 中使用Unity注入Controller

       

      在MVC2中我們會寫一個controlleFactory 繼承自DefaultControllerFactory。

      并且override GetControllerInstance()這個方法。

      MVC3對于依賴注入提供更好的支持。我們可以使用- IDependencyResolver 和 IControllerActivator 來實現對controller的注入。

      具體實現如下:

      創建一個MVC3項目。

      我們要實現MVC3中新提供 的兩個接口:IDependencyResolver和IControllerActivator

      IDependencyResolver公開兩個方法 - GetService的GetServices.The GetService方法解決了單獨注冊的服務,支持任意對象的創建,GetServices解決注冊多個服務。IDependencyResolver接口的實現應該委托給底層的依賴注入容器提供注冊服務請求的類型。當有沒有注冊的服務請求的類型,ASP.NET MVC框架預計這個接口的實現返回GetService為空,并從GetServices返回空集合。讓我們以統一提供依賴注入工作IDependencyResolver intreface派生創建一個自定義的依賴解析器類。

      我們定義一個類名為UnityDependencyResolver:

        public class UnityDependencyResolver : IDependencyResolver
      {
      IUnityContainer container;
      public UnityDependencyResolver(IUnityContainer container)
      {
      this.container = container;
      }

      public object GetService(Type serviceType)
      {
      try
      {
      return container.Resolve(serviceType);
      }
      catch
      {
      return null;
      }
      }

      public IEnumerable<object> GetServices(Type serviceType)
      {
      try
      {
      return container.ResolveAll(serviceType);
      }
      catch
      {
      return new List<object>();
      }
      }
      }

      實現兩個方法GetService和GetServices。使用Unity容器返回我們需要的Service或者ojbect。

      實現兩個方法GetService和GetServices。使用Unity容器返回我們需要的Service或者ojbect。

       

      ASP.NET MVC 3已經推出了一個新的接口IControllerActivator,讓您激活與自定義的行為控制器,并且可以使用依賴注入.讓我們創建一個派生自IControllerActivator 接口的一個自定義的控制器

      IController IControllerActivator.Create( System.Web.Routing.RequestContext requestContext,
      Type controllerType)
      {
      return DependencyResolver.Current
      .GetService(controllerType) as IController;
      }

      DependencyResolver.Current.GetService會執行我們自己定義的UnityDependencyResolver中的方法。

       

      定義好這兩個類,我們找到Global.asax.cs,并在其中中添加一個私有方法GetUnityContainer():

              private IUnityContainer GetUnityContainer()
      {
      //Create UnityContainer
      IUnityContainer container = new UnityContainer()
      .RegisterType<IControllerActivator, CustomControllerActivator>()
      .RegisterType<ILogger, FlatFileLogger>();
      return container;
      }

      這個方法定義了一個新的容器。并且注冊了映射關系。我們要返回的container中包含:CustomControllerActivator和FlatFileLogger。

      IUnityContainer container = GetUnityContainer();

      DependencyResolver.SetResolver(new UnityDependencyResolver(container));

      上邊的都做好了。我們在Application_Start方法中添加如下代碼:

       

      protected void Application_Start()
      {
      ...
      IUnityContainer container = GetUnityContainer();
      DependencyResolver.SetResolver(new UnityDependencyResolver(container));
      }

       

      首先我們通過GetUnityContainer方法獲得container,并且設置當前的Resolver是我們自己實現的UnityDependencyResolver。

      在Controller中我們只需要添加一個[Dependency]特性,就可以很方便的獲取到我們注入的Logger。

       

        public class HomeController : Controller
      {
      [Dependency]
      public ILogger Logger { get; set; }

      public ActionResult Index()
      {

      ViewBag.Message = "Welcome to ASP.NET MVC!";

      Logger.GetType();

      return View();
      }

      public ActionResult About()
      {
      return View();
      }
      }

       

      我們可以使用Logger.GetType()查看到,我們當前的Logger就是我們之前注冊的FlatFileLogger。

       

      參考資料

       

      http://unity.codeplex.com/      

      http://www.rzrgm.cn/Terrylee/archive/2008/02/21/unity-application-block-part1.html         

      http://msdn.microsoft.com/zh-cn/library/ff663144.aspx    

      http://www.martinfowler.com/articles/injection.html        

      http://weblogs.asp.net/shijuvarghese/archive/2011/01/21/dependency-injection-in-asp-net-mvc-3-using-dependencyresolver-and-controlleractivator.aspx     

      http://www.pnpguidance.net/Screencast/UnityDependencyInjectionIoCScreencast.aspx               

      http://weblogs.asp.net/shijuvarghese/archive/2011/01/21/dependency-injection-in-asp-net-mvc-3-using-dependencyresolver-and-controlleractivator.aspx                 

      http://msdn.microsoft.com/en-us/library/ff660878(v=pandp.20).aspx          

      http://msdn.microsoft.com/zh-cn/library/dd203182.aspx

       

      示例代碼下載

       





      posted @ 2012-01-06 08:54  技術弟弟  閱讀(31694)  評論(49)    收藏  舉報
      主站蜘蛛池模板: 久久―日本道色综合久久| 无码成人精品区在线观看| 男女18禁啪啪无遮挡激烈网站| 一区二区三区激情都市| 久热这里只有精品视频六| 国产一区二三区日韩精品| 亚洲人成网站免费播放| 伊人精品成人久久综合| 日韩伦理片| 国产精品入口麻豆| 亚洲精品无码成人A片九色播放| 国产综合久久久久鬼色| 部精品久久久久久久久| 成人片在线看无码不卡| 老色鬼在线精品视频在线观看 | 报价| 亚洲人成电影网站 久久影视| 成人性无码专区免费视频| 亚洲av成人网在线观看| 国产小受被做到哭咬床单GV| 精品av无码国产一区二区| 亚洲综合一区二区三区| 黑人玩弄人妻中文在线| 国产精成人品日日拍夜夜 | 亚洲深深色噜噜狠狠网站| 美女自卫慰黄网站| 国产精品视频中文字幕| 99国产欧美另类久久久精品| 国产成人a在线观看视频免费| 日区中文字幕一区二区| 国产精品一二三中文字幕| 中文字幕亚洲制服在线看| 无码中文字幕av免费放| 人妻少妇偷人一区二区| 亚洲日韩中文字幕在线播放| 国产成人亚洲欧美二区综合| 一二三三免费观看视频| 日本精品不卡一二三区| 丁香五月亚洲综合在线| 成人亚洲一级午夜激情网| 无码国内精品久久人妻蜜桃|