2010-04-19 4 views
5

Ninjects ConstructorArgument를 사용할 때 특정 매개 변수에 주입 할 정확한 값을 지정할 수 있습니다. 이 값을 null로 할 수없는 이유는 무엇입니까? 어쩌면 예 .. 그것은 당신이하고 싶은 일이 아니다,하지만 난 내 단위 테스트에서 사용하려면 : 생성자의 인수가 너무 값 유형이 될 수 있기 때문에Ninjects ConstructorArgument에 값 null을 삽입 할 수없는 이유는 무엇입니까?

public class Ninja 
{ 
    private readonly IWeapon _weapon; 
    public Ninja(IWeapon weapon) 
    { 
     _weapon = weapon; 
    } 
} 

public void SomeFunction() 
{ 
    var kernel = new StandardKernel(); 
    var ninja = kernel.Get<Ninja>(new ConstructorArgument("weapon", null)); 
} 
+0

저는 ninject에 익숙하지 않지만 IoC 컨테이너가 적절한 생성자를 찾기 위해 유형 정보를 사용하고 null 값으로 찾을 수 없다고 생각합니다. 문서 나 코드에서 답변을 검색하는 것이 좋습니다. 하나의 라이브러리에서 해당 Type 객체의 인스턴스를 사용하는 것이 null 대신 전달되어야합니다. 여기에도 비슷한 해결책이있을 수 있습니다. – SergGr

+0

감사합니다 .-) – stiank81

답변

7

값 형 또는 null 이외의 Reference Type를 건네주는 경우).

해결 방법은 Object로 널 캐스팅하는 것입니다 : -

var ninja = kernel.Get<Ninja>(new ConstructorArgument("weapon", (object)null)); 

Ninject에 2 출처 :

public class ConstructorArgument : Parameter 
{ 
    /// <summary> 
    /// Initializes a new instance of the <see cref="ConstructorArgument"/> class. 
    /// </summary> 
    /// <param name="name">The name of the argument to override.</param> 
    /// <param name="value">The value to inject into the property.</param> 
    public ConstructorArgument(string name, object value) : base(name, value, false) { } 

    /// <summary> 
    /// Initializes a new instance of the <see cref="ConstructorArgument"/> class. 
    /// </summary> 
    /// <param name="name">The name of the argument to override.</param> 
    /// <param name="valueCallback">The callback to invoke to get the value that should be injected.</param> 
    public ConstructorArgument(string name, Func<IContext, object> valueCallback) : base(name, valueCallback, false) { } 
} 

생식 :

public class ReproAndResolution 
{ 
    public interface IWeapon 
    { 
    } 

    public class Ninja 
    { 
     private readonly IWeapon _weapon; 
     public Ninja(IWeapon weapon) 
     { 
      _weapon = weapon; 
     } 
    } 

    [Fact] 
    public void TestMethod() 
    { 
     var kernel = new StandardKernel(); 
     var ninja = kernel.Get<Ninja>(new ConstructorArgument("weapon", (object)null)); 
    } 
} 

레슨? 당신은 최신 소스를 다운로드하지 말고 미친 듯이 보일 것입니다. 위대한 의견, 좋은 깨끗한 코드베이스. @ Ian Davis에게 다시 한번 감사의 말을 전한다. 내 장치에서 사용하려는

+0

+1 좋은 - 흥미로운 것들. 설명을 위해 – Finglas

+0

Thx. 내가 개체 nulls를 캐스팅 주위에 가고 싶다고 생각하지 않지만이 내 질문에 대답하는 것! 아마도 나는 최신 소스를 체크 아웃해야만한다 :-) – stiank81

+0

@ stiank81 : @Finglas의 대답에 대한 나의 의견 (내가 Accepted One : P가되어야한다고 동의하더라도 올바른 대답이라고 생각한다.)에 의하면, 추한 이유 왜냐하면 그것은 정상적인 사용법으로 이루어지기를 의도하지 않았기 때문입니다. (ConstructorArgument가 다른 질문에서 잘못된 기본 접근법을 다루지 않았습니까? : P) @Finglas : 감사합니다. 다른 것들을 제거해 주셔서 감사합니다. –

0

이 아마 지원되지 않습니다.

+0

이것은 잘못된 답변을 찾았습니다. 하지만 Brian의 대답에 동의하지 않는 리플렉션에 대해서도 나에게 자극을주었습니다 (둘 다 +0을 남겨두고 너무 늦게 다른 것을 취소하고 개념적 통찰력을 제공했지만 Ninject가 권장/방지/force) –

3

나는 Ninject를 모르지만 AFAIK 생성자 삽입은 일반적으로 필수 종속성에 사용되므로 null은이 컨텍스트에서 거의 의미가 없습니다. 종속성이 필수적이지 않은 경우 유형은 기본 생성자를 제공하고 대신 속성 주입을 사용해야합니다.

This post은 추가 정보를 제공합니다.

가 (일반 사용보다 ConstructorArgument ctor에 다른 오버로드에 결합 즉, 어디 '있기 때문에 이것은 : 소스 (P 당신은 생략 내가 reproing에 의해 얻은 스택 추적)을 보면

+0

Gerrie의 대답보다 논리적 인 것처럼 보였기 때문에 이것을 +1했습니다.리플렉션에서는 가치 유형뿐만 아니라 참조 유형 및 포인트에 대해서도 실제로 컨텍스트에서 잘 일반화 할 수 있으므로 실제로 동의하지는 않습니다. 개발자가 원하지 않는 것은 불특정, 무작위로 초기화되지 않은 것 및/또는 의존성 체인을 식별하는 데 도움이되는 명확한 방법으로 지정되지 않은 종속성입니다. –

+0

속성 주입은 이에 적합한 해결책입니까? 그렇다면 이것은 합리적인 것처럼 들립니다. 링크 Thx. – stiank81

+0

@ stiank81 : 속성 주입은 여러분이 달성하고자하는 기본적인 것을 성취 할 수 있습니다 (많은'null' 값). 그렇게하면 코드 청결 함에서 많은 것을 잃을 것입니다. @ Finglas의 대답을 참조하십시오. –

3

no need to use an IOC container for unit tests 있습니다 테스트합니다. 런타임시 컨테이너를 사용하여 응용 프로그램을 연결해야합니다. 그 상처를하기 시작한다면, 당신의 클래스를 나타내는 자사의 냄새가 손에서 점점

귀하의 단위 테스트는이 예에있을 것 (SRP 위반?) :

var ninja = new Ninja(null); 

위입니다 합법적 인 C# 코드 단위 테스트를위한 널 참조를 전달하는 것은 종속성이 필요하지 않은 단위 테스트 영역의 완벽하게 유효한 방법입니다.

+0

+1 중요한 점은 답이 없습니다 질문 (비록 이것이 사실이라는 사실이 아마도 (null의 경우 잘못된 과부하 해결)이 문제로 고려되지 않은 이유 일 것입니다. –

+0

@ 루벤 : 그렇습니다. 그게 전부입니다. 개선 및 학습. – Finglas

관련 문제