No, you can't change the type of an object once it's been created.
I'd also be reluctant to perform a copy via reflection. I would be tempted to create a new TaskCompletionSource
, and add a continuation from the returned task to set the result on the TaskCompletionSource
appropriately, tweaking the exception as you go.
I've got some code to do this already, in the case where you've actually got a Task<T>
:
var tcs = new TaskCompletionSource<SomeResultType>();
task.ContinueWith(completed =>
{
PropagateResult(completed, tcs);
}, TaskContinuationOptions.ExecuteSynchronously);
return tcs.Task;
...
// Generally useful method...
private static void PropagateResult<T>(Task<T> completedTask,
TaskCompletionSource<T> completionSource)
{
switch (completedTask.Status)
{
case TaskStatus.Canceled:
completionSource.TrySetCanceled();
break;
case TaskStatus.Faulted:
// This is the bit you'd want to tweak
completionSource.TrySetException(completedTask.Exception.InnerExceptions);
break;
case TaskStatus.RanToCompletion:
completionSource.TrySetResult(completedTask.Result);
break;
default:
throw new ArgumentException("Task was not completed");
}
}
Or if you're using C# 5 you could even just use:
public async Task MyMethod()
{
Task t = MethodIDontOwnThatReturnsTask();
try
{
await t;
}
catch(Exception e)
{
throw Tweak(e);
}
}
Note that if you need multiple exceptions to be thrown, this may end up being more problematic - it depends on your exact context.