2

나는 학습 목적으로 자체 IoC 컨테이너를 만드는 작업을하고 있습니다. 그들에 대한 몇 가지 질문을 한 후, 객체를 "해석하는"팩토리를 만드는 것이 최선의 해결책이라고 나타났습니다 (see third solution here). 사용자 Krzysztof Koźmic은 캐슬 윈저가 실제로 이것을 구현할 수 있음을 보여주었습니다.구현을 만들지 않고 구현 인터페이스 (동적 프록시)

나는 아침에 CW의 원천을 읽었습니다. Resolve가 호출되면 인터페이스를 반환합니다. 이 인터페이스는 (구현이 없기 때문에) "인터셉트"호출을 어떻게하고 자신의 메서드라고 부릅니까?

나는 분명히 여기에 어떤 반성의 속임수가 있으며 꽤 놀랍다는 것을 알고 있습니다. 나는 모든 사용자가 "차단"이 어떻게 이루어지는 지 알지 못합니다. 나는 자식에게 토끼 구멍을내어 내려고 노력했지만, 나는 길을 잃었다. 누군가가 올바른 방향으로 나를 가리킬 수 있다면 그것은 많이 감사 할 것입니다.

또한 - 호출 된 코드 내부의 컨테이너에 대한 종속성이있는 형식화 된 팩토리를 만들지 않았습니까? ASP.NET MVC 용어로는 나에게 그렇게 보인다.

EDIT : Found Reflection.Emit ... 사용 된 내용 일 수 있습니까?

EDIT2 : 점점 더 자세히 살펴보면 자동으로 공장을 생성하는 것이 더 복잡해집니다. 나는 반복적 인 코드를 고수하게 될지도 모른다.

답변

7

여기에 두 개의 분리 된 개념이 있습니다

  1. 의존성 주입은 단지 인터페이스를 구현하는 기존의 클래스를 인스턴스화합니다. 예를 들어, IMyServices를 구현하는 MyServices 클래스가있을 수 있습니다. IoC 프레임 워크는 IMyServices를 요청할 때 MyServices의 인스턴스로 확인하도록 지정하는 다양한 방법을 제공합니다. 팩토리 또는 도우미 메서드를 설정하기 위해 IL Emit 마법이있을 수 있지만 실제 인스턴스는 사용자가 정의한 클래스입니다.

  2. Mocking 실제로 클래스를 코딩 할 필요없이 인터페이스를 구현하는 클래스를 인스턴스화 할 수 있습니다. 당신이 생각한대로 이것은 일반적으로 Reflection과 IL Emit을 사용합니다. 일반적으로 방출 된 일리노이 코드는 C#으로 작성된 메서드에 작업의 대부분을 위임하는 매우 간단합니다. 조롱의 복잡성 대부분은 프레임 워크가 종종 유창한 구문을 사용하여 동작을 지정할 수 있도록하기 때문에 메서드 자체의 동작을 지정하는 것과 관련이 있습니다. Moles과 같은 일부는 단순히 메소드를 구현하는 델리 게이트를 지정할 수 있습니다.하지만 Moles는 호출을 정적 메소드로 리디렉션하는 것과 같은 기타 미친 작업을 수행 할 수 있습니다.


이 조금 더 정교한하기 위해, 당신은 실제로 IOC의 기능을 구현하기 위해 IL를 사용할 필요가 없습니다,하지만 반사가 상대적으로 고가이기 때문에이 자주 반복 반사 호출의 오버 헤드를 피하기 위해 가치가있다. Here은 캐슬 윈저가 무엇을하고 있는지에 대한 정보입니다.

가 귀하의 질문에 대답하기 위해, 내가 시작하는 것으로 가장 유용한 장소는 OpCodes 클래스였다. 이것은 IL에서 사용 가능한 기능과 OpCodes가 어떻게 작동하는지에 대한 좋은 요약입니다. 이것은 본질적으로 스택 기반 어셈블리 언어 (걱정할 레지스터가 없음)이지만 강력한 형식이며 유형, 필드 및 메서드와 같은 개체 기호 및 개념에 대한 일류 액세스를 제공합니다. Here은 일리노이의 기초를 소개하는 좋은 코드 프로젝트 기사입니다.관심이 있다면 지난 몇 년 동안 만든 Emergent 코드를 사용하여 만든 헬퍼 클래스를 보내 줄 수 있습니다.

+0

의견을 보내 주셔서 감사합니다. 내가 만들고자하는 IoC 컨테이너에 대해 "조롱"을 사용하려고합니다. Castle Windsor는 일종의 기술을 사용하여 지정된 인터페이스를 구현하는 "typed factory"를 만듭니다. 크 르지 스 토프 (Krzysztof)에서 올린 링크를 읽으면 내가 무슨 뜻인지 알게 될 것입니다. 타사 라이브러리를 사용하고 싶지 않습니다. 내 모든 것을 배우기 위해서입니다. 클래스 생성에 대한 리소스가 있습니까? 편집 : 나는 일리노이를 사용하는 * 필요 * 모르겠다, 나는 그것이 어떻게 완료되었는지 궁금해서. 감사! :) – TheCloudlessSky

+0

고마워요. 나는 독서를 시작할 것입니다. 나는 극단적 인 것처럼 보이기 때문에이 기능을 구현하지 않을 수도 있습니다. 그러나 매우 재미 있기 때문에 이것을 보겠습니다. 감사! – TheCloudlessSky

+0

@TheCloudlessSky, IL은 많은 재미있는 일을 할 수 있기 때문에 많은 즐거움을 선사합니다. 하지만 많은 작업이 필요합니다. Emit 메서드는 매우 까다 롭습니다 (올바른 인수가 포함되어 있는지 확인하지 않으므로 런타임에 오류가 발생하거나 잘못 표시되는 IL 코드를 실수로 쉽게 만들 수 있습니다).) 당신이 그것으로 노는 경우에, peverify.exe가 당신의 친구다는 것을 다만 기억하십시오. –

5

형식화 된 팩토리는 Castle DynamicProxy 라이브러리를 사용하여 구현됩니다. 즉, 인터페이스를 구현하는 유형을 생성하고 인터페이스를 통해 인터셉터로 모든 유형의 호출을 전달합니다.

코드에 종속되지 않습니다. Windsor를 참조하지 않는 인터페이스는 사용자가 제어하는 ​​어셈블리에서 만들어집니다. 다른 어셈블리 (애플 리케이션의 진입 지점)에서 Windsor에 인터페이스에 대해 알려주고 공장에 알려 Windsor가 인터페이스에 대해 배우고 그 인터페이스로 작업을 수행합니다. 그것은 그 영광의 통제 반전입니다.

그것은 실제로 복잡하지입니다 :)

+0

답해 주셔서 감사합니다. 그래서 Castle DynamicProxy 라이브러리는 Reflection.Emit을 사용합니다. – TheCloudlessSky

+0

신경 쓰지 마라. 나는 DynamicProxy의 소스를 파고 가서 모든 종류의 깔끔한 것들을 발견했다. (그렇다. Reflection.Emit을 사용하고있다.) 감사! :) – TheCloudlessSky

1

ImpromptuInterface은 인터페이스를 기반으로 DLR 동적 프록시를 생성합니다. 정적 인터페이스로 동적 구현을 ​​할 수 있습니다. 사실 인터페이스를 기반으로하는 동적 인 구현을 통해 공장을 생성하기위한 시작점을 제공하는 기본 클래스 인 ImpromptuFactory도 있습니다.