Search code examples
.netimportcontainersexportmef

compose exported value with mef with non-shared creation policy, but without specify it as attribute


I have an instance of a class which I explicitly created and compose it to a CompositionContainer:

        container.ComposeExportedValue<ILogger>(_logger);

For some reasons, I had to create it explicitly and compose it. using export attribute isn't possible for me.

At every place I import that ILogger, I do it via ctor, for example:

public class A
{
    private readonly ILogger _logger;

    [ImportingConstructor]
    public A(ILogger logger)
    {
        this._logger = logger;
    }
}

In that way, I'll receive the same instance of ILogger every place I import it.

The question is, is it possible to configure that a new identical instance will be created for each time its being imported without using [PartCreationPolicy(CreationPolicy.NonShared)] attribute?

I'll remind you that using attributes isn't possible for me (otherwise I would simply used that attribute)


Solution

  • Try instead:

    public class LoggerComposablePart : ComposablePart
    {
        private readonly IEnumerable<ExportDefinition> exportDefinitions;
    
        public override IEnumerable<ExportDefinition> ExportDefinitions
        {
            get { return exportDefinitions; }
        }
    
        public override IEnumerable<ImportDefinition> ImportDefinitions
        {
            get { return Enumerable.Empty<ImportDefinition>(); }
        }
    
        public LoggerComposablePart()
        {
            Dictionary<string, object> metadata = new Dictionary<string, object>();
    
            metadata.Add(CompositionConstants.ExportTypeIdentityMetadataName, AttributedModelServices.GetTypeIdentity(typeof(ILogger)));
            metadata.Add(CompositionConstants.PartCreationPolicyMetadataName, CreationPolicy.NonShared);
    
            exportDefinitions = new ExportDefinition[] { new ExportDefinition(AttributedModelServices.GetContractName(typeof(ILogger)), metadata) };
        }
    
        public override object GetExportedValue(ExportDefinition definition)
        {
            // Create new logger instance for each import
            return new Logger();
        }
    
        public override void SetImport(ImportDefinition definition, IEnumerable<Export> exports)
        {
        }
    }
    

    Then e.g.:

    CompositionBatch batch = new CompositionBatch();
    
    batch.AddPart(new LoggerComposablePart());
    
    container.Compose(batch);
    
    var x = container.GetExportedValue<A>();