MVC 3 中的依赖注入变得更容易
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
}
运行此示例后,我们将获得以下预期结果
摘要
总结一下,在 MVC 3
beta 版本中,通过实现 IDependencyResolver
接口
并在 DependencyResolver
静态
类中注册它,可以使用 DI
和 IoC
容器的新方法。还有其他注入点可以使用,例如 IControllerActivator
,我将在后续文章中介绍。