从容器中取出时丢弃部件

时间:2013-08-15 18:17:32

标签: c# mef

我使用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(),但事实并非如此。正如AddPart / RemovePart中的Parts Lifetime所述,在这种情况下应该处理非共享部分。我的代码中是否有错误?

1 个答案:

答案 0 :(得分:1)

据我所知,使用CompositionBatch添加的部分由ComposablePartExportProvider处理(这是一个实现细节),它不会处理它们。只有CatalogPartExportProvider处理其导出的部件并使用此提供程序,您需要让MEF创建部件。

有关详细信息,您可以在What does ReleaseExport really do?中阅读 weshaggard 的第一个答案。

如果您使用.NET 4.5,那么您可以使用MEF2引入的约定模型。 否则,您可以使用TypeCatalogAggregateCatalog相结合的方式向容器添加类型,CompositionContainer.ReleaseExport以便随意释放(并在支持时配置)非共享部分和AggregateCatalog.Catalogs。删除以从容器中删除类型。

以下是使用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);