在MEF中卸载一个dll文件

8

我有一些作为dll文件的插件。我的应用程序加载了dll并运行得很好。但当我尝试删除旧插件并替换为新插件时,它不允许我这样做,因为已被应用程序加载。我发现可以使用 appdomain 来解决这个问题,但我无法找到一个使用 mef 的解决方案。

我需要一段可以在 mef 上运行的代码。下面是我用来加载插件的代码。

//Creating an instance of aggregate catalog. It aggregates other catalogs
var aggregateCatalog = new AggregateCatalog();

//Build the directory path where the parts will be available
var directoryPath = "Path to plugins folder";

//Load parts from the available dlls in the specified path using the directory catalog
var directoryCatalog = new DirectoryCatalog(directoryPath, "*.dll");

//Add to the aggregate catalog
aggregateCatalog.Catalogs.Add(directoryCatalog);

//Crete the composition container
var container = new CompositionContainer(aggregateCatalog);


// Composable parts are created here i.e. the Import and Export components assembles here
container.ComposeParts(this);
2个回答

5
我发现通过使用AppDomain可以实现这一点。但我无法找到使用MEF的解决方案。
不幸的是,MEF不支持此功能。 MEF专门设计用于应用程序可扩展性,而不是作为通用插件系统,支持在运行时卸载和替换代码。
使这个工作的唯一方法是在一个单独的AppDomain中使用MEF,并整体卸载AppDomain 。 CLR本身不支持卸载已加载的程序集,除了卸载打开程序集的整个AppDomain。

应该有解决方案。我听说这将在MEF的下一个版本中发布。不知道是否属实。 - fhnaseer
1
@fhnaseer 不,至少目前公开展示的内容中没有。这真的超出了MEF预期使用案例的范围,所以我怀疑它会在那里发生。CLR中唯一支持的删除程序集的方法是卸载整个AppDomain。作为一个库,MEF无法“绕过”这个问题。 - Reed Copsey
那么,在ImportMany中,“AllowRecomposition = true”的含义是什么呢?无论我写还是不写,行为都是相同的。 - fhnaseer
1
@fhnaseer 它允许MEF引入更多的程序集 - 但它从不删除它们。 基本上,IEnumerable<T>会使用额外的类型重新创建,但旧的程序集仍然保留在内存中。 - Reed Copsey

1

如果您尝试像这样在目录中插入一个装配对象:

Assembly assembly = Assembly.Load(System.IO.File.ReadAllBytes(Path.Combine(directoryPath, ItemPlugin)));
aggregateCatalog.Catalogs.Add(new AssemblyCatalog(assembly));

您可以稍后删除/更改文件...

1
你可以从aggregateCatalog中删除它,但是如果不卸载整个appdomain,就无法从appdomain中卸载程序集。 - Peter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接