3

经过大量挖掘后,我认为可以在 MVC4 中将 MEF 用于 DI,下面的 SO 链接给出了几个示例:

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

它们工作得很好,但我想知道如何消除像 MVC 4 应用程序中的控制器一样显式“导入”和“导出”的需要?

网上有一些建议,一些顶级编程头脑的博客。但我在复制他们的成功故事方面收效甚微。仅举几例:

请问有什么建议吗?

4

2 回答 2

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...

于 2013-05-20T00:04:49.463 回答
0

好的,我现在有一个解决方案。

MEFcontrib 为基于约定的模型提供了良好的支持。因此,只需将 NuGet(安装包 mefcontrib)添加到您的 mvc 4 项目即可。

一旦你有了 mefcontrib 二进制文件,你只需要先注册约定,然后通过添加约定目录来利用它。下面的片段显示了如何:

大会注册:

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

这会注册您的 api 控制器和 mvc 控制器,以便它们可以被 MEF 化。但是,它不包括 AsyncController。

MEF MVC 引导程序

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);
    }
}

就这样,大功告成!在您的 MVC 4 应用程序中享受动态 DI。

于 2013-05-22T11:28:18.947 回答