6

단일 메서드 인터페이스 대신 명명 된 대리자를 사용하여 실험 해 왔습니다.캐슬 윈저에 정적 클로저를 등록하는 간단한 방법이 있습니까?

public interface IProductSource 
{ 
    IEnumerable<Product> GetProducts(); 
} 
public class DataContextProductSource : IProductSource 
{ 
    private readonly DataContext _DataContext; 
    public DataContextProductSource(DataContext dataContext) 
    { 
     if (dataContext == null) throw new ArgumentNullException("dataContext"); 
     _DataContext = dataContext; 
    } 
    public IEnumerable<Product> GetProducts() 
    { 
     return _DataContext.Products.AsEnumerable(); 
    } 
} 

에 :

public delegate IEnumerable<Product> DGetProducts(); 
public static class DataContextFunctions 
{ 
    public DGetProducts GetProducts(DataContext dataContext) 
    { 
     if (dataContext == null) throw new ArgumentNullException("dataContext"); 
     return() => dataContext.Products.AsEnumerable(); 
    } 
} 

이것은 기본적으로 사실을 활용하고 우리가 (사건을 과장하지 않도록 제거 일부 바꿈)에서 갈 수 이것은 코드 크기에 대한 몇 가지 장점이 있습니다 일단 당신이 의존성 주입으로 충분히 멀리 가면, 많은 클래스가 클로저가 될 것입니다. 이러한 클래스는 람다를 반환하는 함수로 대체 될 수 있습니다. 관련된 함수의 전체 집합 (변경 가능한 상태를 캡슐화 할 필요는 없지만 "표준"종속성 주입의 클래스를 사용하여 표현되었을 수 있음)은 정적 클래스 (또는 VB 용어로 "모듈")로 롤업 될 수 있습니다. .

이것은 모두 훌륭하지만 좋지만 Castle Windsor에 이러한 정적 방법을 등록하는 가장 좋은 방법을 찾는 데 어려움을 겪고 있습니다. 종속성이없는 메소드는 간단합니다.

Component.For<DGetIntegers>().Instance(Integers.GetOneToTen) 

그러나 위의 DataContextFunctions.GetProducts는 몇 가지 종속성이 있습니다.

