MEF ComposeParts没有创建具有需要Injected参数的类

时间:2016-04-26 11:31:59

标签: c# inversion-of-control unity-container mef

我有几个与此相似的课程......

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

和这样的消息阅读器类......

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

在我的第一次迭代中,那就是它的全部内容,而且一切正常。

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

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

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

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

现在它编译并运行正常,但readers集合始终为空。

在其构造函数中采用相同类型的其他类中,Unity会注入对象。这似乎不会出现在我的MEF代码中。

那么,对于这个问题......

如何让系统进入:

  • IConfig注入我的读者类的构造函数
  • 强制读者集合回到使用我导出的读者类填充。

1 个答案:

答案 0 :(得分:1)

我从未将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
    }
}