1

私は Castle n00b で、Castle Windsor の Fluent API を使用して、命名規則に基づいて実装をサービスに自動登録しています (ISomething は Something によって実装されています)。私がサポートしたかったことの 1 つは、自動登録が個別の dll にある依存関係を取得し、それらも自動登録することです。

つまり、IFoo は Foo (どちらも Foo.dll 内) によって実装され、Foo は Bar.dll 内の IBar に依存します。

自動登録を実際に実行するために、次のコードを記述しました。うまくいきそうですが、自分で頑張りすぎたのか気になります。同じことを達成するためのより簡単な方法はありますか?

private static void EnsureRegistered(Type t, IWindsorContainer container)
    {
        if (!container.Kernel.HasComponent(t) && (!(t.Assembly.FullName.StartsWith("System") || t.Assembly.FullName.StartsWith("mscorlib"))))
        {
            bool registeredAtLeastOneComponent = false;

            container.Register(AllTypes.Pick().
                   FromAssembly(t.Assembly).If(delegate(Type t2)
                       {
                           //auto-registers all types that implement an interface where
                           //the name of the interface is the same as the class, minus the 'I'
                           //ex: EchoService is auto-registered as handler of IEchoService
                           Type[] interfaces = t2.GetInterfaces();
                           bool shouldRegister = false;
                           foreach(Type interfaceType in interfaces)
                           {
                               shouldRegister = t2.Name.Equals(interfaceType.Name.Substring(1))
                                                     && (!container.Kernel.HasComponent(interfaceType));
                               registeredAtLeastOneComponent = registeredAtLeastOneComponent || shouldRegister;
                               if (shouldRegister)
                                   break;
                           }
                           return shouldRegister;

                       }).WithService.Select(delegate(Type type, Type baseType)
                         {
                             Type serviceType = null;
                             Type[] interfaces = type.GetInterfaces();
                             foreach(Type interfaceType in interfaces)
                             {
                                 if (!type.Name.Equals(interfaceType.Name.Substring(1))) continue;
                                 serviceType = interfaceType;
                                 break;
                             }

                             return new Type[] {serviceType};

                         }));

            if (!registeredAtLeastOneComponent)
                return;

            //for each of the items in the graph, if they have see if they have dependencies
            //in other assemblies that aren't registered, register those dependencies as well
            foreach(GraphNode registered in container.Kernel.GraphNodes)
            {
               if (!(registered is Castle.Core.ComponentModel))
                    continue;

               Castle.Core.ComponentModel registeredComponent = registered as Castle.Core.ComponentModel;

               foreach(ConstructorCandidate constructor in registeredComponent.Constructors)
               {
                   foreach(DependencyModel dep in constructor.Dependencies)
                   {
                       EnsureRegistered(dep.TargetType, container);
                   }
               }
            }
        }
    }
4

2 に答える 2

2

コンポーネントをどのように構造化し、名前を付けるかに大きく依存します...いくつかの単純な規則(つまり、「MyApp.Services」名前空間の下のすべてのコンポーネントサービスと「MyApp.Services.Impl」の下のそれらの実装)を維持すれば、これを劇的に減らすことができます複雑さ (たとえば、 ayende1ayende2を参照)。

また、IMOの有用性は、最も単純なケースを除いてかなり制限されています...たとえば、サービスインターフェイスなしで登録したいサービス、構成が必要なサービス、サービスのオーバーライドなどが必要な場合、これは機能しません.

于 2009-03-12T19:23:07.943 に答える
0

これがあなたの質問に答えるかどうかはわかりませんが、これはサービスを自動登録するために行ったことです。

        // Auto-Register Services as Singletons
        container.Register(
            AllTypes.FromAssembly(typeof(BaseService).Assembly).Pick()
                    .WithService.DefaultInterfaces()
                    .Configure(s => s.LifestyleSingleton()));

すべてのサービスは、BaseService (抽象クラス) と Interface - IService から継承します。これにより、Concrete Service クラスがそのインターフェイスに自動的にバインドされ、コンテナで使用できるようになります。

于 2013-01-31T15:54:51.763 に答える