16

特定の winsor-container で (デフォルトの) 実装を再定義したいと考えています。それが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がまだサービスを定義していない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();
    }
}
于 2010-08-21T08:39:10.757 に答える
0

はい、サービスのデフォルトの実装を再定義します。あなたはなぜこれをやっているのですか?再定義するのではなく、そもそもこれを登録してみませんか?

より多くのコンテキストを提供できますか?

于 2009-03-19T12:31:45.833 に答える