ASP.NET MVC 4.0控制器和MEF,如何将这两者结合在一起?

时间:2013-07-10 19:23:04

标签: c# asp.net-mvc mef

我正在尝试使用MEF创建ASP.NET MVC模块。虽然到目前为止我没有使用没有MVC的MEF没有问题,但是当涉及到导出控制器时我遇到了一些困难。

我使用此方法作为示例http://kennytordeur.blogspot.de/2012/08/mef-in-aspnet-mvc-4-and-webapi.html 我通过引入一个包含控制器的外部DLL使其变得更加复杂。但是如果我遵循Kenny的想法,那么我需要有一个通用的接口(比如他的例子中的IMyTest),但是,因为我打算拥有一些控制器,这意味着我需要太多的接口。最后,看起来我重用了控制器的内部方法,而不是整个控制器。

我在这里找到了一个问题How to integrate MEF with ASP.NET MVC 4 and ASP.NET Web API,其中包含一些代码示例,其中我看到了相似的图片 - 导入了接口IContactRepository的_contactRepository,然后在视图中重用。

这就是为什么我的问题是,导出整个控制器而不使用接口是否正常?怎么做?

我发现MEF和ASP.NET之间的联系相当令人困惑,起初它认为互联网上有很多例子,但是当我看得更深,它们中的大部分已经过时而且不实用或者太原始而无法看到它如何应用于更大的项目。

谢谢!

1 个答案:

答案 0 :(得分:6)

我在MVC 4中使用了MefContrib和MEF,并使用以下内容连接所有内容。您需要从Global.asax中的Application_Start调用Configure方法,以便在MVC需要处理请求时一切就绪。

using System.ComponentModel.Composition.Hosting;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MefContrib.Hosting.Conventions;
using MefContrib.Web.Mvc;

[assembly: PreApplicationStartMethod( typeof(Core.Web.Initialization.DependencyInjection.RegisterDependencyResolver), "RegisterHttpModule" )]

namespace Core.Web.Initialization.DependencyInjection
{
    public class RegisterDependencyResolver
    {
        public static void RegisterHttpModule()
        {
            // Register the CompositionContainerLifetimeHttpModule HttpModule.
            // This makes sure everything is cleaned up correctly after each request.
            CompositionContainerLifetimeHttpModule.Register();      
        }

        public void Configure()
        {
            // Create MEF catalog based on the contents of ~/bin.
            //
            // Note that any class in the referenced assemblies implementing in "IController"
            // is automatically exported to MEF. There is no need for explicit [Export] attributes
            // on ASP.NET MVC controllers. When implementing multiple constructors ensure that
            // there is one constructor marked with the [ImportingConstructor] attribute.
            var catalog = new AggregateCatalog(
                new DirectoryCatalog( "bin" ),
                new ConventionCatalog( new MvcApplicationRegistry() ) );

            // Tell MVC3 to use MEF as its dependency resolver.
            var dependencyResolver = new CompositionDependencyResolver( catalog );
            DependencyResolver.SetResolver( dependencyResolver );

            // Tell MVC3 to resolve dependencies in controllers
            ControllerBuilder.Current.SetControllerFactory( new DefaultControllerFactory( new CompositionControllerActivator( dependencyResolver ) ) );

            // Tell MVC3 to resolve dependencies in filters
            FilterProviders.Providers.Remove( FilterProviders.Providers.Single( f => f is FilterAttributeFilterProvider ) );
            FilterProviders.Providers.Add( new CompositionFilterAttributeFilterProvider( dependencyResolver ) );

            // Tell MVC3 to resolve dependencies in model validators
            ModelValidatorProviders.Providers.Remove( ModelValidatorProviders.Providers.OfType<DataAnnotationsModelValidatorProvider>().Single() );
            ModelValidatorProviders.Providers.Add( new CompositionDataAnnotationsModelValidatorProvider( dependencyResolver ) );

            // Tell MVC3 to resolve model binders through MEF. Model binders must be decorated with [ModelBinderExport].
            ModelBinderProviders.BinderProviders.Add( new CompositionModelBinderProvider( dependencyResolver ) );
        }
    }
}

此外,您需要将控制器导出到MVC。以下是我如何做到这一点的一个例子:

[Export]
[PartCreationPolicy( CreationPolicy.NonShared )]
public partial class HomeController : ControllerCore
{
    [ImportingConstructor]
    public HomeController( DataContext context, ILogFactory logFactory, ServiceFactory serviceFactory ) : base( context, logFactory, serviceFactory )
    {
    }

    public virtual ActionResult Index()
    {
        return View();
    }
}

希望这有帮助!