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 代码中似乎没有发生这种情况。
所以,对于这个问题...
如何让系统:
- 将
IConfig
注入到我的 reader classes 的构造函数中
- 强制 readers 集合恢复为我导出的 reader classes 原样。
我从未将 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
}
}
我有几个 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 代码中似乎没有发生这种情况。
所以,对于这个问题...
如何让系统:
- 将
IConfig
注入到我的 reader classes 的构造函数中
- 强制 readers 集合恢复为我导出的 reader classes 原样。
我从未将 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
}
}