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>();