我使用 CompositionBatch 将可组合部分添加到容器中,稍后通过重组将其移除。一切都很好,构图和重组。但我的问题是底层对象没有被处置。我的代码如下所示:
[PartCreationPolicy(CreationPolicy.NonShared)]
[Export]
public class NonShared : IDisposable
{
public NonShared()
{
Console.WriteLine("Constructor of NonShared");
}
public void Dispose()
{
Console.WriteLine("Disposing NonShared");
}
}
class Program : IPartImportsSatisfiedNotification
{
[Import(AllowDefault=true, AllowRecomposition=true)]
private NonShared _nonShared;
public void OnImportsSatisfied()
{
Console.WriteLine("Program.OnImportsSatisfied()");
}
static void Main()
{
new Program().Run();
}
private void Run()
{
var partDefinition = AttributedModelServices.CreatePartDefinition(typeof(NonShared), null);
var exportingPart = partDefinition.CreatePart();
var addingBatch = new CompositionBatch();
addingBatch.AddPart(this);
addingBatch.AddPart(exportingPart);
var container = new CompositionContainer();
container.Compose(addingBatch);
// Do something.
var removingBatch = new CompositionBatch();
removingBatch.RemovePart(exportingPart);
container.Compose(removingBatch);
}
}
我希望调用 Nonshared.Dispose(),但事实并非如此。作为Parts Lifetime在AddPart/RemovePart描述的,非共享部分应该在这种情况下被处理掉。我的代码中是否有错误?
最佳答案
据我所知,使用 CompositionBatch 添加的部件由 ComposablePartExportProvider 处理(这是一个实现细节),它不会处理它们。只有 CatalogPartExportProvider 处理其导出的部件,要使用此提供程序,您需要让 MEF 创建部件。
有关这方面的更多信息,您可以阅读 weshaggard 在 What does ReleaseExport really do? 中的第一个答案。 .
如果您在 .NET 4.5 上工作,那么您可以使用随 MEF2 引入的约定模型。 否则你可以使用 TypeCatalog s 结合 AggregateCatalog向容器添加类型,CompositionContainer.ReleaseExport随意释放(并在支持的情况下处置)非共享部分和 AggregateCatalog.Catalogs。 Remove 从容器中移除类型。
这是一个使用 TypeCatalog
的示例:
class Program : IPartImportsSatisfiedNotification
{
[Import(AllowDefault=true, AllowRecomposition=true)]
private Lazy<NonShared>_nonShared; //Lazy<T> is needed for ReleaseExport to work.
public void OnImportsSatisfied()
{
Console.WriteLine("Program.OnImportsSatisfied()");
}
static void Main()
{
new Program().Run();
}
private void Run()
{
var aggregateCatalog = new AggregateCatalog();
using (var container = new CompositionContainer(aggregateCatalog ))
{
container.ComposeParts(this);
//Check if the field is injected. It shouldn't be since the
//NonShared type is not known to the container yet..
Console.WriteLine("NonShared field {0}", this._nonShared != null ? "exists" : "does not exist");
//Add the NonShared type to a type catalog.
var typeCatalog = new TypeCatalog(typeof(NonShared));
//Add the TypeCatalog to the AggregateCatalog.
aggregateCatalog.Catalogs.Add(typeCatalog);
//Check if the field is injected. This time it should be.
Console.WriteLine("NonShared field {0}", this._nonShared != null ? "exists" : "does not exist");
if(this._nonShared != null)
{
//Access the lazy object so it gets a value.
this._nonShared.Value.ToString();
//Release the part. The Dispose method should be called.
container.ReleaseExport<NonShared>(this._nonShared);
}
}
}
}
您可以轻松地测试整个类型目录的删除:
aggregateCatalog.Catalogs.Remove(typeCatalog);
关于c# - 从容器中取出零件时的处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18259052/