65.9K
CodeProject 正在变化。 阅读更多。
Home

MVC 3 中的依赖注入变得更容易

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.33/5 (5投票s)

2010年10月18日

CPOL

2分钟阅读

viewsIcon

36387

MVC 3 中的依赖注入变得更容易

过去,我写过一篇文章,展示了如何在 ASP.NET MVC Framework 中使用 Unity 实现 依赖注入。这篇文章重新回顾了那篇文章,并展示了如何在 MVC 3 中轻松完成同样的事情。请注意,提供的代码基于 MVC 3 beta 版本,未来可能会发生变化。

IDependencyResolver 和 DependencyResolver

MVC 3 引入了一个新的 接口IDependencyResolver。这个 接口 通过提供两种方法来实现服务定位

  • GetService(Type serviceType) – 此方法获取服务类型并返回一个对象,如果解析器成功解析了该类型。如果解析器无法解析该类型,则必须返回 null 以激活默认 MVC 行为。
  • GetServices(Type serviceType) – 此方法获取服务类型并返回所有已解析对象的 IEnumerable<object>。如果解析器无法解析该类型,则必须返回一个空集合以激活默认 MVC 行为。

DependencyResolver 是一个 静态 类,你可以使用它来注册你自定义的 IDependencyResolver。在实现 IDependencyResolver 后,你可以在 DependencyResolver 中使用其中一个 SetResolver 重载方法来设置它。然后你将能够使用 Current 属性来获取当前的 DependencyResolver ,以便解析类型。如果你不喜欢使用 DependencyResolver 的功能,则无需实现任何内容。MVC 实现内部构建了默认的解析行为。

构建和使用 UnityDependencyResolver

这是一个简单的 UnityDependencyResolver 实现

public class UnityDependencyResolver : IDependencyResolver
{
    #region Members
   
    private IUnityContainer _container;    
   
    #endregion
   
    #region Ctor
   
    public UnityDependencyResolver(IUnityContainer container)
   {
      _container = container;
   }
    
   #endregion
    
   #region IDependencyResolver Members
    
   public object GetService(Type serviceType)
    {
     try
      {
       return _container.Resolve(serviceType);
      }
     catch (Exception ex)
      {
       return null;
      }
   }
    
   public IEnumerable<object> GetServices(Type serviceType)
    {
     try
      {
       return _container.ResolveAll(serviceType);
      }
     catch (Exception ex)
      {
       return new List<object>();
      }
   }
    
   #endregion
}

为了使用这个解析器,将容器构建在适当的位置是 Global.asax 文件。以下是实现

public class MvcApplication : System.Web.HttpApplication
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
   {
      filters.Add(new HandleErrorAttribute());
   }
    
   public static void RegisterRoutes(RouteCollection routes)
    {
     routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
     routes.MapRoute(
          "Default", // Route name
         "{controller}/{action}/{id}", // URL with parameters
          new { controller = "Home", 
          action = "Index", id = UrlParameter.Optional } // Parameter defaults
     );    
   }
    
   protected void Application_Start()
    {
     AreaRegistration.RegisterAllAreas();
      
     RegisterGlobalFilters(GlobalFilters.Filters);
      RegisterRoutes(RouteTable.Routes);
     
      var container = InitContainer();
     DependencyResolver.SetResolver(new UnityDependencyResolver(container));       
    }
   
    private static IUnityContainer InitContainer()    
   {                   
      var container = new UnityContainer();        
   
      // Register the relevant types for the         
     // container here through classes or configuration                      
      container.RegisterType<IMessageService, MessageService>();
     return container;
    }
}

如你所见,我添加了容器的初始化,并将 DependencyResolver 设置为 Unity 实现。Message 服务和控制器与我在之前的文章中展示的类相同

public interface IMessageService 
{ 
  string GetMessage();
}
 
public class MessageService : IMessageService
{
 #region IMessageService Members
 
 public string GetMessage()
  {
   return "Hello Controller!";
  }
 
  #endregion
}

public class HomeController : Controller
{
  #region Members     
 
  [Dependency]    
 public IMessageService MessageService { get; set; }
           
 #endregion
 
 #region Actions    
 
 public ActionResult Index()
  {
   ViewModel.Message = MessageService.GetMessage();
 
   return View();
  }
 
  public ActionResult About()
 {
    return View();
 }
 
 #endregion
}

运行此示例后,我们将获得以下预期结果

HomeController Result

摘要

总结一下,在 MVC 3 beta 版本中,通过实现 IDependencyResolver 接口并在 DependencyResolver 静态 类中注册它,可以使用 DIIoC 容器的新方法。还有其他注入点可以使用,例如 IControllerActivator ,我将在后续文章中介绍。

© . All rights reserved.