3

Ok so I am using Caliburn Micro and Mef2 in a C# WPF app using .Net 4.5. I am wondering if there is any way I can configure my registrations for Mef2 inside of the separate dlls and then use them inside my main dll. Basically the dll will configure its own imports and exports.

Something like:

RegistrationBuilder builder = new RegistrationBuilder();

        builder.ForTypesDerivedFrom<IShell>().Export<IShell>().SetCreationPolicy(CreationPolicy.Shared);
        builder.ForTypesDerivedFrom<IFindProducts>().Export<IFindProducts>().SetCreationPolicy(CreationPolicy.Shared);
        builder.ForTypesMatching(t => t.Name.EndsWith("ViewModel")).Export().SetCreationPolicy(CreationPolicy.NonShared);

        return builder;

in each dll but I am stuck att he point of merging all the registrations into one RegistrationBuilder to then pass into each catalog.

Contango
  • 76,540
  • 58
  • 260
  • 305
twreid
  • 1,453
  • 2
  • 22
  • 42

1 Answers1

4

An approach would be to pass the RegistrationBuilder to each assembly for update. This could be done by adding an interface like:

public interface IRegistrationUpdater
{
    void Update(RegistrationBuilder registrationBuilder);
}

in a contracts assembly. This one will be referenced by all assemblies that need to register MEF2 Conventions. For example:

public class RegistrationUpdater: IRegistrationUpdater
{
    public void Update(RegistrationBuilder registrationBuilder)
    {
        if (registrationBuilder == null) throw new ArgumentNullException("registrationBuilder");

        registrationBuilder.ForType<SomeType>().ImportProperty<IAnotherType>(st => st.SomeProperty).Export<ISomeType>();
        registrationBuilder.ForType<AnotherType>().Export<IAnotherType>();
    }
}

with SomeType implementing ISomeType and AnotherType implementing IAnotherType. IAnotherType needs not parts. ISomeType needs a IAnotherType part.

Then in your main program you need to find the available IRegistrationUpdaters using something like:

static IEnumerable<IRegistrationUpdater> GetUpdaters()
{            
    var registrationBuilder = new RegistrationBuilder();
    registrationBuilder.ForTypesDerivedFrom<IRegistrationUpdater>().Export<IRegistrationUpdater>();
    using (var catalog = new DirectoryCatalog(".", registrationBuilder))
    using (var container = new CompositionContainer(catalog))
    {
        return container.GetExportedValues<IRegistrationUpdater>();
    }  
}

which can then be used to iterate through each updater and call IRegistrationUpdater.Update(RegistrationBuilder).

var mainRegistrationBuilder = new RegistrationBuilder();
foreach (var updater in GetUpdaters())
{
    updater.Update(mainRegistrationBuilder);
}

var mainCatalog = new DirectoryCatalog(".", mainRegistrationBuilder);
var mainContainer = new CompositionContainer(mainCatalog);

var s = mainContainer.GetExportedValue<ISomeType>();
Panos Rontogiannis
  • 4,154
  • 1
  • 24
  • 29