2013-03-20 16 views
5

Qualcuno può spiegare perché questo non funziona? Se rimuovi l'intercettatore dalla registrazione di IFoo e risolvi una barra, ottieni un Foo (MyFoo non è nullo). Ma con l'intercettore, il Foo non si risolve più.Windsor non risolve i componenti intercettati

Perché? Come posso sapere perché non si risolverà tramite la registrazione o la traccia?

Versioni:

  • Castle.Core: 3.2
  • Castle.Windsor: 3.2
  • .NET 4,5
  • C# 5

    using Castle.DynamicProxy; 
    using Castle.MicroKernel.Registration; 
    using Castle.Windsor; 
    using System; 
    
    namespace Sandbox 
    { 
    public interface IFooInterceptor : IInterceptor { } 
    
    public interface IFoo 
    { 
        void Print(); 
    } 
    
    public interface IBar 
    { 
        IFoo MyFoo { get; set; } 
    } 
    
    public class Foo : IFoo 
    { 
        public void Print() 
        { 
         Console.WriteLine("Print"); 
        } 
    } 
    
    public class FooInterceptor : IFooInterceptor, IInterceptor 
    { 
    
        public void Intercept(IInvocation invocation) 
        { 
         Console.WriteLine("Awesome"); 
         invocation.Proceed(); 
        } 
    } 
    
    public class Bar : IBar 
    { 
        public virtual IFoo MyFoo { get; set; } 
    } 
    
    class Program 
    { 
    
        static void Main(string[] args) 
        { 
         IWindsorContainer container = new WindsorContainer() 
          .Register(
           Component.For<IBar>().ImplementedBy<Bar>().LifestyleTransient(), 
           Component.For<IFoo>().ImplementedBy<Foo>().LifestyleTransient().Interceptors<IFooInterceptor>(), 
           Component.For<IFooInterceptor>().ImplementedBy<FooInterceptor>().LifestyleTransient() 
          ); 
    
         var bar = container.Resolve<IBar>(); 
         var foo = container.Resolve<IFoo>(); // this isn't null 
         bar.MyFoo.Print();     // exception: bar.MyFoo is null 
         Console.WriteLine("Done"); 
         Console.ReadLine(); 
        } 
    
    } 
    } 
    

Edit: Ho appena trovato (principalmente per caso) che la modifica della configurazione dell'intercettore da un'interfaccia a una classe concreta funziona. Tuttavia, sto registrando l'intercettore e la sua interfaccia, quindi la domanda originale è leggermente modificata: perché le specifiche dell'interfaccia falliscono (silenziosamente, non meno)?

+1

Non sono d'accordo con la rimozione del tag DynamicProxy. – Amy

+1

Sembra che questo sia un bug. Le proprietà sono dipendenze opzionali ma dovrebbero essere compilate di default ma in qualche modo è in conflitto con l'intercettazione. Se rendi la tua dipendenza obbligatoria con 'Component.For () .ImplementedBy () .LifestyleTransient(). Properties (PropertyFilter.RequireAll)' funziona anche. Ho trovato questo problema su github: https://github.com/castleproject/Windsor/issues/24 che si sente collegato a questo. – nemesv

+0

@nemesv Penso che puoi postare quella come risposta in modo che la domanda non rimanga senza risposta. Fornire Bar.MyFoo come argomento del costruttore risolverà anche il problema. – Marwijn

risposta

2

Castle gestisce le proprietà come dipendenze facoltative, ma dovrebbe iniettarle per impostazione predefinita. Ma sembra che in combinazione con gli Interceptor queste dipendenze opzionali non siano risolte correttamente.

cosa si può fare voi è quello di rendere il vostro dipendenze richieste modificando Bar da usare iniezione costruttore:

public class Bar : IBar 
{ 
    public Bar(IFoo foo) 
    { 
     MyFoo = foo; 
    } 

    public virtual IFoo MyFoo { get; private set; } 
} 

o registri Bar con la Properties esplicitamente contrassegnati richiesto:

Component.For<IBar>().ImplementedBy<Bar>().LifestyleTransient() 
    .Properties(Prop‌​ertyFilter.RequireAll) 

Nota: in produzione dovresti usare il metodo PropertiesRequired invece del Properties perché è ormai obsoleto.

Ho anche trovato questo problema github che sembrava anche rilevanti: Bug - optional dependencies not provided

Problemi correlati