MEF ComposeParts 未创建 类 具有需要注入的参数

MEF ComposeParts not creating classes that have Parameters that need to be Injected

我有几个 class 与此类似...

[Export(typeof (IMessageReader))]
public class DropboxFolderWatchMessageReader : IMessageReader

和这样的消息 reader class ...

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;
    }
}

我的工作单位是这样做的...

public IEnumerable<Message> FetchMessages()
{
    var reader = new MessageReader();
    MefComposer.Container.ComposeParts(reader);

    var messages = reader.GetMessages();
    var result = AddMessages(messages);

    return result;
}

在我的第一次迭代中,仅此而已,而且一切正常。

然后我必须得到消息 readers 来做更多的事情,这反过来意味着我需要将参数传递给构造函数...

public DropboxFolderWatchMessageReader(IConfig config)
{
    //...
}

当我尝试 运行 我的代码时,我收到一条消息,大意是我的 reader 无法创建,因为它们不再具有默认构造函数。我需要用 [ImportingConstructorAttribute] 装饰一个构造函数。所以,我补充说...

[System.ComponentModel.Composition.ImportingConstructorAttribute]
public DropboxFolderWatchMessageReader(IConfig config)
{
    //...
}

现在它编译并且 运行 没问题,但是 readers 集合总是空的。

在其他 class 中,在其构造函数中采用相同类型的对象具有由 Unity 注入的对象。我的 MEF 代码中似乎没有发生这种情况。

所以,对于这个问题...

如何让系统:

我从未将 ImportingConstructor 与字段级导入混合使用,尽管我认为它会起作用。 (只要你不需要构造函数中的字段或从构造函数调用的方法。)

我的一般建议是不要混合,生成如下构造函数:

[System.ComponentModel.Composition.ImportingConstructorAttribute]
public DropboxFolderWatchMessageReader(IConfig config, [ImportMany(typeof(IMessageReader))]
IEnumerable<IMessageReader> readers;)
{
    this.reader = readers.ToList();
    // rest of body
}

如果您需要混合方法,但需要在对象初始化时使用读取器,您可以像这样实现接口 IPartImportsSatisfiedNotification

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
    }
}