我正在学习 MEF,我想创建一个简单的示例(应用程序)以了解它的实际工作原理。于是我想到了一个简单的翻译器。我创建了一个包含四个项目(DLL 文件)的解决方案:
契约(Contract)
网络
必应翻译器
谷歌翻译
Contracts 包含 ITranslate
接口(interface)。顾名思义,它只包含契约(Contract)(接口(interface)),因此导出商和进口商都可以使用它。
public interface ITranslator
{
string Translate(string text);
}
BingTranslator 和 GoogleTranslator 都是该契约(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.dll 和 BingTranslator.dll 文件的文件夹(导出器位于这些文件中) ,并在 /bin
文件夹中
我只有包含导入程序的 Web.dll 文件。但是,我的问题是,MEF 不会使用所需的转换器填充 GeneralController
的 Translator
属性。我阅读了该站点上与 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/