PartCreationPolicy default problem

Jun 23, 2009 at 8:59 PM


I'm wondering about the following scenario involving shared and non shared exports with the same contract.


interface IService {}

class SharedService : IService {}

class NonSharedService : IService {}


The source comments indicates that an export will default to CreationPolicy.Any, which in means that the CompositionContainer will choose Shared by default, unless the part or the importer request a non shared one.

However, the behavior I get is different:

In the above case, NonSharedService is essentially shared on GetExports<IService>(...).GetExportedObject()

But when none of the exported services define the PartCreationPolicy attribute, both exports return Non-Shared instances. Is this right? or should I be wrong to expect that both exports are going to return shared instances?

What is the designed default behavior when an export doesn't define the PartCreationPolicy attribute?




Jun 23, 2009 at 10:42 PM

The default behavior is that if both the Exporter and the Importer are marked with CreationPolicy.Any then you should get a Shared instance. See for a complete table of possibilities.

In your case I would expect for both SharedService and NonSharedServices to return the same instance within in a given container each time they are asked for. If this isn't the behavior you are seeing can you please post some sample code that does repros the different behavior. Also how are you determining that they both return NonShared instances?

Jun 24, 2009 at 12:08 AM
Edited Jun 24, 2009 at 12:10 AM


Thanks for the reply. It seems I was evaluating something wrong before because doing a test and then trying on the code itself the behavior I get is like what you are describing. 

As for the determination of the nonshared instances, I get the exports by quering with specific metadata to the NonSharedService type, and then comparing the references.

Something on these lines:


interface IService { }

[Service(ServiceType = typeof(NonSharedService))]
class NonSharedService : IService { }

[Service(ServiceType = typeof(SharedService))]
class SharedService : IService { }

class ServiceAttribute : Attribute, IServiceMetadata
    public Type ServiceType { get; set; }

public interface IServiceMetadata
    Type ServiceType { get; } 

class Program
    static void Main(string[] args)
        AggregateCatalog catalog = new AggregateCatalog();

        catalog.Catalogs.Add(new TypeCatalog(typeof(NonSharedService), typeof(SharedService)));

        CompositionContainer container = new CompositionContainer(catalog);

        var nonSharedExp = container.GetExports<IService, IServiceMetadata>()
            .Where(export => export.MetadataView.ServiceType == typeof(NonSharedService))
        var otherNonSharedExp = container.GetExports<IService, IServiceMetadata>()
            .Where(export => export.MetadataView.ServiceType == typeof(NonSharedService))

            "The two exports for the same NonSharedService type are equal");

        IService nonSharedService = nonSharedExp.GetExportedObject();

        IService otherNonSharedService = otherNonSharedExp.GetExportedObject();

            "The two references to a Non-Shared part are equal");

        var sharedExp = container.GetExports<IService, IServiceMetadata>()
            .Where(export => export.MetadataView.ServiceType == typeof(SharedService))

        var otherSharedExp = container.GetExports<IService, IServiceMetadata>()
            .Where(export => export.MetadataView.ServiceType == typeof(SharedService))

           "The two exports for the same SharedService type are equal");

        IService sharedService = sharedExp.GetExportedObject();

        IService otherSharedService = otherSharedExp.GetExportedObject();

            "The two references to a shared service are equal");


On an unrelated note, adding the type in the attribute was a way to get around the fact that MEF doesn't expose the type on the export (discussed somewhere on the forum). 

Although I understand the design reasoning, it makes our system run a lot better if we have access to it.

Thanks again,