C# – Prism ServiceLocator GetInstance and MEF

cmefprism

I'm trying to use Microsoft.Practices.ServiceLocation.ServiceLocator and MEF. Interface IServiceLocator defines method GetInstance with two parameters. First parameter is serviceType and second paremeter is key.

I have two classes which implement interface IMyInterface and they have Export attribute:

[Export(typeof(IMyInterface)), PartCreationPolicy(CreationPolicy.Shared)]
public class Class1 : IMyInterface 
{}

[Export(typeof(IMyInterface)), PartCreationPolicy(CreationPolicy.Shared)]
public class Class2: IMyInterface 
{}

I want to get instance of Class1 via Prism ServiceLocator GetInstance method:

ServiceLocator.Current.GetInstance(typeof(IMyInterface),"Key");

But I have no idea how and where should be "key" defined. I tried to define key in export attribute:

[Export("Key1",typeof(IMyInterface)), PartCreationPolicy(CreationPolicy.Shared)]
public class Class1 : IMyInterface 
{}

[Export("Key2",typeof(IMyInterface)), PartCreationPolicy(CreationPolicy.Shared)]
public class Class2: IMyInterface 
{}

When I call method GetInstance with key parameter

ServiceLocator.Current.GetInstance(typeof(IMyInterface),"Key1");

I get Microsoft.Practices.ServiceLocation.ActivationException (Activation error occured while trying to get instance of type IMyInterface, key "Key1"). Does anybody know how can be the export key defined?
Thanks

Best Answer

Prism uses MefServiceLocatorAdapter to adapt MEF's CompositionsContainer to the IServiceLocator interface. This is the actual code that is used by it to get your part:

protected override object DoGetInstance(Type serviceType, string key)
{
    IEnumerable<Lazy<object, object>> exports = this.compositionContainer.GetExports(serviceType, null, key);
    if ((exports != null) && (exports.Count() > 0))
    {
        // If there is more than one value, this will throw an InvalidOperationException, 
        // which will be wrapped by the base class as an ActivationException.
        return exports.Single().Value;
    }

    throw new ActivationException(
        this.FormatActivationExceptionMessage(new CompositionException("Export not found"), serviceType, key));
}

So as you can see, you're exporting and calling GetInstance correctly. However, I believe your service locator isn't set up correctly, and that's why you're getting this exception. If you're using Prism's MefBootstrapper to initialize your application, this should already be done for you. Otherwise, you'll need to use this code to initialize it:

IServiceLocator serviceLocator = new MefServiceLocatorAdapter(myCompositionContainer);
ServiceLocator.SetLocatorProvider(() => serviceLocator);
Related Topic