您的位置:首页 > 移动开发 > Unity3D

为ASP.NET MVC创建一个基于Unity的ControllerFactory

2011-12-13 16:35 1226 查看
谈到IoC和ASP.NET的集成,很多人会先后想到Ninject,不过我们个人还是倾向于Unity。这篇文章简单地介绍如果创建基于Unity的ControllerFactory。如下面的代码所示,我们通过直接继承DefaultControllerFactory创建一个自定的UnityControllerFactory。构造函数指定的是配置的UnityContainer的名称,如果没有显式指定则采用默认的UnityContainer。在重写的GetControllerInstance方法中,直接调用IUnityContainer的Resolve方法根据Controller类型创建相应的对象。[源代码从这里下载]

[code]      public class UnityControllerFactory: DefaultControllerFactory

     {

         public IUnityContainer Container { get; private set; }

         public UnityControllerFactory(string containerName = "")

         {

             IUnityContainer container = new UnityContainer();

             UnityConfigurationSection configSection = ConfigurationManager.GetSection(UnityConfigurationSection.SectionName) as UnityConfigurationSection;

             if (null == configSection && !string.IsNullOrEmpty(containerName))

             {

                 throw new ConfigurationErrorsException("Cannot find <unity> configuration section");

             }

      

             if (string.IsNullOrEmpty(containerName))

             {

                 configSection.Configure(container);

             }

             else

             {

                 configSection.Configure(container, containerName);

             }

             this.Container = container;

         }

         protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)

         {

             Guard.ArgumentNotNull(controllerType, "controllerType");

             return (IController)this.Container.Resolve(controllerType);

         }

     }

[/code]

为了演示DefaultControllerFactory的作用,我们来创建一个简单的例子。假设我们要创建一个维护联系人的应用,我们通过具有如下定义的Contact类型表示联系人,而IContactRepository接口定义了一个从存储中获取所有联系人的GetAllContacts方法,DefaultContactRepository是对IContactRepository接口的实现。

[code]
     public class Contact

     {

         public string Name { get; set; }

         public string Gender { get; set; }

         public string Address { get; set; }

     }

      

     public interface IContactRepository

     {

         IEnumerable<Contact> GetAllContacts();

     }

      

     public class DefaultContactRepository : IContactRepository

     {

         public IEnumerable<Contact> GetAllContacts()

         {

             yield return new Contact

             {

                 Name = "Zhang San",

                 Gender = "Male",

                 Address = "#328, XingHu Street, Su Zhou, Jiang Su Province, PRC."

             };

      

             yield return new Contact

             {

                 Name = "Li Si",

                 Gender = "Female",

                 Address = "#328, Jin Ji Hu Road, Su Zhou, Jiang Su Province, PRC."

             };

         }

     }

[/code]

我们在Web应用的主页显示联系人列表,为此我创建了如下一个HomeController。在这里我们演示的是构造器注入,所以我们通过构造函数指定的IContactRepository对象来初始化Repository属性。在Action方法Index中调用IContactRepository的GetAllContacts方法为对应的View指定Model。

[code]
     public class HomeController : Controller

     {

         public IContactRepository Repository { get; private set; }

         public HomeController(IContactRepository repository)

         {

             this.Repository = repository;

         }

         public ActionResult Index()

         {

             return View(this.Repository.GetAllContacts());

         }

     }

[/code]

Index.cshtml代码如下所示,这是一个Model类型为IEnumerable<Contact>的View,它将所有的联系人信息列出来。

[code]
     @model IEnumerable<Artech.Web.Mvc.Extensions.Contact>

     @{

         ViewBag.Title = "Index";

     }

      

     <h2>Contact List</h2>

      

     <div>

     <ul>

     @foreach (var contact in this.Model)

     { 

         <li>

             <h3>@contact.Name</h3>

             <p>Gender: @contact.Gender</p>

             <p>Address: @contact.Address</p>

             <hr />

         </li>

     }

     </ul>

     </div>

[/code]

自定义的UnityContainerFactory的注册定义在Gloable.asax中。初次之外,额外需要做的是忽略掉针对favicon.ico的路由,否则程序运行将会失败。

[code]
     public class MvcApplication : System.Web.HttpApplication

     {

         public static void RegisterGlobalFilters(GlobalFilterCollection filters)

         {

             filters.Add(new HandleErrorAttribute());

         }

      

         public static void RegisterRoutes(RouteCollection routes)

         {

             routes.IgnoreRoute("favicon.ico");

             routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

             routes.MapRoute("Default", "{controller}/{action}/{id}",

                 new { controller = "Home", action = "Index", id = UrlParameter.Optional } 

             );

         }

      

         protected void Application_Start()

         {

             AreaRegistration.RegisterAllAreas();

             RegisterGlobalFilters(GlobalFilters.Filters);

             RegisterRoutes(RouteTable.Routes);

      

             ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory());

         }

     }

[/code]

接口IContactRepository和DefualtContactRepository之间的映射关系定义在如下所示的<unity>配置中。

[code]
     <unity>

       <alias alias="IContactRepository" type="Artech.Web.Mvc.Extensions.IContactRepository, UnityIntegration" />

       <alias alias="DefaultContactRepository" type="Artech.Web.Mvc.Extensions.DefaultContactRepository, UnityIntegration" />

       <container>

         <register type="IContactRepository" mapTo="DefaultContactRepository"/>

       </container>

     </unity>

[/code]

通过浏览器访问Web应用的主页,将会得到如下所示的联系人列表。



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: