gpt4 book ai didi

c# - 将 Task 转换为 Task,其中 T 未知
转载 作者:太空狗 更新时间:2023-10-30 00:23:44 25 4
gpt4 key购买 nike

如何转换 Task<object>Task<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;
}

最佳答案

创建这个方法:

public async static Task<T> Convert<T>(Task<object> task)
{
var result = await task;

return (T) result;
}

然后你可以做这样的事情(这是必需的,因为 T 只在运行时已知):

//Assuming that variable "task" is referencing the Task<object>

Type taskReturnType = ((MethodInfo) call.MethodBase).ReturnType; //e.g. Task<int>

var type = taskReturnType.GetGenericArguments()[0]; //get the result type, e.g. int

var convert_method = this.GetType().GetMethod("Convert").MakeGenericMethod(type); //Get the closed version of the Convert method, e.g. Convert<int>

var result = convert_method.Invoke(null, new object[] {task}); //Call the convert method and return the generic Task, e.g. Task<int>

关于c# - 将 Task<object> 转换为 Task<T>,其中 T 未知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34561106/

25 4 0