views:

878

answers:

3

In my MEF usage, I have a bunch of imports that I want to make available in many other parts of my code. Something like:

[Export (typeof (IBarProvider))]
class MyBarFactory : IBarPovider
{
 [Import]
 public IFoo1Service IFoo1Service { get; set; }

 [Import]
 public IFoo2Service IFoo2Service { get; set; }

 [Import]
 public IFoo3Service IFoo3Service { get; set; }

 [Import]
 public IFoo4Service IFoo4Service { get; set; }

 [Import]
 public IFoo5Service IFoo5Service { get; set; }

 public IBar CreateBar()
 {
  return new BarImplementation(/* want to pass the imported services here */);
 }
}

class BarImplementation : IBar
{
 readonly zib zib;

 public BarImplementation(/* ... */)
 {
  this.zib = new Zib(/* pass services here, too */);
 }
}

I could pass each imported service as an individual parameter, but it's a lot of boring code. There's gotta be something better. Any ideas?

A: 

I thought about making an interface to provide these services:

partial class BarImplementation
{
 public IRequiredServices
 {

  public IFoo1Service IFoo1Service { get; set; }
  public IFoo2Service IFoo2Service { get; set; } 
  public IFoo3Service IFoo3Service { get; set; }   
  public IFoo4Service IFoo4Service { get; set; }  
  public IFoo5Service IFoo5Service { get; set; }
 }
}

Then MyBarFactory implements BarImplementation : BarImplementation.IRequiredServices. That's easy to write, but then, how do I pass them down to Zib? I don't want to couple Zib to its consumer that way.

Jay Bazuzi
A: 

I could make IImports an interface that contains all the services I import, pass that around everywhere, and then classes can use or not use whichever they like. But that couples all the classes toegether.

Jay Bazuzi
This is essentially the route that I went down. All of my modules have an IHost property that I set once I've loaded them. IHost can then have a list of loaded modules...
Tim
+1  A: 

I'm not entirely sure this answers your question but have you considered using the constructor injection yet?

class BarImplementation : IBar
{
    [ImportingConstructor]
    public BarImplementation(IFoo1Service foo1, IFoo2Service foo2, ...) { }
}

By marking your constructor with the ImportingConstructor attribute it will essentially make all the parameters of that constructor required imports.

Wes Haggard
That's interesting.
Jay Bazuzi