简体   繁体   中英

MEF composition using ImportMany and existing instances of composable parts

I'm having the following problem:

When using the ImportMany attribute on MEF always at least one instance of an implementation of the IService interface will be created by MEF.

Since I'm having an existing instance already (simulated by creating one in the code below and adding it as a part to the composition batch), I only want to have this instance in my Services property of the ServiceHost instance. (And of course instances from other types having the same interface implementation ..)

But MEF always also creates a new instance and also pushes it to the Services property so that there are two instances - my own created one and one created by MEF.

How do I prevent MEF from creating an own instance?

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Primitives;

namespace TestConsole
{
    public interface IService
    {
        int InstanceId { get; }
    }

    public class Program
    {
        public static int counter;

        private static void Main(string[] args)
        {
            ServiceHost host = new ServiceHost();

            DirectoryCatalog catalog = new DirectoryCatalog(".", "*.exe");
            CompositionContainer container = new CompositionContainer(catalog);
            CompositionBatch compositionBatch = new CompositionBatch();

            // create an existing instance
            TestService c = new TestService();
            ComposablePart part = AttributedModelServices.CreatePart(c);
            compositionBatch.AddPart(part);
            Console.WriteLine("existing instance: {0}", c.InstanceId);

            compositionBatch.AddPart(AttributedModelServices.CreatePart(host));

            container.Compose(compositionBatch);

            foreach (var service in host.Services)
            {
                Console.WriteLine(service.InstanceId);
            }
        }
    }

    public class ServiceHost
    {
        [ImportMany]
        public IService[] Services { get; set; }
    }

    [Export(typeof(IService))]
    public class TestService : IService
    {
        public TestService()
        {
            this.InstanceId = ++Program.counter;
        }

        public int InstanceId { get; private set; }
    }
}

Thank you .. Bernie

So it's working as expected. It finds 2 instances, because you add two instances (one manually, one from DirectoryCatalog).

You have to make decision: Let MEF to manage your instances, or do it yourself.

If it is possible, remove [Export(typeof(IService))] and use AddExportedValue instead of parts, like this:

// create an existing instance
TestService c = new TestService();
compositionBatch.AddExportedValue<IService>(c);

In this case, you add your instance manually to the compositionBatch, and DirectoryCatalog cannot find this, cause of class has no [Exported] Attribute.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM