c# - 在 MEF 中正确使用 [Import] 属性

标签 c# asp.net-mvc-3 model-view-controller mef extensibility

我正在学习 MEF,我想创建一个简单的示例(应用程序)以了解它的实际工作原理。于是我想到了一个简单的翻译器。我创建了一个包含四个项目(DLL 文件)的解决方案:

契约(Contract)
网络
必应翻译器
谷歌翻译

Contracts 包含 ITranslate 接口(interface)。顾名思义,它只包含契约(Contract)(接口(interface)),因此导出商和进口商都可以使用它。

public interface ITranslator
{
    string Translate(string text);
}

BingTranslatorGoogleTranslator 都是该契约(Contract)的导出商。他们都执行此契约(Contract)并提供(导出)不同的翻译服务(一个来自 Bing,另一个来自 Google)。

[Export(typeof(ITranslator))]
public class GoogleTranslator: ITranslator
{
    public string Translate(string text)
    {
        // Here, I would connect to Google translate and do the work.
        return "Translated by Google Translator";
    }
}

BingTranslator 是:

[Export(typeof(ITranslator))]
public class BingTranslator : ITranslator
{
    public string Translate(string text)
    {
        return "Translated by Bing";
    }
}

现在,在我的 Web 项目中,我只想从用户那里获取文本,使用其中一个翻译器(Bing 和 Google)进行翻译,然后将结果返回给用户。因此,在我的Web 应用程序中,我依赖于翻译器。因此,我以这种方式创建了一个 Controller :

public class GeneralController : Controller
{
    [Import]
    public ITranslator Translator { get; set; }

    public JsonResult Translate(string text)
    {
        return Json(new
        {
            source = text,
            translation = Translator.Translate(text)
        });
    }
}

拼图的最后一 block 应该是将这些组件(部分)粘合在一起(从较小的部分组成整首歌)。因此,在 Web 项目的 Application_Start 中,我有:

        var parts = new AggregateCatalog
            (
                new DirectoryCatalog(Server.MapPath("/parts")), 
                new DirectoryCatalog(Server.MapPath("/bin"))
            );
        var composer = new CompositionContainer(parts);
        composer.ComposeParts();

/parts 是我放置 GoogleTranslator.dllBingTranslator.dll 文件的文件夹(导出器位于这些文件中) ,并在 /bin 文件夹中 我只有包含导入程序的 Web.dll 文件。但是,我的问题是,MEF 不会使用所需的转换器填充 GeneralControllerTranslator 属性。我阅读了该站点上与 MEF 相关的几乎所有问题,但我无法弄清楚我的示例有什么问题。谁能告诉我我在这里错过了什么?

最佳答案

好的,你需要做的是(没有规定性能,这只是为了看看它是否有效)

public class GeneralController : Controller
{
    [Import]
    public ITranslator Translator { get; set; }

    public JsonResult Translate(string text)
    {
        var container = new CompositionContainer(
        new DirectoryCatalog(Path.Combine(HttpRuntime.BinDirectory, "Plugins")));
        CompositionBatch compositionBatch = new CompositionBatch();
        compositionBatch.AddPart(this);
        Container.Compose(compositionBatch);

        return Json(new
        {
            source = text,
            translation = Translator.Translate(text)
        });
    }
}

我不是 MEF 方面的专家,坦率地说,对于我使用它的目的,它对我没有多大帮助,因为我只用它来加载 DLL,然后我有一个依赖注入(inject)的入口点,从那时起我使用 DI 容器而不是 MEF。

MEF 是必要的——据我所知。在您的情况下,您需要主动编写需要 MEF 的内容,即您的 Controller 因此您的 Controller 工厂需要组合您的 Controller 实例。

因为我很少在我的 MVC 应用程序中使用 MEFed 组件,所以我有一个过滤器来过滤那些需要 MEF 的操作(而不是在我的 Controller 工厂中使用 MEFing 我的所有 Controller ):

public class InitialisePluginsAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        CompositionBatch compositionBatch = new CompositionBatch();
        compositionBatch.AddPart(filterContext.Controller);
        UniversalCompositionContainer.Current.Container.Compose(
            compositionBatch);
        base.OnActionExecuting(filterContext);
    }
}

这里 UniversalCompositionContainer.Current.Container 是一个用我的目录目录初始化的单例容器。


个人对MEF的看法

MEF 虽然不是 DI 框架,但它做了很多这样的事情。因此,与 DI 有很大的重叠,如果您已经使用 DI 框架,它们必然会发生冲突

MEF 在运行时加载 DLL 方面非常强大,尤其是当您拥有 WPF 应用程序时,您可能会在其中加载/卸载插件并期望其他所有内容都按原样运行,添加/删除功能。

对于 Web 应用程序,这没有多大意义,因为您真的不应该在工作的 Web 应用程序中删除 DLL。因此,它的用途非常有限。

我打算写一篇关于 ASP.NET MVC 中的插件的文章,并将用一个链接更新这篇文章。

关于c# - 在 MEF 中正确使用 [Import] 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10700344/

相关文章:

c# - 是否可以绑定(bind)到 XAML 中的 System.Windows.Interactivity.Behavior?

c# - 跨两个列表应用运算符的 C# 惯用方法是什么?

c# mvc pdf 下载在 android chrome 上失败

c# - VS2008中.net 2.0的扩展方法

c# - 使用保留字作为实体名称

asp.net-mvc-3 - 如何使用 Razor 显示动态图像名称

asp.net - Razor - 如何在 div 标签中显示 html 内容?

jquery - c# asp.net mvc 中的 json 对象返回未定义

c# - 我的自动增量不是从1开始

php - 使用 ajax 在基于 mvc 的 php 应用程序的下拉列表中填充城市?