Frage

Ich bin mit Schloss Windsor 2.5.1 in einem ASP.NET MVC-Projekt und mit Eigenschaft Injektion ein Objekt zu erstellen, das erwarte ich immer auf einer Basis Controller-Klasse zur Verfügung steht. Ich bin eine Fabrik mit diesem Objekt zu erstellen, aber wenn es ein Fehler im Konstruktor ist, ich habe keine Warnung aus Windsor überhaupt bekommen, und es gibt nur mein Ziel, aber ohne die Eigenschaft zu injizieren.

Ist dies das erwartete Verhalten, und wenn ja, wie kann ich einen Fehler ausgelöst, wenn eine Fabrik etwas zurück ausfällt?

Hier ist ein Beispiel

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!
    }
}

Eine interessante Beobachtung, wenn ich dies in meiner MVC-Anwendung zu verwenden, ich einen internen Fehler von Windsor bekommen, wenn ReleaseComponent telefonieren - so dass, obwohl es nicht geben Sie mir eine Klasse zurück mit meiner Abhängigkeit injiziert, es scheint immer noch zu versuchen, die Freigabe es.

War es hilfreich?

Lösung

Soweit ich weiß, ja, das ist das gewünschte Verhalten. Dies ist auf die Werksmethoden nicht spezifisch, es funktioniert wie die für alle optionalen Service-Abhängigkeiten. Optionale Abhängigkeiten, die werfen, wenn sie als nicht auflösbaren behandelt zu lösen. Dies ist definiert in DefaultComponentActivator.ObtainPropertyValue ()

Natürlich können Sie immer die Standard-Aktivator mit Ihren eigenen überschreiben, wenn Sie dieses Verhalten ändern möchten.

Andere Tipps

Neben der Option von Mauricio vorgeschlagen, ist es auch möglich, eine Einrichtung zu schaffen, das erwartete Verhalten zu erreichen, wie auf diese Beispiel Seite über Einrichtungen.

Hier ist meine Implementierung, die etwas prägnanter ist:

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

Dann dekoriert nur alle Eigenschaften mit [NonOptional] und Sie erhalten eine Fehlermeldung an, wenn es ein Problem mit dem Bau.

Wie von Castle Windsor 3.2 es gibt neue coole Ergänzung, ist

scroll top