C#、Castle Windsor 和复合设计模式
C#, Castle Windsor and The Composite design pattern
我使用复合模式为几个独立平台设计了遥测记录器
public interface ILogger
{
void Log();
}
public class A : ILogger
{
public void Log(...);
}
public class B : ILogger
{
public void Log(...);
}
public class Many : ILogger
{
private readonly List<ILogger> m_loggers;
public Many(IEnumerable<ILogger> loggers)
{
m_loggers = loggers.ToList();
}
public void Log()
{
m_loggers.ForEach(c => c.Log());
}
}
现在我希望能够从 Windsor 容器中获取 "Many" 的实例
但遇到了一些问题:
如果所有 ILogger 都在容器中,我如何确保我得到 "Many" 实现而不是 "A" 或 "B"?
我试着按照这个例子
Castle Windsor: How do I inject all implementations of interface into a ctor?
并使用 container.Kernel.Resolver.AddSubResolver(new
CollectionResolver(container.Kernel));
注册一个 class 与 IEnumerable 依赖关系,但如果
class 也实现了 IComponent 不会创建一个循环
依赖性 ?
我正在尝试的可能吗?
是否可以在容器注册中使用工厂方法?
var container = new Castle.Windsor.WindsorContainer();
container.Register(Component.For<A>());
container.Register(Component.For<B>());
container.Register(Component.For<ILogger>()
.UsingFactoryMethod(k => new Many(k.Resolve<A>(), k.Resolve<B>())));
var logger = container.Resolve<ILogger>();
更改后:
public Many(params ILogger [] loggers)
{
m_loggers = loggers.ToList();
}
我对 Windsor Container 的有限了解使我想到了这一点,沿着使用工厂初始化对象的相同思路可能对此有所改进。重要的是配置在容器内(即使有点冗长)
首先这是复合设计模式而不是组件。
在您的案例中,您在 Castle Windsor 中执行此操作的方式应该如下所示
container.Kernel.Resolver.AddSubResolver(new CollectionResolver(container.Kernel));
container.Register(Component.For<ILogger>().ImplementedBy<Many>());
container.Register(Component.For<ILogger>().ImplementedBy<A>());
container.Register(Component.For<ILogger>().ImplementedBy<B>());
这是可行的,因为 Castle Windsor 对 Composite 或 Decorator 等模式有内部理解,因此在这种情况下不会创建循环依赖。请记住,在这种情况下,注册顺序很重要。
可以找到有关在 Castle Windsor 中注册不同模式的更多信息 here。
我使用复合模式为几个独立平台设计了遥测记录器
public interface ILogger
{
void Log();
}
public class A : ILogger
{
public void Log(...);
}
public class B : ILogger
{
public void Log(...);
}
public class Many : ILogger
{
private readonly List<ILogger> m_loggers;
public Many(IEnumerable<ILogger> loggers)
{
m_loggers = loggers.ToList();
}
public void Log()
{
m_loggers.ForEach(c => c.Log());
}
}
现在我希望能够从 Windsor 容器中获取 "Many" 的实例 但遇到了一些问题:
如果所有 ILogger 都在容器中,我如何确保我得到 "Many" 实现而不是 "A" 或 "B"?
我试着按照这个例子 Castle Windsor: How do I inject all implementations of interface into a ctor? 并使用
container.Kernel.Resolver.AddSubResolver(new CollectionResolver(container.Kernel));
注册一个 class 与 IEnumerable 依赖关系,但如果 class 也实现了 IComponent 不会创建一个循环 依赖性 ?
我正在尝试的可能吗?
是否可以在容器注册中使用工厂方法?
var container = new Castle.Windsor.WindsorContainer();
container.Register(Component.For<A>());
container.Register(Component.For<B>());
container.Register(Component.For<ILogger>()
.UsingFactoryMethod(k => new Many(k.Resolve<A>(), k.Resolve<B>())));
var logger = container.Resolve<ILogger>();
更改后:
public Many(params ILogger [] loggers)
{
m_loggers = loggers.ToList();
}
我对 Windsor Container 的有限了解使我想到了这一点,沿着使用工厂初始化对象的相同思路可能对此有所改进。重要的是配置在容器内(即使有点冗长)
首先这是复合设计模式而不是组件。
在您的案例中,您在 Castle Windsor 中执行此操作的方式应该如下所示
container.Kernel.Resolver.AddSubResolver(new CollectionResolver(container.Kernel));
container.Register(Component.For<ILogger>().ImplementedBy<Many>());
container.Register(Component.For<ILogger>().ImplementedBy<A>());
container.Register(Component.For<ILogger>().ImplementedBy<B>());
这是可行的,因为 Castle Windsor 对 Composite 或 Decorator 等模式有内部理解,因此在这种情况下不会创建循环依赖。请记住,在这种情况下,注册顺序很重要。
可以找到有关在 Castle Windsor 中注册不同模式的更多信息 here。