如何将MEF与ASP.NET MVC 4和ASP.NET Web API集成

在同一个项目中,如何将Managed Extensibility Framework(MEF)与ASP.NET MVC 4和ASP.NET Web API集成?

考虑一个示例应用程序,带有一个MVC控制器HomeController和一个Web API控制器ContactController 。 两者都有一个IContactRepository类型的属性,它们依赖于MEF来解决。 问题是如何将MEF插入MVC和Web API,以便通过MEF创建实例。

HomeController的:

/// <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方法中向ASP.NET MVC和ASP.NET Web API注册您的实现。

在这个例子中,我们将创建一个MefConfig类,它实现了一个从Application_Start调用的方法RegisterMef ,以安装我们的依赖解析器。 MefDependencyResolver类实现了System.Web.Mvc.IDependencyResolverSystem.Web.Http.Dependencies.IDependencyResolver并且同样处理了MVC和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;
    }
}

你可以看看这个http://kennytordeur.blogspot.be/2012/08/mef-in-aspnet-mvc-4-and-webapi.html。 它解释了如何在Asp.net MVC 4 / Web Api项目中使用MEF。 还有一个基于这个代码的Nuget包。 这样你就可以非常方便快速地进行测试。


@ aknuds1答案是迄今为止我看到的将MEF集成到DependencyResolver中最好的答案。 我能够很容易地将它扩展到MEF2中使用基于约定的组合。 MefConfig类是所有需要改变,然后不是太多。

/// <summary>
///     Responsible for configuring MEF for the application.
/// </summary>
public static class MefConfig
{
    /// <summary>
    ///     Registers MEF conventions and exports.
    /// </summary>
    public static void RegisterMef()
    {
        // Register MVC/API conventions
        var registrationBuilder = new RegistrationBuilder();
        registrationBuilder.ForTypesDerivedFrom<Controller>().SetCreationPolicy(CreationPolicy.NonShared).Export();
        registrationBuilder.ForTypesDerivedFrom<ApiController>().SetCreationPolicy(CreationPolicy.NonShared).Export();
        var assemblyCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly(), registrationBuilder);
        var aggregateCatalog = new AggregateCatalog(assemblyCatalog);
        var container = new CompositionContainer(aggregateCatalog);
        var resolver = new MefDependencyResolver(container);
        // Install MEF dependency resolver for MVC
        DependencyResolver.SetResolver(resolver);
        // Install MEF dependency resolver for Web API
        GlobalConfiguration.Configuration.DependencyResolver = resolver;
    }
}
链接地址: http://www.djcxy.com/p/20385.html

上一篇: How to integrate MEF with ASP.NET MVC 4 and ASP.NET Web API

下一篇: ASP.NET MVC 4, Web API