2010-12-09 4 views
8

ASP.NET MVC 프로젝트에서 Castle Windsor 2.5.1을 사용하고 속성 주입을 사용하여 기본 컨트롤러 클래스에서 항상 사용할 수 있다고 예상되는 개체를 만듭니다. 나는이 객체를 생성하기 위해 팩토리를 사용하지만 생성자에 오류가있는 경우 Windsor에서 경고를 얻지 못하고 객체를 반환하지만 속성을 주입하지는 않습니다.Castle Windsor 이상한 동작 wth 속성 주입 및 팩토리 메서드

예상되는 동작입니까? 그렇다면 팩터 리가 아무것도 반환하지 못할 때 발생하는 오류를 어떻게 얻을 수 있습니까? 그것은 나를 다시 포기하지 않았다 순간에도 - 여기

내가 내 MVC 응용 프로그램이 사용하는 경우 ReleaseComponent 호출 할 때, 나는 윈저에서 내부 오류가 발생, 예를 들어

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

흥미로운 관찰이다 클래스에 내 종속성을 주입하면 여전히 그것을 공개하려고 시도합니다.

답변

5

내가 아는 한, 네, 의도 한 행동입니다. 이것은 팩토리 메소드에만 국한되지 않고 모든 선택적 서비스 종속성에 대해 작동합니다. 해결할 때 throw되는 선택적 종속성을 확인할 수없는 것으로 처리합니다. 이것은 다음과 같이 정의됩니다 DefaultComponentActivator.ObtainPropertyValue()

물론이 동작을 변경하려면 기본 활성기를 사용자가 직접 무시할 수 있습니다.

+1

감사합니다. 이 문제를 해결하기 위해 몇 가지 방법으로 문제를 해결할 수 있습니다. – amarsuperstar

+1

다음은이 문제를 해결하는 방법입니다. http://stackoverflow.com/a/12007547/114029 –

5

Mauricio가 제안한 옵션뿐 아니라 this 기능에 대한 예제 페이지에서 설명한대로 예상되는 동작을 수행하는 기능을 만들 수도 있습니다.

[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] 어떤 속성을 장식 건설에 문제가있을 경우 오류가 발생합니다 :

여기에 조금 더 간결 내 구현입니다.

+1

Perfect! 읽는 사람이 나를 설치하는 구문을 기억하지 못하는 경우 부트 스트랩 루틴 중에 Container.AddFacility ()를 호출하십시오. –

0

캐슬 윈저 3.2부터 새롭고 멋진 추가 내용이 Diagnostic logging in the container입니다.

그래서 당신은 ASP.NET MVC 응용 프로그램에서 예를 들어,이 작업을 수행하는 경우 : 당신이 당신의 구성 log4net 로거 윈저에 걸려 로그를 재 지정할 수 있습니다

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

. 예외가 기록되어

  • 윈저 (속성 주입 등) 선택적 종속성이 해결하려고

    하지만 예외 인해 실패

    현재 기록되는 정보의 종류가 포함된다.

  • 규칙에 따라 유형을 등록하고 해당 유형에 대한 기존 등록으로 인해 유형을 무시하면이 사실이 기록됩니다.
관련 문제