16

我想在给定的 Windsor 容器中重新定义(默认)实现。这就是 OverWrite 的用途吗?不过,这不起作用。

container.Register(
                    Component.For<IServiceOperationAuthorization>()
                            .OverWrite()
                            .Instance(_authorization)
                    );

还有其他想法吗?

干杯,拉斯

4

6 回答 6

13

您可以在需要覆盖默认实现的地方非常简单地执行此操作。这是我们集成测试的一个例子。两种实现现在都已注册,但您的代码将使用默认的实现,即您刚刚注册的实现。像炸弹一样工作,对应用程序的其余部分没有任何影响:

        var sendMailStub = MockRepository.GenerateStub<ISendMail>();
        _container.Register(
            Component
                .For<ISendMail>()
                .Instance(sendMailStub)
                .IsDefault()
            );
于 2013-05-30T09:15:18.220 回答
10

我同意 Krzysztof 的观点,这通常不是一个好主意……但是据我所知,OverWrite() 不会覆盖默认组件,它只会覆盖由属性定义的生活方式(即 [Singleton])。

如果要更换一个组件,可以使用container.Kernel.RemoveComponent(string key)后跟注册的新组件。

一个有意义的例子。

于 2009-03-20T00:25:24.487 回答
3

这可能是通过使用装饰器设置容器可以更好地解决的问题,您可以在其中显式更改装饰器正在引导调用的实现......特别是如果您想替换现有组件的实现(即单例)已被注入,它可能在您的应用程序的生命周期中存在。

真的需要更多关于你想要达到的目标的背景。


这是有关在 Windsor 注册装饰器的更多信息

于 2009-03-21T22:13:44.600 回答
3

在集成测试套件中运行系统时,我需要切换组件实现并且无法使用 container.Kernel.RemoveComponent()。所以我最终得到了一个简单的设施来为我处理这个问题。

于 2009-10-28T21:00:42.030 回答
1

我实际上找到了一个很好的解决方案,我将 xml 文件结合起来进行覆盖,并使用流利的注册作为默认值。

fluent-API 将 impl 的全名作为默认键。在运行中,我覆盖了 xml-config 的 id 以模仿 fluent-API 的键约定。

然后我一边听一边注册 xml-config 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;

        // ....
    }
}

进行接线的基类:(Logging 来自 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();
    }
}
于 2010-08-21T08:39:10.757 回答
0

是的,它确实重新定义了服务的默认实现。你为什么这么做?为什么不首先注册它,而不是重新定义它?

你能提供更多的上下文吗?

于 2009-03-19T12:31:45.833 回答