Recommended pattern for defered composition

Dec 3, 2008 at 9:10 PM
I was wondering if there are any best-practises or recommended patterns when you need to compose something after application startup. For example if you have a winform based application you may build the catalogs and compose the container at application startup, but what if you for example need to create an instance the class Foo as the result of a button click and Foo in turn had some Imports? Then you'd need to compose the instance of Foo inside of the click handler for the button.

Is using a shared container, in for example a static member, and calling the compose method on it after the instance of Foo has been created the best option? How would this impact performance? Wouldn it recompose the entire application then? Here is a short example, of what I mean, in the form of a Console Application

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Reflection;

class Program
{
 static void Main()
 {
  Program app =
   new Program();
  app.Compose();

  // Imagine this line happens at an unknown time,
  // perhaps in the click event of a button.
  Foo f = new Foo();

  Console.WriteLine("Done! Press any key to quit.");
  Console.ReadLine();
 }
 
 void Compose()
 {
  var catalog =
   new AggregatingComposablePartCatalog();
  catalog.Catalogs.Add(new AttributedAssemblyPartCatalog(Assembly.GetExecutingAssembly()));

  this.Container =
   new CompositionContainer(catalog);
  this.Container.AddPart(this);
  this.Container.Compose();
 }

 public CompositionContainer Container { get; set; }
}

[ContractType]
public interface IBar
{
}

[Export(typeof(IBar))]
public class NullBar : IBar
{
}

/// <summary>
/// This class is instanciated after the initial composition has occured
/// </summary>
public class Foo
{
 [Import(typeof(IBar))]
 public IEnumerable<Export<IBar>> Bar { get; set; }
}

Developer
Dec 3, 2008 at 11:46 PM
The simplest way to do this is by importing an Export<Foo>, which is basically a lazy initialized version of Foo (with metadata if any exists). As part of the lazy initialization of Foo it will be composed. So in your form just do something like:

[Import]
Export<Foo> LazyFoo { get; set; }

... // When you want to activate it do something like:
LazyFoo.GetExportedObject();

Hope that helps,
Wes
Dec 4, 2008 at 5:57 AM
Yeah, however this isn't always a pattern which is always applicable. For example imagine something like this

public abstract class ProviderBase
{
    public abstract void Execute();
}

public class MefDrivenProvider : ProviderBase
{
   [Import(typeof(IBar))]
   private IEnumerable<Export<IBar>> Bars { get; set; }

   public override void Execute()
   {
        foreach(Export<IBar> bar in this.Bars)
        {
            bar.GetExportedObject().SomeMethod();
        }
   }  
}

public class NullProvider : ProviderBase
{
   public override void Execute()
   {
   }  
}

public class ProviderEngine
{
    public List<ProviderBase> Providers { get; set; }

    public void Execute()
    {
        foreach(ProviderBase provider in this.Providers
       {
              provider.Execute();
       }
    }  
}


and then using it

ProviderEngine engine = new ProviderEngine();
engine.Providers.Add(new MefDrivenProvider());
engine.Providers.Add(new NullProvider());
engine.Execute();


Here it's not really feasible to store a lazy version of the MefDrivenProvider. So it would either mean that the provider would somehow get access (perhaps having it stored in a static field) the container and compose itself or have the ProviderEngine compose each provider before calling the execute method.. the ideal would be to have the MefDrivenProvider be self composing, so what I have do so far is

public class MefDrivenProvider : ProviderBase
{
   public MefDrivenProvider()
   {
      ExportCollection<IBar> exports =
         Application.Container.GetExports<IBar>("TheContractName");

      this.Bars = exports.ToList<Export<IBar>>();
   }

   private List<Export<IBar>> Bars { get; set; }

   public override void Execute()
   {
        foreach(Export<IBar> bar in this.Bars)
        {
            // Inspect metadata and call the object if the metadata is valid
            bar.GetExportedObject().SomeMethod();
        }
   }  
}


This works and it enables me to compose instances of MefDrivenProvider on the fly - is this a pattern that you would concider "good practise" ?
Dec 4, 2008 at 8:20 PM

You may want to look at ICompositionService. You can have the container export ICS, and you can import it into your parts that need to create other parts. ICS has SatisfyImports / AddPart methods which you could use to either directly have your Provider composed (and not get added to the container), or you can add it to the container.

From: TheCodeJunkie [mailto:notifications@codeplex.com]
Sent: Wednesday, December 03, 2008 10:57 PM
To: Glenn Block
Subject: Re: Recommended pattern for defered composition [MEF:41424]

From: TheCodeJunkie

Yeah, however this isn't always a pattern which is always applicable. For example imagine something like this

public abstract class ProviderBase
{
public abstract void Execute();
}

public class MefDrivenProvider : ProviderBase
{
[Import(typeof(IBar))]
private IEnumerable<Export<IBar>> Bars { get; set; }

public override void Execute()
{
foreach(Export<IBar> bar in this.Bars)
{
bar.GetExportedObject().SomeMethod();
}
}
}

public class NullProvider : ProviderBase
{
public override void Execute()
{
}
}

public class ProviderEngine
{
public List<ProviderBase> Providers { get; set; }

public void Execute()
{
foreach(ProviderBase provider in this.Providers
{
provider.Execute();
}
}
}


and then using it

ProviderEngine engine = new ProviderEngine();
engine.Providers.Add(new MefDrivenProvider());
engine.Providers.Add(new NullProvider());
engine.Execute();


Here it's not really feasible to store a lazy version of the MefDrivenProvider. So it would either mean that the provider would somehow get access (perhaps having it stored in a static field) the container and compose itself or have the ProviderEngine compose each provider before calling the execute method.. the ideal would be to have the MefDrivenProvider be self composing, so what I have do so far is

public class MefDrivenProvider : ProviderBase
{
public MefDrivenProvider()
{
ExportCollection<IBar> exports =
Application.Container.GetExports<IBar>("TheContractName");

this.Bars = exports.ToList<Export<IBar>>();
}

private List<Export<IBar>> Bars { get; set; }

public override void Execute()
{
foreach(Export<IBar> bar in this.Bars)
{
// Inspect metadata and call the object if the metadata is valid
bar.GetExportedObject().SomeMethod();
}
}
}


This works and it enables me to compose instances of MefDrivenProvider on the fly - is this a pattern that you would concider "good practise" ?

Read the full discussion online.

To add a post to this discussion, reply to this email (MEF@discussions.codeplex.com)

To start a new discussion for this project, email MEF@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com

Developer
Dec 5, 2008 at 12:48 AM
While Glen is correct that ICompositionService or even ExportProvider could give you some benefits in dynamic scenarios I don't believe that will help with your case exactly.

Do you own the ProviderEngine type? If so then you can do something like:

[Export(typeof(ProviderBase))]
public class MefDrivenProvider : ProviderBase { }

[Export(typeof(ProviderBase))]
public class NullProvider : ProviderBase { }

[Export]
public class ProviderEngine
{
  public ExportCollection<ProviderBase> Providers { get; set; }

  public void Execute()
  {
    foreach(ProviderBase provider in this.Providers)
    {
      provider.GetExportedObject().Execute();
    }
  }
}

With host code that looks something like:

ProviderEngine engine = container.GetExportedObject<ProviderEngine>();
engine.Execute();

That would cause all the ProviderBases to be lazily activated and composed.

However if you don't own the ProviderEngine type then it becomes a little more difficult. In general it is not a great idea to have the Container stored in a static global place, it would techinically work but it has some drawbacks. One of which is that it now ties your MefDrivenProvider to a static place in memory and makes it's reuse very limited.

I would suggest doing one of the following:
1) Create the CompositionContainer locally in the MefDrivenProvider and use it do your composition.
2) Take a CompositionContainer or ExportProvider as a parameter to the constructor of your MefDrivenProvider so that whom ever creates it will have to provide it that dependency.

Hope that helps,
Wes

Dec 8, 2008 at 6:10 AM
@weshaggard, I was just writing an explination on why your example was a bad one becuase it would require design-time knowledge about all the providers that may be loaded at run-time but then I re-read it and noticed what you were doing. I like your example and I have a feeling that's the "MEF design pattern" that we'll have to wrap our heads around in order to integrate composition into applications.

That said I still think my example is a bit different than yours. Yours will load all providers into the ExportCollection and even though I could use a named contract or metadata filtering to determing exactly which providers will be loaded/executed in the loop it's still not the same as mine.

In my example i explicitly only add the providers I want/need to. Imagine a winform with 3 buttons on it

Button 1
- Add the NullProvider to the ProviderEngine

Button 2
- Add the MefDriverProvider to the ProviderEngine

Button 3
- Call the Execute method on the ProviderEngine


The buttons have no secuence restrictions on them and could be pressed in any order, not known at design-time. See how my scenario is different? Not only do I want defered composition of the MefDrivenProvider but I have logic, at run-time, which determins which Providers that will be available to the Engine when it's told to execute.

Question: Are the any solid documentation / example on the ExportProviders? I'd like to know more about them and start experimenting with creating my own