我正在实现一个有限状态机,每个类代表一个状态。每个州知道它可以转换到哪些其他状态,这自然会导致循环关系。 (见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容器?
答案 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>();
}
}