如何覆盖与温莎城堡的成分?
-
20-08-2019 - |
题
我要重新定义在给定的温莎容器的(默认)实现。难道这就是改写为?不工作,虽然。
container.Register(
Component.For<IServiceOperationAuthorization>()
.OverWrite()
.Instance(_authorization)
);
任何其他的想法?
欢呼声, 拉斯
解决方案 5
其实,我找到了一个很好的解决方案,我结合XML的文件覆盖,并使用默认流利的注册。
在流利-API需要IMPL作为默认密钥的全名。在飞行中我重写XML的配置的ID的模仿流畅-API的关键的约定。
然后我注册XML-配置而我听听Kernel.ComponentRegistered
。
然后我只从其中XML尚未定义的服务的代码的配置添加服务。
(这是前一段时间,我只是复制粘贴代码。希望你得到它的工作。如果你发现任何问题,我会做修改)的
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();
}
}
其他提示
您可以非常简单地做到这一点,你需要重写默认实现的地方。这是我们的集成测试的例子。两种实现,现在注册,但你的代码将使用默认的,这是你刚注册了一个。就像一个炸弹和不具有对应用程序的其余部分任何影响:
var sendMailStub = MockRepository.GenerateStub<ISendMail>();
_container.Register(
Component
.For<ISendMail>()
.Instance(sendMailStub)
.IsDefault()
);
我与克日什托夫·同意,这通常不是个好主意......但据我可以告诉覆盖()不会覆盖默认组件,它只是覆盖(即[辛格尔顿])的属性定义的生活方式。
如果要替换的组件,则可以使用container.Kernel.RemoveComponent(string key)
后跟新组件的注册。
下面是一个例子,其中的这< EM>确实意义。
这将是这类问题可能是由与装饰,在那里你可以明确地改变装饰是指导调用执行设置的容器进行了较好地解决了......特别是如果你要替换现有的执行情况组分(即单件)被注射,其可能存在于应用程序的生命周期。
真的需要你想达到什么更多的背景。
是,它并重新定义的服务的默认的实现。你为什么这么做?为什么在第一个地方不注册此,代替重新定义它?
你能否提供更多的背景?