2010-03-03 56 views

回答

6

是的,这是可能的。默认组件激活器仅用于公共构造函数。 您可以提供该组件,将采取内部构造考虑,或使用例如工厂,以激活组件定制组件激活:

var container = new WindsorContainer() 
    .AddFacility<FactorySupportFacility>() 
    .Register(Component.For<Foo>() 
        .UsingFactoryMethod(() => new Foo())); 
var foo = container.Resolve<Foo>(); 

但是你真的应该重新考虑使.ctor放在首位内部。这样做确实不是一个好主意,特别是当你将课程作为外部世界的组件暴露出来时。

+1

嗨Krzystzof,我认为“如果它是如何完成的?”这个问题是隐含的!我猜不是。所以: 你怎么做到的? 干杯 Joni – joniba 2010-03-03 13:20:15

+0

谢谢伊恩。所以实际上我必须创建一个工厂来使用反射来构建这些组件。因为Castle Windsor已经在使用反射来进行组件注册,所以感到羞耻。但我理解这个推理。 再次感谢。 – joniba 2010-03-03 14:11:51

+1

+1表示重新考虑设计 – 2010-03-03 15:18:45

0

按照接受的答案的建议下,我才得以延长DefaultComponentActivatorprotected建设者的工作(它仍然无法与privateinternal工作;下面的代码工作正常,那就是,但在别的东西DynamicProxy创建链失败)。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Reflection; 
using Castle.Core; 
using Castle.MicroKernel; 
using Castle.MicroKernel.ComponentActivator; 
using Castle.MicroKernel.Context; 

namespace /* YourNameSpaceHere */ 
{ 
    [Serializable] 
    public class NonPublicComponentActivator : DefaultComponentActivator 
    { 
     public NonPublicComponentActivator(ComponentModel model, IKernelInternal kernel, ComponentInstanceDelegate onCreation, ComponentInstanceDelegate onDestruction) 
      : base(model, kernel, onCreation, onDestruction) 
     { /* do nothing */ } 

     private readonly List<Type> loadedTypes = new List<Type>(); 
     protected override ConstructorCandidate SelectEligibleConstructor(CreationContext context) 
     { 
      lock (loadedTypes) 
      { 
       if (!loadedTypes.Contains(context.RequestedType)) 
       { 
        loadedTypes.Add(context.RequestedType); 

        // Add the missing non-public constructors too: 
        var ctors = context.RequestedType.GetConstructors 
        (
         BindingFlags.NonPublic | BindingFlags.Instance 
        ); 

        foreach (var ctor in ctors) 
        { 
         Model.AddConstructor 
         (
          new ConstructorCandidate 
          (
           ctor, 
           ctor.GetParameters().Select(pi => new ConstructorDependencyModel(pi)).ToArray() 
          ) 
         ); 
        } 
       } 
      } 

      return base.SelectEligibleConstructor(context); 
     } 
    } 
} 

然后,您的容器上,你通过通用Activator方法针对ComponentRegistration对象登记本,所以我container.Register调用看起来是这样的:

_container.Register 
    (
     // . . . 

     AllClasses.FromThisAssembly().BasedOn<ISomeInterface>() 
      .Configure 
      (
       c => c.LifeStyle.Transient 
        .Interceptors<MyInterceptor>() 
        .Activator<NonPublicComponentActivator>() // <--- REGISTERED HERE 
      ), 

     // . . . 
    ); 

希望帮助别人!