使用Castle Windsor创建具有循环关系的组件

时间:2012-01-31 23:19:11

标签: castle-windsor

我正在实现一个有限状态机,每个类代表一个状态。每个州知道它可以转换到哪些其他状态,这自然会导致循环关系。 (见State Design Pattern)。

对于这个简化示例,我创建了两个组件,其中第一个组件具有对第二个组件的引用,第二个组件具有对第一个组件的引用。

问题是Windsor框架正确设置了第一个创建组件的引用,但没有为第二个创建引用:

以下是两个组成部分:

// DefaultMouseHandler knows about NewLineMouseHandler
public class DefaultMouseHandler : MouseHandler
{
    public DefaultMouseHandler()
    {
    }

    public NewLineMouseHandler NewLineMouseHandler
    {
        get;
        set;
    }

    internal override MouseHandler LeftButtonDown(System.Windows.Input.MouseButtonEventArgs e)
    {
        return this.NewLineMouseHandler;
    }
}


// NewLineMouseHandler knows about DefaultMouseHandler
public class NewLineMouseHandler : MouseHandler
{
    public NewLineMouseHandler()
    {
    }

    public DefaultMouseHandler DefaultMouseHandler
    {
        get;
        set;
    }

    internal override MouseHandler LeftButtonUp(System.Windows.Input.MouseButtonEventArgs e)
    {
        return this.DefaultMouseHandler;
    }
}

然后我按如下方式注册组件:

_windsorContainer.Register(Classes.FromThisAssembly()
                                 .BasedOn<MouseHandler>()
                         );

但是当我第一次尝试创建DefaultMouseHandler

  • 构建DefaultMouseHandler
  • 构建NewLineMouseHandler
  • NewLineMouseHandler
  • 上设置了DefaultMouseHandler

DefaultMouseHandler未设置NewLineMouseHandler

这可以被视为温莎城堡的缺陷吗?

让两个组件相互引用的最佳方法是什么,两个组件都不知道Windsor容器?

2 个答案:

答案 0 :(得分:0)

我同意@sll这可能表明设计可以改进。另一方面,有正当理由做你正在做的事情。如果您永远不会解析NewLineMouseHandler并且它仅用作NewLineMouseHandler的依赖项,那么只需手动设置依赖项:

windsor.Register(Classes.FromThisAssembly()
                    .BasedOn<MouseHandler>()
                    .ConfigureFor<NewLineMouseHandler>(
                        h => h.OnCreate(
                            c =>
                                {
                                    var @default = (DefaultMouseHandler) c;
                                    @default.NewLineMouseHandler.DefaultMouseHandler = @default;
                                }))
    );

答案 1 :(得分:0)

我提出的解决方案是使用TypedFactoryFacility

这允许在需要时创建对象,因此我们不会在初始化时将它们的复杂性全部依赖于彼此。

public interface IMouseHandlerFactory
{
    T CreateHandler<T>() where T : MouseHandler;
}

// In the registration code
_windsorContainer.AddFacility<TypedFactoryFacility>();
_windsorContainer.Register(Classes.FromThisAssembly()
                               .BasedOn<MouseHandler>(),
                           Component.For<IMouseHandlerFactory>()
                                    .AsFactory()
                          );

// The base class
public abstract class MouseHandler
{
    // Every mousehandler will create at least one other mouse handler
    // This is the factory that they will use for mouse handling creation
    // The property will be automatically set by the DI container
    public IMouseHandlerFactory MouseHandlerFactory { get; set; }

    // Methods the concrete implementations will override
    internal virtual MouseHandler LeftButtonDown(MouseButtonEventArgs e) { return this; }
    internal virtual MouseHandler LeftButtonUp(MouseButtonEventArgs e) { return this; }
}   

// The implementations
public class DefaultMouseHandler : MouseHandler
{
    internal override MouseHandler LeftButtonDown(MouseButtonEventArgs e)
    {
        return this.MouseHandlerFactory.CreateHandler<NewLineMouseHandler>();
    }
}

public class NewLineMouseHandler : MouseHandler
{
    internal override MouseHandler LeftButtonUp(MouseButtonEventArgs e)
    {
        return this.MouseHandlerFactory.CreateHandler<DefaultMouseHandler>();
    }
}