Use ImportMany on a Field in a class with an ImportingConstructor

Aug 13, 2012 at 7:01 PM

I have a situation in which I have an ImportingConstructor: 

[ImportingConstructor]
 public Foo(ISomething somethings, ISomethingElse somethingelses) {}

I also want a collection of another type but don't need it in the constructor. So I added it as a property import.

[ImportMany]
IEnumerable<ISomethingEntirelyDifferent> _somethingentirelydifferents;

_somethingentirelydifferents is always null; what can I do to solve this?

Aug 15, 2012 at 12:31 AM

Ensure you are calling

container.ComposeParts();

or possibly

container.SatisfyImports();

(not sure about the latter)

 

Aug 16, 2012 at 11:55 PM

Isn't that presumptive that the container will be there to compose or satisfy? 

I ended up removing this entirely and going with a different solution that supercedes the question as posted.  I'm curious about your solution, though.

Aug 17, 2012 at 12:48 AM

If you're using the Microsoft.Composition package, field exports like the one above aren't supported at all; you'll need to use a public property with a getter/setter:

[ImportMany]
public IEnumerable<ISomethingEntirelyDifferent> Somethingentirelydifferents { get; set; }

Cheers,
Nick 

Aug 17, 2012 at 12:51 AM

Ha! I totally missed the private scoping.

Aug 17, 2012 at 1:40 AM
Edited Aug 17, 2012 at 1:45 AM

I have not managed to get [ImportMany] to work for me without using "full" MEF as opposed to Microsoft.Composition.

using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;

public void Foo()
{
    DirectoryCatalog catalog = new DirectoryCatalog("bin");
    var container = new CompositionContainer(catalog);
    container.ComposeParts(this);
}

[ImportMany]
public IEnumerable Bars { get; set; }

Got some help recently from Nick, but honestly I'm still a little hazy. I've ended up doing the following hack:

ContainerConfiguration config = new ContainerConfiguration();

string[] plugins = Directory.GetFiles("path/to/plugins", "*.dll");

foreach (var file in plugins)
{
    var name = AssemblyName.GetAssemblyName(file);
    var assembly = Assembly.Load(name);
    config.WithAssembly(assembly);
}

using (CompositionHost container = config.CreateContainer())
{
    _plugins = container.GetExports();
}

So hey Nick - how does composition get set in motion with Microsoft.Composition?

Aug 17, 2012 at 12:10 PM

Hi James,

If you have:

using Microsoft.Composition;

in your source file, you should be able to use:

container.SatisfyImports(this);

with your second example, along with [ImportMany] exactly as you would in the "full" MEF (SatisfyImports is an extension method).

Have you tried this, and if so, what result do you get?

Cheers,
Nick 

Aug 17, 2012 at 5:36 PM

Argh - there's really so much to this MEF stuff and, though I've been buried in it for weeks now, I still feel overwhelmed. I had not included using Microsoft.Composition; so had not seen the extension method at all. Unfortunately, I'm using a static class to allow me to share my plugin collection between a number of classes and so (I think) the [ImportMany] attribute will not be of use.

I'm really wishing I could have had a chance to have a chat with you about my solution before you left Seattle (I'm just a few hours north) - I feel like there's a simple and 'correct' way to do what I want, but I'm just not getting it. I'd ask to send you the basics of my framework for your evaluation and recommendation but, since you're no longer on the clock with this stuff, is there someone at MS I could/should talk to?

@MattR1031 - sorry for hijacking! ;)

Coordinator
Aug 17, 2012 at 6:31 PM

James, shoot me an email and I can help out, if not I can loop in the right people who can. (Nick we will find you J ).

Cheers

-alok

From: jamesfernandes [email removed]
Sent: Friday, August 17, 2012 9:36 AM
To: Alok Shriram
Subject: Re: Use ImportMany on a Field in a class with an ImportingConstructor [MEF:391394]

From: jamesfernandes

Argh - there's really so much to this MEF stuff and, though I've been buried in it for weeks now, I still feel overwhelmed. I had not included using Microsoft.Composition; so had not seen the extension method at all. Unfortunately, I'm using a static class to allow me to share my plugin collection between a number of classes and so (I think) the [ImportMany] attribute will not be of use.

I'm really wishing I could have had a chance to have a chat with you about my solution before you left Seattle (I'm just a few hours north) - I feel like there's a simple and 'correct' way to do what I want, but I'm just not getting it. I'd ask to send you the basics of my framework for your evaluation and recommendation but, since you're no longer on the clock with this stuff, is there someone at MS I could/should talk to?

@MattR1031 - sorry for hijacking! ;)

Aug 17, 2012 at 7:25 PM

Thanks Alok - sent you a long and convoluted email. ;)