8

ASP.NETMVCプロジェクトでCastleWindsor2.5.1を使用しており、プロパティインジェクションを使用して、ベースコントローラークラスで常に使用できると予想されるオブジェクトを作成しています。ファクトリを使用してこのオブジェクトを作成していますが、コンストラクターでエラーが発生した場合、Windsorからの警告はまったく表示されず、プロパティを挿入せずにオブジェクトが返されるだけです。

これは予想される動作ですか?もしそうなら、ファクトリが何も返さないときにエラーを発生させるにはどうすればよいですか?

これが例です

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

興味深いことに、MVCアプリケーションでこれを使用すると、呼び出し時にWindsorから内部エラーが発生します。ReleaseComponentしたがって、依存性が注入されたクラスが返されなかったとしても、解放しようとしているように見えます。

4

3 に答える 3

5

私の知る限り、はい、それは意図された動作です。これはファクトリ メソッドに固有のものではなく、すべてのオプションのサービスの依存関係に対して同様に機能します。解決時にスローされるオプションの依存関係は、解決できないものとして扱われます。これはDefaultComponentActivator.ObtainPropertyValue()で定義されています

もちろん、この動作を変更したい場合は、いつでもデフォルトのアクティベーターを独自のものでオーバーライドできます。

于 2010-12-09T17:34:18.110 に答える
5

Mauricio によって提案されたオプションと同様に、設備に関するこの例のページで説明されているように、期待される動作を実現するための設備を作成することもできます。

もう少し簡潔な私の実装は次のとおりです。

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

次に、プロパティを で装飾するだけで[NonOptional]、構築に問題がある場合はエラーが発生します。

于 2010-12-10T15:15:44.500 に答える
0

Castle Windsor 3.2 の時点で、コンテナに Diagnostic loggingというクールな新機能が追加されました。

したがって、たとえば ASP.NET MVC アプリでこれを行うと、次のようになります。

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

Windsor によってキャッチされたログを、構成済みの log4net ロガーにリダイレクトできます。

現在ログに記録されている情報の種類は次のとおりです。

  • Windsor がオプションの依存関係 (プロパティ インジェクションなど) を解決しようとして、例外が原因で失敗した場合、例外がログに記録されます。
  • 慣例により型を登録し、その型の既存の登録が原因でそれを無視すると、この事実がログに記録されます。
于 2014-01-08T21:47:40.553 に答える