- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在构建一个简单的 MEF 应用程序。我想要实现的是构建一个插件,可以在同一个组合应用程序中多次注册。插件的注册应该取决于插件配置文件中的设置,但我无法做到这一点。
[编辑]
我的服务器有 CompositionContainer,需要与 6 个不同的目标(即交通灯 Controller )通信。对于每个目标,我想添加一个插件。插件逻辑是一样的,所以我只想维护1个插件。每个目标都有自己的网址进行通信(以及一些其他配置项),我希望它们位于(单独的)配置文件中。
我尝试的是将插件放在子目录中,然后递归地遍历这些目录以将插件添加到目录中。但是,这不起作用。在子目录中找到的第二个插件将被导入,但这个插件是针对第一个插件的。当循环遍历容器 FASTAdapters 时,所有部分似乎都与第一个部分相同。
private void Compose()
{
var catalog = new AggregateCatalog();
string sDir = AppSettingsUtil.GetString("FASTAdaptersLocation", @"./Plugins");
foreach (string d in Directory.GetDirectories(sDir))
{
catalog.Catalogs.Add(new DirectoryCatalog(d));
}
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
我不知道我是否也可以使用 ExportMetadata 属性。似乎必须对 ExportMetadata 属性进行硬编码,但我希望尽可能从配置文件中读取该属性。
[/编辑]
我的目标是拥有 6 个 ControllerAdapter,每个针对不同的 Controller (读作:与不同的网络服务器通信)。 6 个 ControllerAdapter 中的逻辑是相等的。
我认为复制 ClassLibrary(例如复制到 1.dll、2.dll 等)并添加配置文件(1.dll.config 等)应该可以解决问题,但不是。
在组合时,我在容器中得到多个实例typeof(FAST.DevIS.ControllerAdapter)
,但我不知道如何进一步。
我需要在导出时对元数据做些什么吗?
导入服务器
[ImportMany]
public IEnumerable<IFASTAdapter> FASTAdapters { get; set; }
private void Compose()
{
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new DirectoryCatalog(AppSettingsUtil.GetString("FASTAdaptersLocation", Path.GetDirectoryName(Assembly.GetAssembly(typeof(ControllerServer)).Location))));
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
插件
namespace FAST.DevIS.ControllerAdapter
{
[Export (typeof(IFASTAdapter))]
public class ControllerAdapter : IFASTAdapter
{
...
}
}
界面
namespace FAST.Common.FastAdapter
{
public interface IFASTAdapter
{
/// Parse plan parameters
///
//Activator
bool ParsePlan(PlansContainer plan);
bool ActivatePlan();
void Configure(string config);
}
}
最佳答案
与 MEF 解决方案相比,这可能更多地与您如何使用程序集有关。
你说:
The logic in the 6 ControllerAdapters is equal.
那么是同一个DLL只是复制了6次到不同的插件目录吗?如果是,那就是问题所在。
我对您的方法进行了建模并运行了一些测试来证明我的想法。该代码实际上与您的相同,并从服务器的 bin/plugin 目录的子目录中读取插件。
使用NUnit 来练习服务器类库的简单测试:
[Test]
public void Compose()
{
var server = new Server();
server.Compose();
Console.WriteLine("Plugins found: " + server.FASTAdapters.Count());
Console.WriteLine();
foreach (var adapter in server.FASTAdapters)
{
Console.WriteLine(adapter.GetType());
Console.WriteLine(adapter.GetType().Assembly.FullName);
Console.WriteLine(adapter.GetType().Assembly.CodeBase);
Console.WriteLine();
}
Assert.Pass();
}
一个插件的测试结果:
Plugins found: 1AdapterPlugin.ControllerAdapterAdapterPlugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=nullfile:///C:/USERS/GARKIN/DOCUMENTS/VISUAL STUDIO 2012/PROJECTS/MEFADAPTERS/ADAPTERSERVER/BIN/DEBUG/PLUGINS/ADAPTER1/ADAPTERPLUGIN.DLL
Test result for two plugins in place, using the same plugin assembly copied over to two distinct plugin directories (probably your case):
Plugins found: 2AdapterPlugin.ControllerAdapterAdapterPlugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=nullfile:///C:/USERS/GARKIN/DOCUMENTS/VISUAL STUDIO 2012/PROJECTS/MEFADAPTERS/ADAPTERSERVER/BIN/DEBUG/PLUGINS/ADAPTER1/ADAPTERPLUGIN.DLLAdapterPlugin.ControllerAdapterAdapterPlugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=nullfile:///C:/USERS/GARKIN/DOCUMENTS/VISUAL STUDIO 2012/PROJECTS/MEFADAPTERS/ADAPTERSERVER/BIN/DEBUG/PLUGINS/ADAPTER1/ADAPTERPLUGIN.DLL
You also get the exact same result if you give distinct names to those DLLs because effectively it is still the same assembly inside.
Now I add the third plugin, but this time it is a different plugin assembly:
Plugins found: 3AdapterPlugin.ControllerAdapterAdapterPlugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=nullfile:///C:/USERS/GARKIN/DOCUMENTS/VISUAL STUDIO 2012/PROJECTS/MEFADAPTERS/ADAPTERSERVER/BIN/DEBUG/PLUGINS/ADAPTER1/ADAPTERPLUGIN.DLLAdapterPlugin.ControllerAdapterAdapterPlugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=nullfile:///C:/USERS/GARKIN/DOCUMENTS/VISUAL STUDIO 2012/PROJECTS/MEFADAPTERS/ADAPTERSERVER/BIN/DEBUG/PLUGINS/ADAPTER1/ADAPTERPLUGIN.DLLAdapterPlugin2.ControllerAdapterAdapterPlugin2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=nullfile:///C:/USERS/GARKIN/DOCUMENTS/VISUAL STUDIO 2012/PROJECTS/MEFADAPTERS/ADAPTERSERVER/BIN/DEBUG/PLUGINS/ADAPTER3/ADAPTERPLUGIN2.DLL
The different assembly is of course found and identified correctly.
So this all boils down to how the .NET runtime handles assembly loading, which is a complex and strictly defined process and works differently for strongly and weakly named assemblies. I recommend this article for a good explanation of the process: Assembly Load Contexts Subtleties.
In this case, the same process is followed behind the scenes when using MEF:
The .NET runtime finds the first weakly typed plugin assembly and loads it from that location and MEF does it's export processing.
Then MEF tries to process the next plugin assembly it founds using the catalog, but the runtime sees the assembly with the same metadata already loaded. So it uses the already loaded one to look for exports and ends up instantiating the same type again. It does not touch the second DLL at all.
There is no way the same assembly can be loaded more than once by the runtime. Which makes perfect sense when you think of it. Assembly is just bunch of types with their metadata and once loaded the types are available, no need to load them again.
This may not be completely correct, but I hope it helps to explain where the problem lies and it should be clear that duplicating DLLs for this purpose is useless.
Now regarding what you want to achieve. It seems that all you need is just to get multiple instances of the SAME adapter plugin to use them for different purposes, which has nothing to do with multiplying DLLs.
To get multiple adapter instances you can define multiple imports with RequiredCreationPolicy
set to CreationPolicy.NonShared
in your server which MEF will accordingly instantiate for you:
public class Server
{
[Import(RequiredCreationPolicy = CreationPolicy.NonShared)]
public IFASTAdapter FirstAdapter { get; set; }
[Import(RequiredCreationPolicy = CreationPolicy.NonShared)]
public IFASTAdapter SecondAdapter { get; set; }
// Other adapters ...
public void Compose()
{
var catalog = new AggregateCatalog();
var pluginsDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "plugins");
foreach (string d in Directory.GetDirectories(pluginsDir))
{
catalog.Catalogs.Add(new DirectoryCatalog(d));
}
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
}
相应的 NUnit 测试以检查适配器是否已实例化并且它们是不同的实例:
[Test]
public void Compose_MultipleAdapters_NonShared()
{
var server = new Server();
server.Compose();
Assert.That(server.FirstAdapter, Is.Not.Null);
Assert.That(server.SecondAdapter, Is.Not.Null);
Assert.That(server.FirstAdapter, Is.Not.SameAs(server.SecondAdapter));
}
如果所有这些都能在一定程度上帮助您,我们还可以看看您希望如何配置什么以及如何使用 app.config 实例化。
关于c# - 如何根据 app.config 多次导出一个 MEF 插件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15131014/
我在互联网上搜索了很多小时,但没有找到满意的结果,所以 -VSTO Addin 和 COM Addin(我们作为类库项目制作并使用 Excel 对象)之间有什么区别?VSTO 项目是否有任何限制,例如
我在互联网上搜索了很多小时,但没有找到满意的结果,所以 -VSTO Addin 和 COM Addin(我们作为类库项目制作并使用 Excel 对象)之间有什么区别?VSTO 项目是否有任何限制,例如
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,
我正在寻找有关如何构建可扩展 WCF 服务器(具有动态加载的服务)的建议,最好使用 System.Addins 或 MEF。 服务器应托管实现最小“插件”API(StartService/StopSe
有没有一种方法可以使用加载浏览器扩展/插件/插件的 headless 浏览器(即 PhantomJS、Selenium)来运行自动测试? 更具体地说,我想模拟广告拦截器(如 Ghostery、ad-b
我是 gradle 的新手,我使用 artifactory 作为我的 repo 服务器。我在网上查看了如何将我的项目发布到我的 repo 服务器,发现我可以使用 maven-publish 或使用 a
我想禁用某些状态的点击/事件,并仅使少数状态可点击。我通读了http://newsignature.github.io/us-map/处的文档,并且找不到与此问题相关的任何内容。 最佳答案 http:
据我了解,在Intellij中使用idea插件打开Maven构建的项目并不是最好的方法,即调用: mvn idea:idea 但是直接打开pom文件(Intellij有默认的Maven插件);同样的事
使用Artifactory plugin对于 Jenkins pipeline 来说是一种幸福,只要遵循文档就可以了。但后来我介绍了Maven Flatten plugin解析父模块和子模块 mvn
我已经安装了Elasticsearch版本1.7.1。一切正常。我也安装了 JDBC 驱动程序。检查下面我的插件文件夹 目录E:\Xampp\htdocs\my-elastic\elasticsear
在我使用 webpack common chunks 插件创建包含第三方库(如 angular、react、lodash 等)的 vendor 包之前,但后来我知道了 webpack dll
我们正在尝试使用(Jenkins、sonar、eclipse ...)安装 CI 平台。 为了让每个开发人员都可以在提交之前对他的代码进行分析,我想知道两种选择: 使用 Sonar 插件运行本地分析。
我知道这是一个比较特殊的问题。尽管如此,也许有些人知道这一点: 我想在 Eclipse 中使用 Maven 编译 Hector=> 分支:0.7.0 和标签:hector-0.7.0-29(https
我卡住了。我一直在尝试寻找或自己创建一个简单的准系统示例,说明如何为 VS 2010 Express 创建 Outlook 插件。我知道这在 VS 2010 Pro 中更简单,但是,在快速版本中真的不
我有以下排除过滤器来忽略所有 R 文件类: findbugs-exclude-filter.xml 当我将它用于 FindBugs-IDEA 插件时,它可以
我刚开始玩 CakePHP,我发现了 Wildflower CMS .我喜欢这个想法,并打算开始修补它。不过,我有一个问题。 在自述文件中,我发现了以下内容:“Wildflower 不是也不会是 Ca
虽然现在大部分情况都是使用n-api来编写插件,但是底层毕竟是v8(和libuv),使用v8编写简单的插件,同时熟悉v8的使用。 本文介绍在写c++插件时,简单又常用的写法,其实本质上,写插件
本篇是 Python 系列教程第 3 篇,更多内容敬请访问我的 Python 合集 Visual Studio Code的安装非常简单,就不放这里增加文章篇幅了。 相比PyCharm,V
Maven – 插件 什么是 Maven 插件? Maven 实际上是一个依赖插件执行的框架,每个任务实际上是由插件完成。Maven 插件通常被用来: 创建 jar 文件 创建 war
我正在编写一个插件来添加带有标签 [deposit_page] 的页面;该标记应替换为一些 PHP 代码。 这就是我所拥有的,但它不起作用。有什么我遗漏或做错了什么吗? function deposi
我是一名优秀的程序员,十分优秀!