4
如何將Task<object>
轉換爲Task<T>
其中T未知?將任務<object>轉換爲任務<T>其中T未知
例如 Task<object> to Task<int>
interface IAsyncActions
{
Task<int> GetValueAsync();
}
class Proxy : RealProxy
{
public Proxy() : base(typeof(IAsyncActions)) { }
public override IMessage Invoke(IMessage msg)
{
var call = (IMethodCallMessage)msg;
var method = (MethodInfo)call.MethodBase;
if (method.ReturnType.IsSubclassOf(typeof(Task)))
{
// return type is Task<T>
Task taskResult = AsyncMethod2(call);
return new ReturnMessage(taskResult, null, 0, call.LogicalCallContext, call); // InvalidCastException if taskResult not a Task<int>
}
else
{
// ...
return null;
}
}
static void Main()
{
Proxy p = new Proxy();
IAsyncActions tProxy = (IAsyncActions)p.GetTransparentProxy();
int result = tProxy.GetValueAsync().Result; // InvalidCastException
}
// This method works fine
Task AsyncMethod(IMethodCallMessage call)
{
Task<int> task = Task.FromResult(1234);
return task;
}
// This method does not work
Task AsyncMethod2(IMethodCallMessage call)
{
Type taskReturnType = ((MethodInfo)call.MethodBase).ReturnType; // Task<int>
Task<object> result = Task.FromResult<object>(1234);
// converting result to taskReturnType
// ...
//
return result;
}
}
我找到了一個解決方案,但它是相當昂貴:
Task AsyncMethod2(IMethodCallMessage call, MethodInfo method)
{
PropertyInfo resultProp = method.ReturnType.GetProperty("Result");
Type taskResultType = resultProp.PropertyType;
Type tcs = typeof(TaskCompletionSource<>);
Type[] typeArgs = { taskResultType };
Type genericTcs = tcs.MakeGenericType(typeArgs);
var taskProperty = genericTcs.GetProperty("Task");
object tcsInstance = Activator.CreateInstance(genericTcs);
MethodInfo setResult = genericTcs.GetMethod("SetResult");
MethodInfo setException = genericTcs.GetMethod("SetException", new Type[] { typeof(IEnumerable<Exception>)});
var setEx = (Action< IEnumerable<Exception>>)setException.CreateDelegate(typeof(Action<IEnumerable<Exception>>), tcsInstance);
Task task = (Task)taskProperty.GetValue(tcsInstance);
Task<object> result = new Task<object>(delegate
{
//throw new InvalidOperationException("qwerty");
return 1234;
});
result.Start();
result.ContinueWith(x =>
{
var args = new object[] { x.Result };
setResult.Invoke(tcsInstance, args);
}, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnRanToCompletion);
result.ContinueWith(x =>
{
setEx(x.Exception.InnerExceptions);
}, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnFaulted);
return task;
}
點是代碼必須被異步執行,這就是爲什麼我沒有1234的價值,同時任務
我幾乎可以肯定的是https://msdn.microsoft.com/en-us /magazine/dn574805.aspx(Unity的異步攔截器)包含您正在查找的確切代碼。 –
這很難理解,但這真的是我在找的,謝謝 – Miles