2012-05-31 2 views
8

나는 다음과 같은 시나리오가와 제네릭 메서드 호출 :올바른 파생 형

내가 세 가지 클래스가을의 그들 A, BC를 호출 할 수 있습니다. 공통점은 동일한 인터페이스 인 ISomeInterface에서 상속 받고 Entity Framework를 사용하여 엔터티에 매핑되는 클래스라는 것입니다.

이 인터페이스를 구현하는 개체 목록을받은 메서드가 있지만 개체 자체는 A, B 또는 C의 인스턴스가됩니다.

방법 쉘이 문제는 ProcessEntity 방법입니다, 지금이

public void MyMethod(List<ISomeInterface> entityList) 
{ 
    foreach(var entity in entityList) 
    { 
    ProcessEntity(entity); 
    } 
} 

것 같습니다. 이 유형이나 단체에 따라 데이터베이스에서 일치하는 요소의 테이블을 검색해야하는 일반적인 방법이다, 그래서 다음과 같습니다

public void ProcessEntity<T>(T entity) 
{ 
    using(var repository = new DbRepository()) 
    { 
    var set = repository.Set<T>(); 
    ... 
    } 
} 

문제는 TISomeInterface 때문에 라인 var set = repository.Set<T>();이 실패한다는 것입니다 이 경우 실제 유형 (A, B 또는 C)이 아니므로 주어진 유형과 관련이없는 예외를 제공합니다. 이는 이해할 수 있습니다.

내 질문은 : 어떻게 ProcessEntity 목록에서 개체의 실제 형식 및 그들이 구현하는 interfacetype 호출 할 수 있습니다.

답변

13

엔터티를 ProcessEntity에 전달할 때 dynamic 키워드를 적용 할 수 있습니다. 이 경우 엔티티의 실제 유형은 런타임에 결정됩니다.

public void MyMethod(List<ISomeInterface> entityList) 
{ 
    foreach(var entity in entityList) 
    { 
    dynamic obj = entity; 
    ProcessEntity(obj); 
    } 
} 
+1

트릭을 수행 할 수도 있습니다. 나는'ProcessEntity (obj);를'ProcessEntity (obj as dynamic); '로 바꾼다. 동적 인 사용에 대해 나는 몰랐다.고마워요 :) –

+0

@ ØyvindKnobloch-Bråthen 예,이 런타임 형식화가 많이 좋아요 –

2

글쎄, 당신은 방문자와 같은 트릭을 할 수있는 다음과 같은 해결 방법 : 단지 ep.ProcessEntity<A>(this)A에 구현 (와 같은 방법으로 ISomeInterface

  • 의 방법 Process(EntityProcessor ep)를 정의

    1. BC)
    2. 루프에 ProcessEntity(entity) 대신 entity.Process(this)을 호출하면됩니다.

    은 (메소드 이름은 아마도없는 깨끗한있다, 그러나 당신은 생각을해야한다)

  • +0

    이 작동하지만, lazyberezovsky의 대답은 나를 위해 훨씬 더 청소기입니다. 그 이유는 A, B에 더 많은 로직을 넣을 필요가 없다는 것을 의미합니다. 와 C (이 유형 중 20 개는 3이 아닌 20 개가 있습니다.)) –

    +0

    @ Øyvind : 글쎄, 내 솔루션은 더 많은 작업이 필요하지만 컴파일시 필요한 메소드의 존재를 확인합니다. 또한 약간 더 빨라질 수도 있습니다. – Vlad

    +0

    나는 당신의 요지를 보았지만 다이나믹을 사용하면 필요한 방법이 전혀 없기 때문에 클래스 A, B, C가이 기능에 대한 지식을 갖고 있지 않은 것을 선호합니다. 또한 동일한 패턴을 따르도록 만들어진 새로운 클래스에이 추가 기능을 추가하는 것을 기억할 필요가 없음을 의미합니다. –

    2

    당신은 그것을 호출 한 후 제네릭 메서드 정의를 얻을 리플렉션을 사용할 수 있습니다, 예를 들면 :

    var method = typeof(ClassContainingProcessEntity) 
        .GetMethod(ProcessEntity) 
        .MakeGenericMethod(entity.GetType); 
    method.Invoke(this, entity); 
    

    유형별로 메소드를 캐시 할 수 있으며, 성능이 중요한 경우 일종의 델리게이트 팩토리를 사용하여 런타임에이를 컴파일 할 수 있습니다.

    또는 Visitor pattern

    +0

    그래, 둘 다 잘 돌아가고 내가 여기에 더 좋은 대답이 없다면 나는 반사 경로로 갈 생각이다. 그래도 훨씬 더 깨끗한 동적 인 픽스처럼 보입니다. 귀하의 의견을 주셔서 감사합니다 :) –