2012-02-14 3 views
0

Medusa을 업데이트하려고하는데 현재 장식 된 POCO가 현재 List<DbParameter>을 사용하는 모든 곳에서 사용될 수 있습니다. 내가 겪고있는 문제는 잘못된 오버로드가 호출되고 있다는 것입니다. 여기에 제가 보는 것의 간단한 예입니다 :이 경우일반 매개 변수를 전달하면 잘못된 오버로드가 발생합니다.

void Run() 
{ 
    CallDoSomething<Program>("Hello World", new object()); 
    CallDoSomething<Program>("Hello World2", new List<int>()); 
} 

// `DoSomething<T>` represents the functions that do the heavy lifting 
public T DoSomething<T>(string someString, List<int> ints) where T : class 
{ 
    Console.WriteLine("List<int>: {0}", someString); 
    return default(T); 
} 
public T DoSomething<T>(string someString, object ints) where T : class 
{ 
    Console.WriteLine("object: {0}", someString); 
    // In my real implementation, this turns the object to a typed List<T> 
    // and passes it to the previous overload. 
    return default(T); 
} 

// We're trying to refactor the code in this method to reduce code duplication in 
// the `CallDoSomething<T>` methods that will actually be called by the end user 
internal T CallDoSomething<T, U>(string someString, U ints) where T : class 
{ 
    // Do a bunch of stuff here that would otherwise be duplicated by the `CallDoSomething<T>` methods 
    return DoSomething<T>(someString, ints); 
} 

public T CallDoSomething<T>(string someString, List<int> ints) where T : class 
{ 
    return CallDoSomething<T, List<int>>(someString, ints); 
} 
public T CallDoSomething<T>(string someString, object ints) where T : class 
{ 
    return CallDoSomething<T, object>(someString, ints); 
} 

는, 결과 출력은 다음과 같습니다

object: Hello World 
object: Hello World2 

내가 기대 동안이되고 :

object: Hello World 
List<int>: HelloWorld2 

두 경우 모두 객체이기 때문에 두 경우 모두 object 매개 변수를 사용하는 오버로드에 대한 것이 었습니다. 나는 (내가 아는 바로는) Generics와 과부하 해결이 런타임보다는 컴파일 타임에 처리되기 때문에 이것이 일어나는 것으로 생각된다.

나를 맞이한 첫 번째 대안은 Reflection을 사용하여 CallDoSomething<T, U>에서 호출을 동적으로 호출하는 것이지만 너무 어둡습니다. 대신 내가 와서 해결 방법은 작동하는 것 같다 CallDoSomething<T, U> 대리인을 전달 포함됩니다. 여기처럼 보이는 무엇 :이 작동하는 것 같다하고 코드 중복의 많은 양을 제거

void Run() 
{ 
    CallDoSomething<Program>("Hello World", new object()); 
    CallDoSomething<Program>("Hello World2", new List<int>()); 
} 

public T DoSomething<T>(string someString, List<int> ints) where T : class 
{ 
    Console.WriteLine("List<int>: {0}", someString); 
    return default(T); 
} 
public T DoSomething<T>(string someString, object ints) where T : class 
{ 
    Console.WriteLine("object: {0}", someString); 
    return default(T); 
} 

internal delegate T DoSomethingDelegate<T, U>(string someString, U ints) where T : class; 
internal T CallDoSomething<T, U>(string someString, U ints, DoSomethingDelegate<T, U> doSomething) where T : class 
{ 
    // Do a bunch of stuff here that would otherwise be duplicated by the `CallDoSomething<T>` methods 
    return doSomething(someString, ints); 
} 

public T CallDoSomething<T>(string someString, List<int> ints) where T : class 
{ 
    return CallDoSomething<T, List<int>>(someString, ints, DoSomething<T>); 
} 
public T CallDoSomething<T>(string someString, object ints) where T : class 
{ 
    return CallDoSomething<T, object>(someString, ints, DoSomething<T>); 
} 

있지만, 코드가 상당히 복잡합니다. 이 문제에 접근하는 더 좋은 방법이 있습니까?

답변

4

예, 컴파일시 오버로드가 해결됩니다. 당신은 이 같은 C# 4를 사용하는 경우이 실행 시간에 평가하는 강제 수 있습니다

internal T CallDoSomething<T, U>(string someString, U ints) where T : class 
{ 
    dynamic d = ints; 
    return DoSomething<T>(someString, d); 
} 

그러나 개인적으로 나는 당신이 가능하게 할 수있는 경우에 당신의 설계를 단순화하려고 것입니다. 이런 종류의 일은 지저분 해집니다. 매우입니다.

+0

저는 .NET 4에 있습니다. 따라서 '동적'이 내 마음을 넘어 섰지 만, 'ints'는 이미 제네릭이므로 많은 차이가 있다고 생각하지 않았습니다. 그것은 이해가된다. 디자인을 단순화하는 조언이 있습니까? –

+0

@ M.Babcock : 일반적이고 동적 인 것은 매우 다릅니다. generics는 * 컴파일 타임에 더 많은 유형 정보를 제공합니다. 동적은 * 실행 시간 *에 더 많은 유형 정보를 사용하는 것입니다. 디자인 단순화와 관련하여 더 많은 내용을 모른 채 말하기는 어렵습니다. –

+0

도움 주셔서 감사합니다. 위임자 솔루션은 .NET 4 외부에서 사용하도록 허용 할 것입니다. 대리자 솔루션이 작동하는 것처럼 보이지만 이런 식으로 진행하는 것이 아닌 이유를 알고 있습니까? –

관련 문제