c# - 异步委托转换/转换
问题描述
我有一些财产类:
public class Test<TInput, TResult>
{
public Func<Func<TInput, TResult>, Func<TInput, TResult>> MyProperty { get; set; }
}
TResult
类型可以是任何类型:int
, decimal
, Task
, Task<>
.
假设TResult
是Task
或Task<>
(仅用于此示例)。请不要建议转换为Func<TInput, Task<TResult>>
- 这对我来说是不可能的。
现在我有一些方法(不编译,见下文):
public void MyMethod(Func<TInput, Task<bool>> predicate, Func<TInput, TResult> ifTrue)
{
this.MyProperty = inputDelegate => async input =>
{
var predicateResult = await predicate.Invoke(input);
return predicateResult ? await ifTrue.Invoke(input) : await inputDelegate.Invoke(input);
};
}
显然有编译时错误说async
不能在这里使用,因为这个委托的返回类型应该是Task
-like or void
(我知道TResult
是Task
或者我可以检查,但编译器不知道)。
我也尝试继续:
public void MyMethod2(Func<TInput, Task<bool>> predicate, Func<TInput, TResult> ifTrue)
{
this.MyProperty = inputDelegate => input =>
{
return predicate.Invoke(input)
.ContinueWith(t => t.Result ? ifTrue.Invoke(input) : inputDelegate.Invoke(input));
};
}
此方法也不会编译为 continuation 结果 is not TResult
, but Task<TResult>
。
我想应该有办法做到这一点(我正在玩铸造和委托转换,但我无法让它工作)。
还要记住,它不允许阻塞异步,所以不能只使用.Result
on.Wait()
任务。
先前关于TResult
is Task
-like 类型的假设是否有可能以某种方式处理这种情况?
谢谢
更新
我试图等待内部继续predicate
:
public void MyMethod3(Func<TInput, Task<bool>> predicate, Func<TInput, TResult> ifTrue)
{
this.MyProperty = inputDelegate => input =>
{
var continuationTask = predicate.Invoke(input)
.ContinueWith
(
async t =>
{
var task = (Task)(object)(t.Result ? ifTrue.Invoke(input) : inputDelegate.Invoke(input));
await task;
object result = null;
var taskType = task.GetType();
if (taskType.IsGenericType) // Task<>
{
// task is already completed because of await above
result = taskType.GetProperty(nameof(Task<object>.Result)).GetValue(task);
}
return result;
}
).Unwrap(); // make return type Task<object> from Task<Task<object>>
// InvalidCastException -> if TResult is something different form Task<object>
// if TResult is Task<int> then cast fails (because Task<int> and Task<object> are different types and task is not co/contra -variant)
return (TResult)(object)continuationTask;
};
}
但我不能将最终结果转换为所需的类型。
解决方案
似乎您的问题是让编译器相信您确定是/ 。TResult
Task
Task<T>
如果您使用扩展方法,您可以编写一个MyMethod
仅适用于Test
对象 where TResult
is 的Task
重载,以及另一个仅适用于Test
对象 where TResult
is 的重载Task<T>
:
public static class TestExtensions {
public static void MyMethod<TInput>(this Test<TInput, Task> test, Func<TInput, Task<bool>> predicate, Func<TInput, Task> ifTrue)
{
test.MyProperty = inputDelegate => async input =>
{
var predicateResult = await predicate.Invoke(input);
if (predicateResult) {
await ifTrue(input);
} else {
await inputDelegate(input);
}
};
}
public static void MyMethod<TInput, TResult>(this Test<TInput, Task<TResult>> test, Func<TInput, Task<bool>> predicate, Func<TInput, Task<TResult>> ifTrue)
{
test.MyProperty = inputDelegate => async input =>
{
var predicateResult = await predicate.Invoke(input);
return predicateResult ? await ifTrue(input) : await inputDelegate(input);
};
}
}
推荐阅读
- java - 如何在 JavaFX FXML 的窗格中编辑文本/图像/按钮
- wordpress - 显示 ACF 组中 Post Object 字段的数据
- elasticsearch - Elasticsearch 和 CAP 定理
- vbscript - vbscript:替换搜索字符串后的所有内联文本
- c++ - 无法从媒体会话中检索 IMFAudioPolicy
- unzip - 如何使用 Deflate64 压缩解压缩受密码保护的文件?我已经有密码了。在 python 或 vb.net 中
- python - Pycharm“无法使用创建进程”
- java - 在Java中生成某个异常/堆栈跟踪的次数?
- python - 修订后的 AWS SES 转发器示例代码 (Python) 无法转发电子邮件正文
- google-sheets - 阻止“+”和其他符号使用 Google Sheets API 生成公式