在 StructureMap 中注册复合模式

Register composite pattern in StructureMap

在我的项目中,我使用复合模式,我想使用 StructureMap 注册和解析此层次结构。 代码看起来像这样

interface IFoo
{
    void Do();
}

class Foo1 : IFoo
{
    public void Do()
    {
        Console.WriteLine("Foo1");
    }
}

class Foo2 : IFoo
{
    public void Do()
    {
        Console.WriteLine("Foo2");
    }
}

class CompositeFoo : IFoo
{
    private readonly IEnumerable<IFoo> foos;

    public CompositeFoo(IEnumerable<IFoo> foos)
    {
        this.foos = foos;
    }

    public void Do()
    {
        foreach (var foo in this.foos)
        {
            foo.Do();
        }
    }
}

class Bootstrapper
{
    public static void Run()
    {
        var container = new Container(c =>
        {
            c.For<IFoo>().Add<Foo1>();
            c.For<IFoo>().Add<Foo2>();
            c.For<IFoo>().Use<CompositeFoo>();

        });

        // throws exception
        var result = container.GetInstance<IFoo>();
        result.Do();
    }
}

指定代码抛出此异常

Bi-directional dependency relationship detected!
Check the StructureMap stacktrace below:
1.) Instance of IFoo (CompositeFoo)
2.) All registered children for IEnumerable<IFoo>
3.) Instance of IEnumerable<IFoo>
4.) new CompositeFoo(*Default of IEnumerable<IFoo>*)
5.) CompositeFoo
6.) Instance of IFoo (CompositeFoo)
7.) Container.GetInstance<IFoo>()

我在官方文档或互联网上的任何地方都找不到与此相关的任何内容。如果不手动指定所有可能的依赖项,这是完全可能的吗?

在我看来,您有两种选择:

  1. CompositeFoo 注册为 CompositeFoo 而不是 IFoo。然后请求 CompositeFoo.

    的实例
    cfg.For<IFoo>().Add<Foo1>();
    cfg.For<IFoo>().Add<Foo2>();
    cfg.ForConcreteType<CompositeFoo>();
    ...
    var result = container.GetInstance<CompositeFoo>();
    
  2. 为组合定义一个新接口。

    interface ICompositeFoo : IFoo {}
    class CompositeFoo : ICompositeFoo
    ...
    cfg.For<IFoo>().Add<Foo1>();
    cfg.For<IFoo>().Add<Foo2>();
    cfg.For<ICompositeFoo>().Use<CompositeFoo>();
    ...
    var foo = container.GetInstance<ICompositeFoo>();
    

在尝试使用策略或工厂 类 完成此操作后,我解雇了 StructureMap 以支持 Grace。在那里我可以使用以下代码轻松实例化复合对象

var container = new DependencyInjectionContainer();
container.Configure(c =>
{
     c.Export<Foo1>().As<IFoo>();
     c.Export<Foo2>().As<IFoo>();
     c.Export<CompositeFoo>().As<IFoo>();
});

var foo = container.Locate<IFoo>();
foo.Do();

结果如预期:

foo1
foo2

对我来说,StructureMap 的问题是它们不支持任何动态指定对象依赖关系的方式。如果我手动编写所有应该注入或解析所有实例(包括复合对象),我可以让它工作。我可能可以使用带有注入容器的策略并以这种方式指定依赖项,以某种方式使其成为可能,但在我看来这太老套了。