13

저는 Microsoft의 Unity 프레임 워크에서 C#을 사용하고 있습니다. 이 문제를 해결하는 방법을 잘 모르겠습니다. 그것은 아마도 Unity와의 이해가 부족하다는 것과 관련이 있습니다.C#/Unity의 생성자 삽입?

내 문제는 다음 예제 코드를 사용하여 요약 될 수있다 : 이름이 '티미'와 사람의 아들 '이 주입되는 것을 나는 버스에 해결 메서드를 호출 할 때

class Train(Person p) { ... } 

class Bus(Person p) { ... } 

class Person(string name) { ... } 

Person dad = new Person("joe"); 
Person son = new Person("timmy"); 

이 어떻게 확신 할 수 있습니다 기차를 해결할 때 '조'라는 이름을 가진 사람 '아빠'가 해결되었다는 것을 어떻게 확신 할 수 있습니까?

아마도 명명 된 인스턴스를 사용할 것으로 생각합니까? 그러나 나는 잃어 버렸다. 어떤 도움을 주시면 감사하겠습니다.

여담으로

, 나는 오히려 IPerson에 인터페이스를 생성하지 않을 것입니다. 이 문제를 해결하기 위해

답변

15

한 가지 방법은 이름 등록을 주입 생성자를 사용하는 것입니다.

// Register timmy this way 
Person son = new Person("Timmy"); 
container.RegisterInstance<Person>("son", son); 

// OR register timmy this way 
container.RegisterType<Person>("son", new InjectionConstructor("Timmy")); 

// Either way, register bus this way. 
container.RegisterType<Bus>(new InjectionConstructor(container.Resolve<Person>("son"))); 

// Repeat for Joe/Train 
+2

어떻게 하드 코드하지 않고 설정 파일에 저장할 수 있습니까? –

32

"joe"와 "timmy"를 각각의 종속성으로 등록하지 않으면 "timmy"가 Schoolbus에 주입되었는지 확신 할 수 없습니다. 사실 이름없는 종속성과 동일한 클래스의 인스턴스 두 개를 등록하려고하면 모호한 설정이되어 Person을 전혀 해결할 수 없습니다. 일반적으로

, 당신이 명명 된 인스턴스 당신은 아마 잘못된 방법으로 DI에 대해려고 많이 등록해야합니다. DI의 주요 아이디어는 도메인 개체 도메인 서비스보다 해결하는 것입니다.

DI의 기본 아이디어는 (인터페이스 또는 추상 클래스) 콘크리트 종류추상적 인 형태를 해결 할 수있는 메커니즘을 제공하는 것입니다. 당신의 예제에는 추상적 인 유형이 없으므로 실제로 의미가 없습니다.

+0

귀하의 통찰력있는 응답에 감사드립니다. 비록 당신이 옳을지라도, DI와 IoC는 새로운 개념이므로 나는 여전히 최고의 디자인을 찾으려고 노력하고 있습니다. –

+1

그 정도면 충분합니다. 내 책을 읽고 싶을 수도 있습니다. :) –

+2

JP. 그의 책을 확인하십시오. 나는 그것이 매우 통찰력있는 것으로 나타났습니다. –

14

Mark Seeman이 올바르게 처리했습니다. 그리고 나는 당신의 혼란에 동정합니다. 자동 종속성 주입 컨테이너를 사용하는 법을 배웠을 때 직접 경험했습니다. 문제는 객체를 설계하고 사용할 수있는 타당하고 합리적인 방법이 많다는 것입니다. 그러나 이러한 접근법 중 일부는 자동 종속성 인젝션 컨테이너에서 작동합니다.

내 개인의 역사 : 내가 유니티 또는 성 윈저 컨테이너와 같은 컨트롤 컨테이너의 반전을 사용하는 방법을 배웠습니다 오래 전에 객체 생성 및 제어의 반전의 OO 원칙을 배웠다. 나는이 같은 코드를 작성하는 습관을 획득 한이 설계에서

public class Foo 
{ 
    IService _service; 
    int _accountNumber; 

    public Foo(IService service, int accountNumber) 
    { 
     _service = service; 
     _accountNumber = accountNumber; 
    } 
    public void SaveAccount() 
    { 
     _service.Save(_accountNumber); 

    } 
} 
public class Program 
{ 
    public static void Main() 
    { 
     Foo foo = new Foo(new Service(),1234); 
     foo.Save(); 
    } 
} 

을 내 푸 클래스는 데이터베이스에 계정을 저장하는 책임이있다. 그 일을하기 위해서는 계좌 번호와 더러운 일을하는 서비스가 필요합니다. 이것은 위에서 제공 한 concreted 클래스와 다소 비슷합니다. 여기서 각 객체는 생성자에서 고유 한 값을 사용합니다. 이 코드는 객체를 자신의 코드로 인스턴스화 할 때 잘 동작합니다. 적시에 적절한 값을 전달할 수 있습니다. 나는 자동 의존성 주입 컨테이너에 대해 알게되었을 때

그러나, 나는 손으로 푸의 인스턴스를 더 이상 것을 찾을 수 없습니다. 컨테이너는 나를 위해 생성자 인수를 인스턴스화합니다. 이것은 IService와 같은 서비스에 큰 편의를 제공했습니다. 그러나 정수와 문자열 등에서는 그렇게 잘 작동하지 않습니다. 이러한 경우 기본값 (정수의 경우 0과 같음)을 제공합니다.대신 나는 등 계좌 번호, 이름, 같은 상황에 특정 값 전달에 익숙한 ... 그래서 내가 이렇게 될 코딩과 디자인의 내 스타일을 조정했습니다했다 : 그것은 모두 나타납니다

public class Foo 
{ 
    IService _service; 
    public Foo(IService service) 
    { 
     _service = service; 
    } 
    public void SaveAccount(int accountNumber) 
    { 
     _service.Save(accountNumber); 

    } 
} 
public class Program 
{ 
    public static void Main() 
    { 
     Foo foo = new Foo(new Service()); 
     foo.Save(1234); 
    } 
} 

Foo 클래스는 유효한 디자인입니다. 그러나 두 번째 버전은 자동 종속성 주입과 함께 사용할 수 있으며 첫 번째 버전은 자동 종속성 주입과 함께 사용할 수 없습니다.

+4

두 번째 Main() 메소드가 다음과 같아야합니다 : Foo foo = new Foo (new Service()); foo.Save (1234); ? – McBainUK

+0

사실 foo.SaveAccount (1234)가되어야합니다 : – sethidev

+0

거기에'int' 초기화에 흥미가 없습니다. 방금 시간 제한을 초기화해야하는 매우 유사한 사례 (완전히 다른 도메인)가있었습니다. 즉, 메서드로 추상화 한 것입니다. – Thomas