我想在给定的windsor容器中重新定义(默认)实现。那是OverWrite的用途吗?但是不起作用。
container.Register(
Component.For<IServiceOperationAuthorization>()
.OverWrite()
.Instance(_authorization)
);
还有其他想法吗?
欢呼声, 拉斯
答案 0 :(得分:12)
您可以在需要覆盖默认实现的位置执行此操作。这是我们的集成测试的一个例子。现在两个实现都已注册,但您的代码将使用默认的代码,即您刚刚注册的代码。像炸弹一样工作,对应用程序的其余部分没有任何影响:
var sendMailStub = MockRepository.GenerateStub<ISendMail>();
_container.Register(
Component
.For<ISendMail>()
.Instance(sendMailStub)
.IsDefault()
);
答案 1 :(得分:9)
我同意Krzysztof这通常不是一个好主意......但是据我所知,OverWrite()不会覆盖默认组件,它只会覆盖属性定义的生活方式(即[Singleton])。
如果要替换组件,可以使用container.Kernel.RemoveComponent(string key)
,然后注册新组件。
Here's an example此 有意义。
答案 2 :(得分:3)
这可能是通过使用装饰器设置容器可以更好地解决的问题,您可以在其中显式更改装饰器指向调用的实现...特别是如果您要替换现有的实现已经注入了组件(即单体),这些组件可能在您的应用生命周期中存在。
真正需要更多关于你想要实现的目标的背景知识。
Here is more information about registering Decorators with Windsor
答案 3 :(得分:3)
我需要在集成测试套件中运行系统时切换组件实现,并且无法使用container.Kernel.RemoveComponent()。所以我最终得到了simple facility来照顾我。
答案 4 :(得分:1)
我实际上找到了一个很好的解决方案,我将xml文件用于覆盖并使用流畅的注册默认值。
fluent-API将impl的全名作为默认密钥。在运行中,我覆盖了xml-config的id,以模仿fluent-API的关键约定。
然后我在听Kernel.ComponentRegistered
时注册xml-config。
之后我只添加了xml尚未定义服务的code-config中的服务。
(不久之前,我只是复制粘贴了代码。希望你能让它运转起来。如果你发现任何问题,我会做编辑)
IList<Type> unnamedServices = new List<Type>();
IDictionary<string, Type> namedServices = new Dictionary<string, Type>();
ComponentDataDelegate registered = captureRegistrations(unnamedServices, namedServices);
container.Kernel.ComponentRegistered += registered;
// The method that captures the services
private static ComponentDataDelegate captureRegistrations(
IList<Type> unnamedServices, IDictionary<string, Type> namedServices)
{
return (key, handler) =>
{
if (handler.ComponentModel.Name == handler.ComponentModel.Implementation.FullName)
{
unnamedServices.Add(handler.Service);
}
else
{
namedServices.Add(key, handler.Service);
}
};
}
之后我在代码中注册服务之前,检查它们是否已经注册。我还创建了一个基类,使这更容易。这是一个应用程序配置:
public class ApplicationConfiguration : WindsorConfigurationSkeleton
{
internal static WindsorServiceLocator create()
{
var container = createWith(null, "components-config.xml", coreServices, caches, roles);
return new WindsorServiceLocator(container);
}
internal static IEnumerable<IRegistration> coreServices()
{
yield return Component.For<ISystemClock>()
.ImplementedBy<PreciseSystemClock>()
.Parameters(Parameter.ForKey("synchronizePeriodSeconds").Eq("10"))
.LifeStyle.Singleton;
yield return Component.For<IMailService>()
.ImplementedBy<MailQueueService>()
.LifeStyle.Singleton;
}
internal static IEnumerable<IRegistration> caches()
{
yield return Component.For<IDataCache<ServiceAttributes>>()
.ImplementedBy<NoDataCache<ServiceAttributes>>()
.LifeStyle.Singleton;
// ....
}
}
进行接线的基类: (记录来自Commons.Logging)
public class WindsorConfigurationSkeleton
{
private static readonly ILog _log = LogManager.GetLogger(
typeof(WindsorConfigurationSkeleton));
internal static IWindsorContainer createWith(
IRegistration[] customs, string configFile, params Func<IEnumerable<IRegistration>>[] methods)
{
IWindsorContainer container = new WindsorContainer();
BugFix.Kernel = container.Kernel;
container.AddFacility("factory.support", new FactorySupportFacility());
IList<Type> unnamedServices = new List<Type>();
IDictionary<string, Type> namedServices = new Dictionary<string, Type>();
ComponentDataDelegate registered = captureRegistrations(unnamedServices, namedServices);
container.Kernel.ComponentRegistered += registered;
if (customs != null)
{
container.Register(customs);
}
if (configFile != null)
{
tryAddXmlConfig(container, configFile);
}
container.Kernel.ComponentRegistered -= registered;
if (methods != null && methods.Length > 0)
{
container.Register(union(unnamedServices, namedServices, methods));
}
return container;
}
private static ComponentDataDelegate captureRegistrations(
IList<Type> unnamedServices, IDictionary<string, Type> namedServices)
{
return (key, handler) =>
{
if (handler.ComponentModel.Name == handler.ComponentModel.Implementation.FullName)
{
var text = unnamedServices.Contains(handler.Service) ? "another" : "default";
_log.Info(
m => m(
"Registered {2} service for {0} with {1}.",
handler.Service.GetDisplayName(),
handler.ComponentModel.Implementation.GetDisplayName(),
text
));
unnamedServices.Add(handler.Service);
}
else
{
var text = namedServices.ContainsKey(key) ? "another" : "default";
_log.Info(
m => m(
"Registered {3} service {0} with name '{1}' and {2}.",
handler.ComponentModel.Service,
handler.ComponentModel.Name,
handler.ComponentModel.Implementation.GetDisplayName(),
text
));
namedServices.Add(key, handler.Service);
}
};
}
protected static void tryAddXmlConfig(IWindsorContainer container, string filename)
{
var fi = Resources.GetFileFromResourceHierarchy(typeof(ApplicationContext).Namespace, filename);
if ( fi == null ) {
return;
}
var configFile = fi.FullName;
var xd = immitateFluentApiDefaultIdBehaviour(configFile);
container.Install(Configuration.FromXml(new StaticContentResource(xd.OuterXml)));
}
private static XmlDocument immitateFluentApiDefaultIdBehaviour(string configFile)
{
var xd = new XmlDocument();
xd.Load(configFile);
foreach (
XmlElement component in
xd.SelectNodes("/configuration/components/component[@type and (not(@id) or @id = '')]"))
{
var type = Type.GetType(component.GetAttribute("type"), true);
component.SetAttribute("id", type.FullName);
}
return xd;
}
private static IRegistration[] union(
IList<Type> unnamed, IDictionary<string, Type> named, params Func<IEnumerable<IRegistration>>[] methods)
{
var all = new List<IRegistration>();
foreach (var method in methods)
{
foreach (var registration in method())
{
var registrationType = registration.GetType();
if (registrationType.IsGenericTypeOf(typeof(ComponentRegistration<>)))
{
var componentType = registrationType.GetGenericArgumentsFor(typeof(ComponentRegistration<>))[0];
var name = (string)registrationType.GetProperty("Name").GetValue(registration, null);
if (name != null)
{
if (named.ContainsKey(name))
{
_log.Debug(
m => m("Skipped registering default named component {0}.", name));
continue;
}
}
else if (unnamed.Contains(componentType))
{
_log.Debug(
m => m("Skipped registering default component for type {0}.", componentType));
continue;
}
all.Add(registration);
}
else
{
all.Add(registration);
}
}
}
return all.ToArray();
}
}
答案 5 :(得分:0)
是的,它确实重新定义了服务的默认实现。你为什么这么做?为什么不首先注册这个,而不是重新定义它?
你能提供更多背景吗?