我正在构建实现MEF的Windows服务。我们的想法是服务应该管理子组件并且是可插拔的,其中可以在运行时引入任意数量的新组件,而无需经历完整的服务重新编译和部署方案。这些组件应该是可插拔的,这意味着只要我将输出组件放到光盘上的指定文件夹中,Windows服务就应该说“嘿,这是一个要运行的新组件......”并且就是这样做的。这就是MEF的力量。到目前为止非常酷的东西。
我理解创建AggregateCatalog和CompositionContainer以导入所有可用子组件(程序集)的概念。这一切都很好,并且在Windows服务初始启动时它按预期工作。但是,我最终将在运行时引入新组件,因此在某些时候我将需要CompositionContainer来识别添加的任何新输出程序集。
我对以下内容的关注是对性能的影响。将CompositionContainer逻辑放入如下所示的循环中是安全/有效的:
[ImportMany(AllowRecomposition = true)]
private IEnumerable<Lazy<IMySubComponentTask, IDictionary<string, object>>>
MySubComponentTasks { get; set; }
while (true)
{
//Create a general aggregate catalog
var catalog = new AggregateCatalog();
//Adds all the parts found in the same assembly as the Program class
catalog.Catalogs.Add(new AssemblyCatalog(typeof(MySubComponentTaskFactory).Assembly));
//Create a new directory catalog
var directoryCatalog = new DirectoryCatalog(@".\Extensions");
//Add the DLLs in the directory to the aggregate catalog
catalog.Catalogs.Add(directoryCatalog);
//Create the current composition container to create the parts
var container = new CompositionContainer(catalog);
//Fill the imports of this object
try
{
container.ComposeParts(this);
}
catch (CompositionException compositionException)
{
Console.WriteLine(compositionException.ToString());
}
}
感谢任何反馈或意见。
谢谢, 麦克
答案 0 :(得分:1)
不,我不会将目录实例化放入循环中。但是,可能会System.Timers.Timer
或System.Threading.Timer
定期检查插件目录 - 最适合您的需求。
由于您的ImportMany允许重构,您应该能够在运行时添加新的合成:
Timer checkPlugin = new Timer();
//set CheckForPlugins as a timer callback or action
void CheckForPlugins()
{
// add plugins catalog if found in directory
}
我找到了一些其他信息:Recomposition and constructors
答案 1 :(得分:0)
创建CompositionContainer应该很便宜。创建目录并不便宜,因为必须检查组件以找到MEF部件。因此,如果可能的话,您应该在循环之外创建目录。