So we've got MEF working with MVC4, how about the convention based model?

假如想象 提交于 2020-01-04 06:27:06

问题


After much digging about I figured it's possible to use MEF for DI in MVC4, below SO link gives a couple of examples:

How to integrate MEF with ASP.NET MVC 4 and ASP.NET Web API

They work fine, but I'm wondering how to eliminate the need of explicitly "Import" and "Export" the obvious like your controllers in the MVC 4 app?

There are some suggestions on the web, some top programming minds' blogs. But I had little success in replicating their success stories. Just to name a couple:

  • http://mef.codeplex.com/wikipage?title=Standalone%20Web%20API%20dependency%20resolver%20using%20Microsoft.Composition&referringTitle=Documentation

  • http://blog.longle.net/2013/05/17/generically-implementing-the-unit-of-work-repository-pattern-with-entity-framework-in-mvc-simplifying-entity-graphs-part-2-mvc-4-di-ioc-with-mef-attributeless-conventions/

Any suggestions please?


回答1:


The version that ships with .NET 4.0 has no built in way to do this. I think MEF 2 ships with 4.5 and it has some more options including naming conventions. There is probably a version you can download and use with .NET 4.0 somewhere on NuGet.

Microsofts continuous development and pre-releases of their open source libraries is great, but its sometimes quite hard to work out what features are available in each release and what version has made it into which framework. I can't really find a definitive answer...




回答2:


Ok, I have a solution now.

The MEFcontrib offers good support for the convention based model. So simply NuGet it(install-package mefcontrib) to your mvc 4 project.

Once you have the mefcontrib binaries, you just need to register the conventions first and then harness it by adding the convention catalogue. Below snippet shows how:

Convention registration:

public class InitPartsConvention : PartRegistry
{
    public InitPartsConvention()
    {
        Scan(x => x.Assembly(Assembly.GetExecutingAssembly()));

        Part()
            .ForTypesAssignableFrom<IHttpController>()
            .MakeNonShared()
            .Export()
            .Imports(x =>
            {
                x.Import().Members(
                    m => new[] {
                                 m.GetConstructors()
                                 .FirstOrDefault(
                                    c => c.GetCustomAttributes(typeof(ImportingConstructorAttribute), false).Length > 0) 
                                    ?? m.GetGreediestConstructor()
                             });

                x.Import().Members(
                    m => m.GetMembers(BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic)
                        .Where(
                        mbr => mbr.GetCustomAttributes(typeof(ImportAttribute), false).Length > 0).ToArray()
                        );
            });

        Part()
            .ForTypesAssignableFrom<IController>()
            .MakeNonShared()
            .Export()
            .Imports(x =>
            {
                x.Import().Members(
                    m => new[] {
                                 m.GetConstructors()
                                 .FirstOrDefault(
                                    c => c.GetCustomAttributes(typeof(ImportingConstructorAttribute), false).Length > 0) 
                                    ?? m.GetGreediestConstructor()
                             });

                x.Import().Members(
                    m => m.GetMembers(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Where(
                        mbr => mbr.GetCustomAttributes(typeof(ImportAttribute), false).Length > 0).ToArray()
                        );
            });
    }
}

This registers your api controllers and mvc controller so that they can be MEFified. It does not cover the AsyncController however.

MEF MVC bootstrapper

public static class MefBootstrapper
{
    public static void RegisterMef()
    {
        var container = GetContainer();
        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;
    }

    private static CompositionContainer GetContainer()
    {
        var path = HostingEnvironment.MapPath("~/bin");
        if (path == null) throw new Exception("Unable to find the path");

        var catelog = new AggregateCatalog(
            new DirectoryCatalog(path),
            new ConventionCatalog(new InitPartsConvention()));  // this adds the convention to MEF
        return new CompositionContainer(catelog);
    }
}

That's it, job done! Enjoy dynamic DI in your MVC 4 apps.



来源:https://stackoverflow.com/questions/16626637/so-weve-got-mef-working-with-mvc4-how-about-the-convention-based-model

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!