2010-03-03 3 views

Répondre

6

Oui, il est possible. L'activateur de composant par défaut ne recherche que les constructeurs publics. Vous pouvez fournir activateur composant personnalisé pour ce composant qui prendrait en compte le constructeur interne, ou par exemple en usine pour activer le composant:

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

Cependant, vous devriez revoir vraiment faire la .ctor interne en premier lieu . C'est vraiment rarement une bonne idée de le faire, surtout quand vous présentez la classe comme une composante du monde extérieur de toute façon.

+1

Salut Krzystzof, je pensais que le "et comment est-il fait si c'est?" était implicite à la question! Je suppose que non. Alors: Comment faites-vous? À votre santé Joni – joniba

+0

Merci Ian. Donc en effet je dois créer une usine pour construire ces composants en utilisant la réflexion. C'est un peu dommage, car Castle Windsor utilise déjà la réflexion pour ses enregistrements de composants. Mais je comprends le raisonnement. Merci encore. – joniba

+1

+1 pour avoir suggéré de reconsidérer la conception –

0

Après les conseils de la réponse acceptée, j'ai pu étendre la classe DefaultComponentActivator à travailler avec protected constructeurs (il ne fonctionne toujours pas avec private ou internal, le code ci-dessous fonctionne très bien, qui est, mais quelque chose d'autre dans la La chaîne de création DynamicProxy échoue).

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

Ensuite, sur votre conteneur que vous enregistrez ce contre un objet ComponentRegistration via la méthode générique Activator, donc mon appel container.Register ressemble à ceci:

_container.Register 
    (
     // . . . 

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

     // . . . 
    ); 

espoir qui aide quelqu'un!