Как переписать компонент с замком Виндзор?

Я создал для этого решение в SQL Server 2005 и разместил его на своем веб-сайте: http://www.jessemclain.com/downloads/code/sql/fn_GetMChooseNCombos.sql.htm

Ниже приведен пример использования:

SELECT * FROM dbo.fn_GetMChooseNCombos('ABCD', 2, '')

результатов:

Word
----
AB
AC
AD
BC
BD
CD

(6 row(s) affected)

16
задан Lars Corneliussen 18 March 2009 в 13:55
поделиться

5 ответов

Я действительно нашел хорошее решение, в котором я комбинирую xml-файлы для переопределений и использую плавную регистрацию для значений по умолчанию.

Fluent-API принимает полное имя impl в качестве ключа по умолчанию. На лету я переопределяю идентификаторы xml-config, чтобы имитировать соглашения по клавишам 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;

        // ....
    }
}

Базовый класс, который выполняет подключение: (Запись из 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();
    }
}
1
ответ дан 30 November 2019 в 21:11
поделиться

Да, это действительно переопределяет реализацию по умолчанию сервиса. Почему Вы делаете это? Почему бы не зарегистрировать это во-первых, вместо того, чтобы переопределить его?

Вы могли обеспечить больше контекста?

0
ответ дан Krzysztof Kozmic 18 March 2009 в 23:55
поделиться
  • 1
    Может также использовать/D параметр командной строки NOMINMAX в файле проекта. Это - полезная альтернатива если Вы don' t имеют PCH' s. – MSalters 17 September 2011 в 23:34

Это было бы видом проблемы, которая могла бы быть лучше решена путем установки контейнера с декоратором, где можно явно изменить реализацию, декоратор направляет вызовы к... особенно, если Вы хотите заменить реализацию, что существующие компоненты (т.е. одиночные элементы) были введены, с которым мог бы существовать в течение времени жизни Вашего приложения.

Действительно потребность больше фона на том, чего Вы пытаетесь достигнуть.

<час>

Вот больше информации о регистрирующихся Декораторах с Виндзором .

3
ответ дан Mark Seemann 18 March 2009 в 23:55
поделиться
  • 1
    @Mehrdad: включая Windows заголовки является уже непортативным как есть. – André Caron 16 September 2011 в 19:54

Я соглашаюсь с Krzysztof, что это обычно - не хорошая идея... Однако насколько я могу сказать, что OverWrite () не перезаписывает компонент по умолчанию, он просто перезаписывает образ жизни, определенный атрибутом (т.е. [Singleton]).

, Если Вы хотите заменить компонент, можно использовать container.Kernel.RemoveComponent(string key) сопровождаемый регистрацией нового компонента.

Вот пример , где это делает , имеют смысл.

9
ответ дан Mauricio Scheffer 18 March 2009 в 23:55
поделиться

Мне нужно было переключить реализацию компонента при запуске системы в наборе интеграционных тестов, и я не смог использовать container.Kernel.RemoveComponent (). В итоге я получил простой объект , который позаботился об этом за меня.

3
ответ дан 30 November 2019 в 21:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: