Замок Виндзор и авторегистрация - PullRequest
1 голос
/ 12 марта 2009

Я - Castle n00b и использую API-интерфейс Fluent в Castle Windsor для автоматической регистрации реализаций в службах на основе соглашения об именах (ISomething реализован Something). Одна вещь, которую я хотел бы поддержать, - это автоматическая регистрация, чтобы получать зависимости, находящиеся в отдельных библиотеках, и автоматически регистрировать их.

Итак: IFoo реализуется Foo (как в Foo.dll), так и Foo зависит от IBar, который находится в Bar.dll.

У меня есть следующий код, написанный для автоматической регистрации. Кажется, это работает, но мне интересно, сделал ли я слишком много работы сам. Есть ли более простой способ сделать то же самое?

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);
                   }
               }
            }
        }
    }

Ответы [ 2 ]

2 голосов
/ 12 марта 2009

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

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

0 голосов
/ 31 января 2013

Не уверен, что это ответ на ваш вопрос, но это то, что я сделал для автоматической регистрации моих услуг.

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

Все мои сервисы наследуются от BaseService (абстрактный класс), а также от интерфейса - IService. Это автоматически связывает класс Concrete Service с его интерфейсом и делает его доступным для использования в контейнере.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...