如何将 MEF 与 ASP.NET MVC 4 和 ASP.NET Web API 集成
如何将 Managed Extensibility Framework (MEF) 与 ASP.NET MVC 4 和 ASP.NET Web API 集成到同一项目中?
How does one integrate Managed Extensibility Framework (MEF) with ASP.NET MVC 4 and ASP.NET Web API in the same project?
考虑一个示例应用程序,它有一个 MVC 控制器 HomeController
和一个 Web API 控制器 ContactController
.两者都有一个 IContactRepository
类型的属性,它们依赖 MEF 来解析.问题是如何将MEF插入MVC和Web API,从而通过MEF创建实例.
Consider an example application, with an MVC controller HomeController
and a Web API controller ContactController
. Both have a property of type IContactRepository
, which they rely on MEF to resolve. The problem is how to plug MEF into MVC and Web API, so that instances are created via MEF.
家庭控制器:
/// <summary>
/// Home controller. Instruct MEF to create one instance of this class per importer,
/// since this is what MVC expects.
/// </summary>
[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class HomeController : Controller
{
[Import]
private IContactRepository _contactRepository = null;
public ActionResult Index()
{
return View(_contactRepository.GetAllContacts());
}
}
ContactController:
/// <summary>
/// Contact API controller. Instruct MEF to create one instance of this class per importer,
/// since this is what Web API expects.
/// </summary>
[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class ContactController : ApiController
{
[Import]
private IContactRepository _contactRepo = null;
public Contact[] Get()
{
return _contactRepo.GetAllContacts();
}
}
IContactRepository 和 ContactRepository:
public interface IContactRepository
{
Contact[] GetAllContacts();
}
[Export(typeof(IContactRepository))]
public class ContactRepository : IContactRepository
{
public Contact[] GetAllContacts()
{
return new Contact[] {
new Contact { Id = 1, Name = "Glenn Beck"},
new Contact { Id = 2, Name = "Bill O'Riley"}
};
}
}
联系方式:
public class Contact
{
public int Id { get; set; }
public string Name { get; set; }
}
解决方案是实现 System.Web.Mvc.IDependencyResolver 和 System.Web.Http.Dependencies.IDependencyResolver 并在您的 Application_Start
方法.
The solution is to implement System.Web.Mvc.IDependencyResolver and System.Web.Http.Dependencies.IDependencyResolver and register your implementation with ASP.NET MVC and ASP.NET Web API respectively, in your Application_Start
method.
在这个例子中,我们将创建一个 MefConfig
类,它实现了一个方法 RegisterMef
,该方法从 Application_Start
调用以安装我们的依赖解析器.类 MefDependencyResolver
实现了 System.Web.Mvc.IDependencyResolver
和 System.Web.Http.Dependencies.IDependencyResolver
并因此处理依赖MVC 和 Web API 的解析职责.
In this example we'll create a class MefConfig
, which implements a method RegisterMef
that gets called from Application_Start
in order to install our dependency resolver. The class MefDependencyResolver
implements both System.Web.Mvc.IDependencyResolver
and System.Web.Http.Dependencies.IDependencyResolver
and, as such, handles dependency resolution duties for both MVC and Web API.
Application_Start,将其放入您的 Global.asax.cs:
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
[...]
MefConfig.RegisterMef();
}
}
MefDependencyResolver 和 MefConfig:
/// <summary>
/// Resolve dependencies for MVC / Web API using MEF.
/// </summary>
public class MefDependencyResolver : System.Web.Http.Dependencies.IDependencyResolver, System.Web.Mvc.IDependencyResolver
{
private readonly CompositionContainer _container;
public MefDependencyResolver(CompositionContainer container)
{
_container = container;
}
public IDependencyScope BeginScope()
{
return this;
}
/// <summary>
/// Called to request a service implementation.
///
/// Here we call upon MEF to instantiate implementations of dependencies.
/// </summary>
/// <param name="serviceType">Type of service requested.</param>
/// <returns>Service implementation or null.</returns>
public object GetService(Type serviceType)
{
if (serviceType == null)
throw new ArgumentNullException("serviceType");
var name = AttributedModelServices.GetContractName(serviceType);
var export = _container.GetExportedValueOrDefault<object>(name);
return export;
}
/// <summary>
/// Called to request service implementations.
///
/// Here we call upon MEF to instantiate implementations of dependencies.
/// </summary>
/// <param name="serviceType">Type of service requested.</param>
/// <returns>Service implementations.</returns>
public IEnumerable<object> GetServices(Type serviceType)
{
if (serviceType == null)
throw new ArgumentNullException("serviceType");
var exports = _container.GetExportedValues<object>(AttributedModelServices.GetContractName(serviceType));
return exports;
}
public void Dispose()
{
}
}
public static class MefConfig
{
public static void RegisterMef()
{
var asmCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
var container = new CompositionContainer(asmCatalog);
var resolver = new MefDependencyResolver(container);
// Install MEF dependency resolver for MVC
DependencyResolver.SetResolver(resolver);
// Install MEF dependency resolver for Web API
System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = resolver;
}
}