Component.For<DGetProducts>().UsingFactoryMethod(
    kernel => DataContextFunctions.GetProducts(kernel.Resolve<DataContext>()) 

이 매우 상세 얻을 수 있고, 분명히 각 종속 직접 커널을 요청해야하는 종류의 포인트를 조금 패배 :이 등록 찾은 가장 좋은 방법입니다. 컨테이너에 필요한 모든 정적 정보를 사용할 수 있으므로이 작업을 수행 할 수 있어야합니다.

캐슬 윈저 (또는 다른 컨테이너)는 내가하지 못했던 간단한 방법, 또는 기술적 인 문제가 발생했는지, 아니면 너무 틈새로 만든 유스 케이스인가? 포함되어 있습니까?

답변

4

합니다. 나는 당신이 custom activator로이 작업을 아주 쉽게 할 수 있다고 생각한다.

+0

고마워요, 크 르지 스 토프. 나는 언젠가 그것을 밖으로 시도하고 결과를 다시보고합니다. 좋은 장소를 시작할 수있는 링크가 있습니까? – ninjeff

+0

@ninjeff 2.5.x를 사용하는 경우 문서가 시작해야합니다. docs.castleproject.org/(S(hucszcu5ilznbv45fvrim355))/... 3.0 베타 버전의 경우 개념은 그대로 있지만 일부 API가 변경되었습니다. 같은. 도코가 완벽하지 않다는 것을 알려주십시오. –

+0

나는이 일을 할 수있었습니다. 한 시간 안에 내 자신의 대답으로 링크와 설명을 게시 할 것입니다 (나 같은 저 카르마 사용자는 8 시간 이내에 우리 자신의 질문에 대답 할 수 없습니다). – ninjeff

10

당신은 DI 컨테이너 (성 윈저) 기능 구성 수행하기 위해 노력하고 있지만, 실제로 객체 구성을 대상 것

짧은 대답. 그것은 단지 당신에게 많은 마찰을 줄 것입니다. 제 추측으로는 다른 용기들과 같은 경험을하게 될 것입니다.

DI 컨테이너는 객체 지향 개념, 특히 SOLID를 중심으로 설계되었습니다. 이러한 원리는 Constructor Injection 및 Auto-wiring과 같은 것들을 내재적으로 이해하도록 설계 되었기 때문에이 원리들로 잘 작동합니다.

더 기능적인 접근 방식에는 아무런 문제가 없지만 아직 오브젝트 구성 대신 기능 구성을 기반으로 만들어진 DI 컨테이너를 아직 보지 못했습니다.

긴 대답은

DI에 대한 일반적인 원칙으로 대표단의 사용은 몇 가지 이유 (적어도 .NET에서) 정적으로 입력 된 언어로 문제가 될 경향이있다. 개념적으로 delegate can be considered as an anonymous Role Interface 이후이 접근법에는 아무런 문제가 없습니다. 그러나 형식 모호성 때문에 다루기 힘들어하는 경향이 있습니다.

내가 일반적으로 볼 수있는 가장 일반적인 방법은 BCL의 내장 대표와 같은 Func<T>, Action<T> 등을 사용하는 것입니다.그러나 소비자가 Func<string>에 의존하는 소비자가 많을 수 있습니다. 소비자가 Func<string>을 요구하기 만해도 동일한 역할의 대리인이 필요하지는 않습니다. 위임자와 DI를 기계적으로 사용할 수는 있지만 대리자는 응용 프로그램 역할을 숨 깁니다.. 역할 만 사라지고 역학 만 남습니다. 당신이 도로를 탈 경우

public delegate IEnumerable<Product> DGetProducts(); 

그러나, 아무 것도 얻은되지 않은 : 영업에서 제안이 위양에 의해 제안

는 그런 다음, 각 역할에 대한 사용자 정의 위임을 정의 할 수 있습니다. 각 역할에 대해 '역할 위임자'를 정의해야합니다. 비슷한 인터페이스를 정의하는 것을 대비하고있는 유일한 절약 꺾쇠 괄호의 커플 명시 적 방법을 정의라고는 명확해야한다 :

public interface IProductSource { IEnumerable<Product> GetProducts(); } 

많은 오버 헤드 (있는 경우)이 아니다.

또한이 토론에서 살펴 봐야 할 수 있습니다 : 흥미로운 접근 방식이다 http://thorstenlorenz.wordpress.com/2011/07/23/dependency-injection-is-dead-long-live-verbs/

+0

답장을 보내 주셔서 감사합니다. 나는 실제로 완전히 기능적인 접근 방식을 시도하지는 않지만 하이브리드 접근 방식을 실험하고 있습니다. 함수를 사용하는 것의 장점과 단점을 다양한 개념의 객체와 그들이 얼마나 잘 상호 작용 하는지를 보려고합니다. – ninjeff

+0

인터페이스 오버 헤드와 관련하여 인터페이스 자체보다는 구현 클래스 길이가 더 깁니다. – ninjeff

1

크 르지 스토프 (Krzysztof)의 지침에 따르면, 나는 이것을 처리하기 위해 커스텀 액티베이터를 쓸 수 있었다. 출처는 github입니다. (질문의 예를 다음) 같은

등록 정적 대표 :

container.Register(Component. 
    For<DGetProducts>(). 
    ImplementedBy(typeof(DataContextFunctions)). 
    Named("GetProducts"). 
    Activator<StaticDelegateActivator>()); 

코드는 크게 DefaultComponentActivator의 재 작성합니다. 또한 내부적이기 때문에 Windsor 소스 코드에서 DependencyTrackingScope을 복사하여 붙여 넣어야했습니다.

테스트 프로젝트의 단일 "테스트"는 단일 유스 케이스 만 포함합니다. 프록시와 같은 고급 시나리오에서는 작동하지 않을 것이라고 생각합니다.

나는 Krzysztof의 답변을 받아 들였습니다. 그의 지침에 따라 해결책이 나왔습니다.

관련 문제