Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Dependency injection 温莎城堡与自动注册_Dependency Injection_Inversion Of Control_Castle Windsor - Fatal编程技术网

Dependency injection 温莎城堡与自动注册

Dependency injection 温莎城堡与自动注册,dependency-injection,inversion-of-control,castle-windsor,Dependency Injection,Inversion Of Control,Castle Windsor,我是Castle n00b,正在使用Castle Windsor中的Fluent API根据命名约定自动注册服务的实现(ISomething由某物实现)。我想支持的一件事是自动注册来获取独立DLL中的依赖项,并自动注册这些依赖项 所以:IFoo是由Foo(都在Foo.dll中)实现的,而Foo依赖于Bar.dll中的IBar 我编写了以下代码来实际执行自动注册。这似乎有效,但我想知道我自己是否做了太多的工作。有没有更简单的方法来完成同样的事情 private static void Ensure

我是Castle n00b,正在使用Castle Windsor中的Fluent API根据命名约定自动注册服务的实现(ISomething由某物实现)。我想支持的一件事是自动注册来获取独立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);
                   }
               }
            }
        }
    }

这实际上取决于您如何构造和命名组件。。。如果保留一些简单约定(即“MyApp.services”命名空间下的所有组件服务及其“MyApp.services.Impl”下的实现),则可以显著降低这种复杂性(例如,请参见)


此外,除最简单的情况外,这种方法的实用性相当有限。。。例如,您希望在没有任何服务接口的情况下注册某些服务,某些服务需要配置、服务覆盖等。在这种情况下,这将不起作用。

不确定这是否回答了您的问题,但这是我为自动注册服务所做的

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

我的所有服务都继承自一个BaseService(抽象类)和一个接口IService。这将自动将具体服务类绑定到其接口,并使其可在容器中使用。

谢谢您的回答。我正在做的是在一些遗留应用程序中引入一个容器,并在使用容器时追求零摩擦(只要它们符合“IBar由Bar实现”的约定)。并同意:复杂场景。不过,我想打80%的案子,谢谢。就像我说的,我主要是想看看我是否错过了一个更简单的方法。正如您所指出的,简化事情的一种方法是简化容器周围的事情:-)