Replacing an exported value

Dec 21, 2009 at 9:40 PM

I have a logging interface with two implementations, both of which are marked as exports using the type of the interface, with the non-default one set as not discoverable. I would like to switch between an instance of the non-default implementation and the default implementation as logging is enabled or disabled by replacing the old exported value with the new one. I have been adding the new value to the CompositionContainer using the ComposeExportedValue method, but I have been unable to remove the old exported value from the container. How am I supposed to replace the exported value of a particular type with a new one?

Dec 21, 2009 at 11:42 PM

Exported values cannot be removed. Parts can. To add/remove parts you need to use CompositionBatch. You use AddPart to add an instance. The method returns a ComposablePart which you need to save in order to remove later.

The unit-test below shows your logger scenario using the manner I described. If you copy it into a test project and add a reference to MEF, it should work.

using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;

namespace RemovingParts
{
    [TestClass]
    public class LoggerTests {
        [TestMethod]
        public void When_logger_is_removed_replacement_logger_is_returned()
        {
            var container = new CompositionContainer();
            var batch = new CompositionBatch();
            var part = batch.AddPart(new LoggerA());
            container.Compose(batch);
            
            //now remove and replace
            batch = new CompositionBatch();
            batch.RemovePart(part);
            batch.AddPart(new LoggerB());
            container.Compose(batch);
            
            var logger = container.GetExportedValue<ILogger>();
            Assert.AreEqual(typeof(LoggerB), logger.GetType());
        }

        [Export(typeof(ILogger))]
        public class LoggerA : ILogger
        {
        }

        [Export(typeof(ILogger))]
        public class LoggerB : ILogger
        {
        }

        public interface ILogger { }
    }
}