I'm trying to override the default Unity Container behavior for the Enterprise Library so that I can use my MEF container. There are a few resources with explanations of how to do this but I'm just not getting it:
- http://blogs.msdn.com/b/bobbrum/archive/2009/06/23/enterprise-library-5-0-some-architecture-changes.aspx
- http://entlib.uservoice.com/forums/90505-silverlight-integration-pack/suggestions/1284693-mef-configurator-for-enterprise-library-container
- http://entlib.codeplex.com/discussions/261443
There is also this post on SO but the code does not compile because LogWriter
is protected. I assume this referred to an old version:
What I understand is that I need to use the CommonServiceLocator
for my MEF container and then attach this to the Enterprise Library container. Here's what I have for my container configurator:
public class MefContainerConfigurator : IContainerConfigurator, IServiceLocator
{
[Import] private CatalogExportProvider provider;
public object GetService(Type serviceType)
{
throw new NotImplementedException();
}
public object GetInstance(Type serviceType)
{
return provider.GetExportedValue<Type>();
}
public object GetInstance(Type serviceType, string key)
{
throw new NotImplementedException();
}
public IEnumerable<object> GetAllInstances(Type serviceType)
{
throw new NotImplementedException();
}
public TService GetInstance<TService>()
{
return provider.GetExportedValue<TService>();
}
public TService GetInstance<TService>(string key)
{
return provider.GetExportedValue<TService>(key);
}
public IEnumerable<TService> GetAllInstances<TService>()
{
return provider.GetExportedValues<TService>();
}
public void RegisterAll(IConfigurationSource configurationSource, ITypeRegistrationsProvider rootProvider)
{
throw new NotImplementedException();
}
}
And in my bootstrapper:
var configurator = new MefContainerConfigurator();
// Does this line read the Enterprise Library configuration from the app.config?
IConfigurationSource cs = new SystemConfigurationSource();
EnterpriseLibraryContainer.ConfigureContainer(configurator, cs);
I think maybe I need to make use of the LogWriterImpl
and ExceptionManagerImpl
classes as these have constructors which accept configuration. My questions at this point would be:
- How do I retrieve the configuration from the
IConfigurationSource
and feed it into the constructors for theLogWriterImpl
andExceptionManagerImpl
constructors? EnterpriseLibraryContainer.ConfigureContainer
callsRegisterAll
in myMefContainerConfigurator
. Is this where I'm supposed to register all of the enterprise library types into the container?- The methods from the
IServiceLocator
interface that I have left as NotImplemented; I couldn't find a way to use these to return objects from my container. Am I supposed to leave them as not implemented and use the generic methods instead?
Edit
I still cannot get this totally right. Based on @Chris Tavares answer, I wrote my RegisterAll
method in the MefContainerConfigurator
to iterate through the TypeRegistrations and add them to a container. I cannot for the life of me figure out how to merge these to my AggregateContainer
that is created in my Bootstrapper
class so that I can actually use these exports outside of the ContainerConfigurator
:
public void RegisterAll(IConfigurationSource configurationSource, ITypeRegistrationsProvider rootProvider)
{
var registrations = rootProvider.GetRegistrations(configurationSource);
foreach (var type in registrations)
{
var builder = new RegistrationBuilder();
builder.ForType(type.ServiceType).Export();
var cat = new AssemblyCatalog(type.ServiceType.Assembly, builder);
var container = new CompositionContainer(cat);
container.ComposeParts(this);
}
}
ConfigureAggregateCatalog in Prism bootstrapper:
protected override void ConfigureAggregateCatalog()
{
AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(RegionNames).Assembly));
// Module assemblies
AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(DataEntryModule).Assembly));
AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(ReportingModule).Assembly));
AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(StatusBarModule).Assembly));
AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(SplashScreenModule).Assembly));
AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(WelcomeModule).Assembly));
AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(AdministrationModule).Assembly));
AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(Bootstrapper).Assembly));
}