Domanda

Sto usando il Castello di Windsor 2.5.1 in un progetto ASP.NET MVC e utilizza l'iniezione di proprietà per creare un oggetto che mi aspetto di essere sempre disponibili su una classe controller di base. Sto usando una fabbrica per creare questo oggetto, se si verifica un errore nel costruttore, non ho ricevuto un avviso da Windsor a tutti e restituisce solo il mio scopo, ma senza iniettare la proprietà.

E 'questo il comportamento previsto, e se sì, come posso ottenere un errore generato quando una fabbrica non riesce a restituire qualcosa?

Ecco un esempio

public class MyDependency : IMyDependency
{
    public MyDependency(bool error)
    {
        if (error) throw new Exception("I error on creation");
    }
}

public interface IMyDependency
{
}

public class MyConsumer
{
    public IMyDependency MyDependency { get; set; }
}

[TestFixture]
public class ProgramTest
{
    [Test]
    public void CreateWithoutError() //Works as expected
    {
        var container = new WindsorContainer().Register(
            Component.For<IMyDependency>().UsingFactoryMethod(() => new MyDependency(false)).LifeStyle.Transient,
            Component.For<MyConsumer>().LifeStyle.Transient
        );

        var consumer = container.Resolve<MyConsumer>();

        Assert.IsNotNull(consumer);
        Assert.IsNotNull(consumer.MyDependency);
    }

    [Test]
    public void CreateWithError_WhatShouldHappen() //I would expect an error since it can't create MyDependency
    {
        var container = new WindsorContainer().Register(
            Component.For<IMyDependency>().UsingFactoryMethod(() => new MyDependency(true)).LifeStyle.Transient,
            Component.For<MyConsumer>().LifeStyle.Transient
        );

        Assert.Throws<Exception>(() => container.Resolve<MyConsumer>());
    }

    [Test]
    public void CreateWithError_WhatActuallyHappens() //Gives me back a consumer, but ignores MyDependency
    {
        var container = new WindsorContainer().Register(
            Component.For<IMyDependency>().UsingFactoryMethod(() => new MyDependency(true)).LifeStyle.Transient,
            Component.For<MyConsumer>().LifeStyle.Transient
        );

        var consumer = container.Resolve<MyConsumer>();

        Assert.IsNotNull(consumer);
        Assert.IsNull(consumer.MyDependency); //Basically fails silently!
    }
}

Un'osservazione interessante, se uso questo nella mia applicazione MVC, ottengo un errore interno da Windsor al momento della chiamata ReleaseComponent - quindi, anche se non ha dato mi riporta una classe con la mia dipendenza iniettato, sembra ancora da provare il rilascio esso.

È stato utile?

Soluzione

Per quanto ne so, sì, che è il comportamento previsto. Questo non è specifico per metodi di fabbrica, funziona così per tutte le dipendenze di servizio opzionali. dipendenze opzionali che gettano per la risoluzione sono trattati come non risolvibile. Questo è definito nella DefaultComponentActivator.ObtainPropertyValue ()

Naturalmente, si può sempre ignorare l'attivatore di default con il proprio se si vuole cambiare questo comportamento.

Altri suggerimenti

Così come l'opzione suggerita da Mauricio, è anche possibile creare uno strumento per ottenere il comportamento previsto come spiegato a questa pagina esempio sulle strutture.

Questa è la mia realizzazione, che è un po 'più conciso:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class NonOptionalAttribute : Attribute
{
}

public class NonOptionalPropertiesFacility : AbstractFacility
{
    protected override void Init()
    {
        Kernel.ComponentModelBuilder.AddContributor(new NonOptionalInspector());
    }
}

public class NonOptionalInspector : IContributeComponentModelConstruction
{
    public void ProcessModel(IKernel kernel, ComponentModel model)
    {
        foreach (var prop in model.Properties.Where(prop => prop.Property.IsDefined(typeof (NonOptionalAttribute), false)))
        {
            prop.Dependency.IsOptional = false;
        }
    }
}

Poi basta decorare qualsiasi proprietà con [NonOptional] e si riceverà un errore se c'è un problema con la costruzione.

A partire dal castello di Windsor 3.2 C'è nuova aggiunta di un fresco che è registrazione diagnostica nel contenitore .

Quindi, se si esegue questa operazione per esempio in un'applicazione ASP.NET MVC:

var logger = _container.Resolve<ILogger>();
((IKernelInternal)_container.Kernel).Logger = logger;

è possibile reindirizzare i log catturati da Windsor al tuo logger log4net configurato.

Il tipo di informazioni in fase di login comprende:

  • Quando Windsor cerca di risolvere una dipendenza opzionale (come l'iniezione di proprietà), ma non riesce a causa un'eccezione, l'eccezione viene registrata.
  • Quando si registra un tipo per convenzione e ignorando che a causa di una registrazione esistente per questo tipo, questo fatto viene registrato.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top