Le château de Windsor un comportement étrange avec l'injection de la propriété et la méthode d'usine

StackOverflow https://stackoverflow.com/questions/4398101

Question

J'utilise le château de Windsor 2.5.1 dans un projet ASP.NET MVC et par injection de propriété pour créer un objet que je pense être toujours disponible sur une classe de contrôleur de base. Je me sers d'une usine pour créer cet objet, s'il y a une erreur dans le constructeur, je ne reçois pas un avertissement de Windsor du tout et il retourne juste mon objet, mais sans injecter la propriété.

Est-ce le comportement attendu, et si oui, comment puis-je obtenir une erreur déclenché lorsqu'une usine ne retourne pas quoi que ce soit?

Voici un exemple

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

Une observation intéressante, si je l'utilise dans mon application MVC, je reçois une erreur interne de Windsor lors de l'appel ReleaseComponent - alors même si elle ne m'a pas REDONNER une classe avec ma dépendance injectée, il semble toujours essayer de libérer il.

Était-ce utile?

La solution

Pour autant que je sache, oui, c'est le comportement prévu. Ce n'est pas spécifique aux méthodes d'usine, cela fonctionne comme ça pour toutes les dépendances de service en option. Dépendances facultatives qui jettent lors de la résolution sont traités comme des non-résoluble. Ceci est défini dans DefaultComponentActivator.ObtainPropertyValue ()

Bien sûr, vous pouvez toujours remplacer l'activateur par défaut avec votre propre si vous voulez modifier ce comportement.

Autres conseils

En plus de l'option proposée par Mauricio, il est également possible de créer un mécanisme pour obtenir le comportement attendu comme expliqué sur cet exemple sur les installations.

Voici ma mise en œuvre qui est un peu plus concis:

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

Alors que décorer les propriétés avec [NonOptional] et vous recevrez une erreur s'il y a un problème avec la construction.

Au château de Windsor 3.2, il y a un nouveau plus de cool qui est

scroll top