Reputation: 1663
I have a couple of classes similar to this ...
[Export(typeof (IMessageReader))]
public class DropboxFolderWatchMessageReader : IMessageReader
and a message reader class like this ...
public class MessageReader
{
[ImportMany(typeof(IMessageReader))]
private List<IMessageReader> readers;
public List<Message> GetMessages()
{
var result = new List<Message>();
readers.ForEach(r => result.AddRange(r.GetMessages()));
return result;
}
}
My Unit of Work does this...
public IEnumerable<Message> FetchMessages()
{
var reader = new MessageReader();
MefComposer.Container.ComposeParts(reader);
var messages = reader.GetMessages();
var result = AddMessages(messages);
return result;
}
In my first iteration, that's all there was to it and it all worked just fine.
Then I had to get my message readers to do a bit more and that, in turn, mean I needed to pass parameters to the constructors...
public DropboxFolderWatchMessageReader(IConfig config)
{
//...
}
When I tried to run my code I got a message to the effect that my readers couldn't be created because they no longer had a default constructor. I needed to decorate a single constructor with the [ImportingConstructorAttribute]
. So, I added that...
[System.ComponentModel.Composition.ImportingConstructorAttribute]
public DropboxFolderWatchMessageReader(IConfig config)
{
//...
}
Now it compiles and runs OK, but the readers
collection is always empty.
In other classes that take the same type in their constructors have the object injected by Unity. This doesn't appear to be happening in my MEF code.
So, to the question...
How do I get the system to:
IConfig
in to the constructors of my reader classesUpvotes: 1
Views: 111
Reputation: 993
I've never mixed ImportingConstructor with field level imports although I would think it would work. (As long you you don't need the field in the constructor or a method called from the constructor.)
My general recommendation is not to mix, yielding a constructor like:
[System.ComponentModel.Composition.ImportingConstructorAttribute]
public DropboxFolderWatchMessageReader(IConfig config, [ImportMany(typeof(IMessageReader))]
IEnumerable<IMessageReader> readers;)
{
this.reader = readers.ToList();
// rest of body
}
If you need to mix the methods, but need to use readers at object initialization you can implement the interface IPartImportsSatisfiedNotification like so:
class DropboxFolderWatchMessageReader : IPartImportsSatisfiedNotification
{
[ImportMany(typeof(IMessageReader))]
private List<IMessageReader> readers;
[System.ComponentModel.Composition.ImportingConstructorAttribute]
public DropboxFolderWatchMessageReader(IConfig config)
{
// empty body. readers still null here
}
public void OnImportsSatisfied()
{
// old constructor body.
// it's safe to use readers here as all imports have been satisfied
}
}
Upvotes: 1