2014-05-23 2 views
2

Task으로 다운 캐스트되었을 때 Task<T>의 결과를 얻을 수있는 방법이 있습니까? 이것이 리플렉션과 관련이 있다는 것을 알고 있지만, 없으면 할 수있는 방법이 있습니까? 아마도 Expression을 사용했을까요? 는 여기에 내가 뭘 원하는지의 예 :일반 작업이 아닌 결과 얻기

RunResult RunTask(Task task) 
{ 
    task.Wait(); 

    object result = ???; 

    if (result is RunResult) 
     return (RunResult)result; 

    return RunResult.Success; 
} 

내가 다른 과부하를함으로써이 작업을 수행 할 수 있다는 것을 알고,하지만 난 행동이 과부하가 선택됩니다에 따라 변경됩니다 것을 좋아하지 않는다.

작업에 결과가 없으면이 상황에서 null이 좋습니다.

+0

작업을 '작업 (으)로 전환하는 편이 낫습니다. – Lee

+0

@Asad 나는 동의할만한 좋은 방법 이겠지만 불행히도 작업은 이미 기본 유형으로 시스템을 통과하고 있습니다. – Janiels

+0

'RunResult'는 열거 형일뿐입니다. 그러나 훨씬 더 복잡 할 수 있습니다. – Janiels

답변

7

이것은 Task<RunResult> 인 것으로 보입니다. 맞습니까? 그런 다음 해당 유형으로 변환하고 결과를 추출하십시오.

이 추측이 잘못 되었다면 dynamic을 사용하면 Result 속성 값으로 신속하게 이동할 수 있습니다.

((dynamic)myTask).Result 

지금이 결과 값은 그래서 당신이 그것을에서 데이터를 추출하는 방법을 모르겠어요 유형 dynamic이다.

+0

이것은 작동 할 것입니다 (결과는 객체에 할당 될 수 있습니다. 잡히지 않는 일반적인'Task' 일 경우). 불행히도 DLR은 다른 짐승이다. – Janiels

+0

실제 제네릭 형식 매개 변수가 무엇인지 아십니까? 그런 다음 그 유형으로 캐스트하십시오. – usr

+0

데이터에 대한 변환을 실행하기 전에 테스트를 거쳐야하므로 정상적으로 작동합니다. 그것을 사용하는 좋은 장소 ! – David

3

ResultRunResult에서 파생되는 것 인 Task<T> 인스턴스를 전달하면이 값이이 함수의 반환 값으로 사용됩니다. 그렇지 않으면 null이됩니다.

RunResult RunTask(Task task) 
{ 
    task.Wait(); 
    var type = task.GetType(); 
    if (!type.IsGenericType) 
    { 
     return null; 
    } 
    //Could also use: ((dynamic)task).Result as RunResult 
    return type.GetProperty("Result").GetValue(task) as RunResult; 
} 
+0

그래, 그렇게 생각 하겠지만'RunResult'를 반환 할 수있는'Task '이있는 경우를 생각해보십시오. – Janiels

+0

@Janiels이 문제를 처리하도록이 업데이트했습니다. –

+0

나는 이것을하기 위해 Reflection보다 다른 방법이 있기를 바랬다. – Janiels

2

Task은 "결과"속성을 노출하지 않으며, Task가 (즉, <T><out T>되지 않습니다) contravariant하지 않기 때문에 당신은 단순히 Task<object>으로 캐스팅 할 수 없습니다.

리플렉션을 제외한 다른 방법은 코드를 처리하는 일반적인 방법을 사용하는 것입니다. Methods는 generics 일 수 있기 때문에이를 통해 작업에 전달할 수 있습니다. 이것은 generic paraneters를 명시 적으로 설정하지 않고 메서드를 호출 할 수 있다는 부가적인 이점을 가지고 있습니다. 왜냐하면 컴파일러에서 사용법으로부터 유추 할 수 있기 때문입니다.

RunResult RunTask<T>(Task<T> task) 
{ 
    task.Wait(); 

    T result = task.Result; 

    if (result is RunResult) 
     return (RunResult)result; 

    return RunResult.Success; 
} 
+0

인터페이스와 델리게이트 만 반역/공변 유형 매개 변수를 가질 수 있으므로 T 공변수를 만들 수도 없습니다. 그러나이 접근법의 문제점은 티모시 실즈의 답변과 같습니다. 우리는 여전히'Task '과'Task '를 체크해야합니다; 잠재적으로 많은 다른 변이. – Janiels

+1

나는 당신의 질문을 정말로 얻지 못한다. 일반이 아닌 Task에서 Result를 추출하고 RunResult가 제공하지만 RunResult에 결과를 확인하고 캐스트하지 않으려는 경우 그 외에도 리플렉션 및 동적 입력 사용을 거부합니다. 제안 된 모든 가능성을 거절하는 대신 정답에 대한 기준은 무엇인지 말해주십시오. – Edin

+0

내 질문은 Reflection없이 할 수 있다면 (내 질문에 실제로 말합니다)입니다. 동적 인 방법은 좋은 방법이지만 불행하게도 DLR을로드합니다.이 경우 Reflection으로 되돌아갑니다. 'Task '일 수 있고 여전히'RunResult'를 리턴 할 수 있기 때문에'Task'을'Task '으로 던질 수 없습니다. 더 복잡한 유형이라면'Task '의 다양한 변형이있을 것입니다. – Janiels