结构图,带有插件列表的构造函数

时间:2009-09-17 10:17:21

标签: c# .net structuremap

我有一个像这样的界面

public interface IWriter
{
  ...
}

和一个班级

public class WriterMerger
{
  public WriterMerger(IEnumerable<IWriter> writers)
  ...
}

我希望structuremap使用所有已注册的IWriter来填充WriterMerger上的构造函数参数。 我用

注册了不同的作家
StructureMap.ObjectFactory.Initialize(x =>
{
  x.ForRequestedType<IWriter>().AddConcreteType<MemoryWriter>();
  x.ForRequestedType<IWriter>().AddConcreteType<FlatFileWriter>();
  x.ForRequestedType<IWriter>().AddConcreteType<DbWriter>();
}

然而打电话

ObjectFactory.CreateInstance<WriterMerger>();

返回异常“没有为PluginFamily定义的默认实例System.Collections.Generic.IEnumerable`1 [[IWriter ..]]”(已修改类名)

自动执行此操作的任何技巧?或者我是否必须制作自定义工厂方法?

4 个答案:

答案 0 :(得分:18)

实际上这可以在不改变构造函数的情况下完成

将容器配置更改为:

StructureMap.ObjectFactory.Initialize(x =>
{
    x.Scan(scan =>
    {
        scan.TheCallingAssembly();
        scan.AddAllTypesOf<IWriter>();
    });
    x.ForRequestedType<IEnumerable<IWriter>>()
        .TheDefault.Is.ConstructedBy(x => ObjectFactory.GetAllInstances<IWriter>());
});

答案 1 :(得分:10)

如果希望注入类型的所有具体实例,则必须将参数声明为数组。您可以通过将构造函数更改为:

来解决问题
public WriterMerger(IWriter[] writers)

请注意,像ReSharper这样的代码清理工具可能会突出显示构造函数中的数组,并建议您使用IEnumerable替换它,如果这是WriterMerger所需的全部内容。但是,这些工具不了解StructureMap使用数组的要求,因此您必须忽略它。

您可能也有兴趣知道您可以自动注册所有IWriters,而不是明确列出它们。只需将容器配置更改为:

StructureMap.ObjectFactory.Initialize(x =>
{
    x.Scan(scan =>
    {
        scan.TheCallingAssembly();
        scan.AddAllTypesOf<IWriter>();
    });
});

有许多不同的扫描选项,允许您扫描不同的程序集,排除某些类型等。

答案 2 :(得分:2)

我复制了你的问题,我相信如果你改变你的IWriter消费类,让你的代码可以使用一个带有IWriter数组的ctor。

public class WriterMerger {  public WriterMerger(IWriter[] writers) }

Josh正确地建议使用StructureMap注册所有类型的IWriter的更好方法。扫描仪FTW。

答案 3 :(得分:1)

我认为这告诉你的是你需要将其中一个IWriters定义为默认值。想象一下,另一个类有以下构造函数:

public class Test{
  public Test(IWriter writer){}
}

如果没有默认的IWriter,它就不知道要分配哪个编写器。因此,您可能需要说明哪个是默认值,即使您从未使用过它。看这篇文章:

What's the difference between AddConcreteType and TheDefaultIsConcreteType in StructureMap?