【问题标题】:ASP.NET MVC 4.0 Controllers and MEF, how to bring these two together?ASP.NET MVC 4.0 控制器和 MEF,如何将这两者结合在一起?
【发布时间】:2013-07-08 21:21:31
【问题描述】:

我正在尝试使用 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之间的联系很混乱,起初似乎互联网上有很多例子,但当我深入研究时,大多数都是过时的,不实用或太原始以至于看不到如何将其应用于更大的项目。

谢谢!

【问题讨论】:

    标签: c# asp.net-mvc mef


    【解决方案1】:

    我在 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();
        }
    }
    

    希望这会有所帮助!

    【讨论】:

    • 莫腾,谢谢你的回答!我是否理解正确,在您的主要解决方案中,您使用 HomeController 就像使用任何其他控制器一样?还是您需要在主应用程序的某处声明它? ControllerCore 类有什么作用?
    • ControllerCore 只是一个基本控制器 - 您可以看到构造函数调用了一个基类,其中使用/存储了参数,但您可以直接在 HomeController 中使用它们而无需基类。配置代码连接 MVC 以在创建控制器时使用 MEF,因此在任何地方都不需要额外的代码(除了在 Application_Start 中对 Configure 方法的调用,如答案中所述)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-23
    • 1970-01-01
    • 2011-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多