IOC 容器在 ASP.NET MVC 中的應用


     IOC:Inversion Of Control 翻譯為控制反轉,我們在面向對象軟件開發過程中,一個應用程序它的底層結構可能由N種不同的構件來相互協作來完成我們定義的系統的業務邏輯。哪么每一個構件可能相互獨立和相互依賴,如果相互依賴的構件中的某一個構件出現異常,就會影響到整個系統的穩定運行,對象之間的耦合關系是無法避免的,也是必要的,因為這是協同工作的基礎。如何降低系統之間、模塊之間和對象之間的耦合度,是軟件工程永遠追求的目標之一。為了解決對象之間的耦合度過高的問題,IOC 的理念被提出,並被成功地應用到實踐當中。說直白一點,就是對象之間的創建與維護我們全權交給了外部容器來管理,這樣就實現了所謂的反轉。

    .NET 體系下這些相對成熟輕量級的IOC 容器,Castle Windsor、Unity、Spring.NET、StructureMap和Ninject等,下面我們就開始演示IOC在ASP.NET MVC 下的應用,在這里我們選擇 Castle 來做為 IOC 容器。ASP.NET MVC 的 Controller 激活是靠ControllerFactory來創建的Controller對象的,所以我們就直接創建一個WindsorControllerFactory類,通過繼承自DefaultControllerFactory來實現Controller的實例創建解析和釋放等功能。 

 1 using Castle.Core.Resource;
 2 using Castle.Windsor;
 3 using Castle.Windsor.Configuration.Interpreters;
 4 using System;
 5 using System.Linq;
 6 using System.Reflection;
 7 using System.Web.Mvc;
 8 
 9 namespace mvc_with_Castle.App_Start
10 {
11     public class WindsorControllerFactory : DefaultControllerFactory
12     {
13         private WindsorContainer container;
14         public WindsorControllerFactory()
15         {
16             container = new WindsorContainer(
17                         new XmlInterpreter(new ConfigResource("castle"))
18                     );
19 
20             var controllerTypes = from t in Assembly.GetExecutingAssembly().GetTypes()
21                                   where typeof(IController).IsAssignableFrom(t)
22                                   select t;
23             foreach (Type t in controllerTypes)
24                 container.AddComponentLifeStyle(t.FullName, t, Castle.Core.LifestyleType.Transient);
25         }
26 
27         protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
28         {
29             return (IController)container.Resolve(controllerType);
30         }
31     }
32 }

     一個自定義的WindsorControllerFactory就這么簡單的創建完了,下一步創建一個基於 IWindsorInstaller 的對容器的安裝類

using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
using System.Web.Mvc;

namespace mvc_with_Castle.App_Start
{
    public class ControllersInstaller : IWindsorInstaller
    {
        public void Install(Castle.Windsor.IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(Classes.FromThisAssembly()
                                .BasedOn<IController>()
                                .LifestyleTransient().Configure(c => c.DependsOn()));
        }
    }
}

    接下來我們對Global.asax做一些修改,注冊我們默認的 WindsorControllerFactory 控制器工廠類。

 1 using Castle.Windsor;
 2 using Castle.Windsor.Installer;
 3 using mvc_with_Castle.App_Start;
 4 using System.Web.Mvc;
 5 using System.Web.Optimization;
 6 using System.Web.Routing;
 7 
 8 namespace mvc_with_Castle
 9 {
10     public class MvcApplication : System.Web.HttpApplication
11     {
12         private static IWindsorContainer container;
13         private static void MyContainer()
14         {
15             container = new WindsorContainer().Install(FromAssembly.This());
16 
17             var controllerFactory = new WindsorControllerFactory();
18             ControllerBuilder.Current.SetControllerFactory(controllerFactory);
19         }
20         protected void Application_Start()
21         {
22             AreaRegistration.RegisterAllAreas();
23             FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
24             RouteConfig.RegisterRoutes(RouteTable.Routes);
25             BundleConfig.RegisterBundles(BundleTable.Bundles);
26 
27             MyContainer();
28         }
29 
30         protected void Application_End()
31         {
32             container.Dispose();
33         }
34     }
35 }

       所有的准備工作差不多都准備完畢,接下來我們就來定義一個接口實現對人員的查詢

 1 using System.Collections.Generic;
 2 
 3 namespace mvc_with_Castle.Service
 4 {
 5     public class SysUser
 6     {
 7         public string Name { get; set; }
 8 
 9         public string Sex { get; set; }
10 
11         public string Phone { set; get; }
12 
13         public string Address { get; set; }
14 
15         public string Email { get; set; }
16     }
17 
18     public interface IUsersSvr
19     {
20         IEnumerable<SysUser> QueryUsers();
21     }
22 
23     public class UsersSvr : IUsersSvr
24     {
25         private static IList<SysUser> list;
26 
27         static UsersSvr()
28         {
29             list = new List<SysUser>();
30             for (int i = 0; i < 10; i++)
31             {
32                 list.Add(new SysUser()
33                 {
34                     Name = "如花" + i,
35                     Sex = "",
36                     Phone = "13882880818",
37                     Address = "皇后大道中段" + i + "",
38                     Email = "jack@gmail.com"
39                 });
40             }
41         }
42 
43         public IEnumerable<SysUser> QueryUsers()
44         {
45             return list;
46         }
47     }
48 }

   再下來就是我們對Castle IOC的配置管理   

 1  <configSections>
 2     <section name="castle" type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor"/>
 3   </configSections>
 4 
 5 <!--注冊服務-->
 6   <castle>
 7     <components>
 8       <component id="UsersSvr" type="mvc_with_Castle.Service.UsersSvr, mvc_with_Castle" service="mvc_with_Castle.Service.IUsersSvr, mvc_with_Castle" lifestyle="Singleton"/>
 9     </components>
10   </castle>

   最后調用我們定義的 IUserSvr 接口來實現查詢數據

 1 using System.Collections.Generic;
 2 using System.Web.Mvc;
 3 using mvc_with_Castle.Service;
 4 
 5 namespace mvc_with_Castle.Controllers
 6 {
 7     public class HomeController : Controller
 8     {
 9         public IUsersSvr _svr { get; set; }
10         public ActionResult Index()
11         {
12             IEnumerable<SysUser> list = _svr.QueryUsers();  
13             return View(list);
14         }
15     }
16 }

    人員信息顯示效果如下 

    在這里我們已經大概了解了什么是IOC容器,和在 ASP.NET MVC 下面我們怎樣利用 IOC 容器來實現通過接口的方式來進行服務的調用的大致原理,在上面的HomeController里面,很明顯我們不用擔心接口怎么被實例化的,或者說我們沒明白服務到底怎么被激活了,哪么再回頭看看前面的代碼是不是就一目了然了呢 ?

    


免責聲明!

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



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