Search code examples
c#dependency-injectionmefsystem.componentmodel

How can I use the same CompositionConainer object (or it's contained assemblies) across my solution?


Let me explain a very simplistic example of what I need. Let's say that I have a VS solution that uses MEF and has the following, broad structure of projects and classes.

  1. Server (Project)
    • Server.cs (Contains Main method, for launching the app.)
  2. Shared (Project)
    • \Contracts
      • ILogger.cs
      • ISettings.cs
  3. Settings (Project)
    • MySettings.cs (class implementing ISettings)
  4. Logger (Project
    • MyLogger.cs (class implementing ILogger)

Given...

  • All of the above projects reference the Shared project.
  • Server is the starting application, which initializes all catalogs into an application container.

...I can start an application and initialize a singleton of MySettings and MyLogger from within my Server application. So far, so good.

Now, let's assume that MyLogger needs to access a settings file for an output directory. The value for the directory location is stored in the MySettings object, which is initialized in Server.cs into a CompositonContainer.

Since I'm using MEF, I do not want to have to reference the Settings project, within the Logger project. Instead, I'd like to use MEF to get the current applications ISettings singleton, which was initialized at the start of my Server application and exists withing the servers CompositionContainer.

How can I properly access the MySettings singleton from within MyLogger using MEF?


Solution

  • Server:

     class Services
     {
         [Import]
         public ISettings Settings 
         { 
             get; set;
         }
    
         [Import]
         public ILogger Logger 
         {
            get;  set;
         }
    
     }
    
    
     static void Main()
     {
         AggregateCatalog catalog = new AggregateCatalog();
         catalog.Add(new AssemblyCatalog(Assembly.GetAssembly(typeof(SettingsProject.MySettings));
         catalog.Add(new AssemblyCatalog(Assembly.GetAssembly(typeof(LoggerProject.MyLogger));
    
    
         Services services = new Services();
    
         CompositionContainer cc = new CompositionContainer(catalog);
         cc.ComposeParts(services);
    
         // services properties are initialized           
    
     }
    

    Settings Project

     [Export(typeof(ISettings)]
     class MySettings
     {
     }
    

    Logger project

     [Export(typeof(ILogger)]
     class MyLogger : ILogger
     {
        [ImportingConstructor]
        public MyLogger(ISettings settings)
        {
        }
     }