我目前正在尝试创建一个 IHttpActionInvoker
与 ASP.NET Web API 一起使用,允许结果为 Async<'T>
.目前,我忽略了 IHttpActionResult
的转换s且只关心HttpResponseMessage
和一个 'T
类型的值.我目前有以下实现:
type AsyncApiActionInvoker() =
inherit Controllers.ApiControllerActionInvoker()
override x.InvokeActionAsync(actionContext, cancellationToken) =
if actionContext = null then
raise <| ArgumentNullException("actionContext")
let actionDescriptor = actionContext.ActionDescriptor
Contract.Assert(actionDescriptor <> null)
if actionDescriptor.ReturnType = typeof<Async<HttpResponseMessage>> then
let controllerContext = actionContext.ControllerContext
Contract.Assert(controllerContext <> null)
let task = async {
let! asyncResult = Async.AwaitTask <| actionDescriptor.ExecuteAsync(controllerContext, actionContext.ActionArguments, cancellationToken)
// For now, throw if the result is an IHttpActionResult.
if typeof<IHttpActionResult>.IsAssignableFrom(actionDescriptor.ReturnType) then
raise <| InvalidOperationException("IHttpResult is not supported when returning an Async")
let! result = asyncResult :?> Async<HttpResponseMessage>
return actionDescriptor.ResultConverter.Convert(controllerContext, result) }
Async.StartAsTask(task, cancellationToken = cancellationToken)
else base.InvokeActionAsync(actionContext, cancellationToken)
这适用于 Async<HttpResponseMessage>
只要。如果我尝试转换为 Async<_>
,我得到一个异常,说明我无法转换为 Async<obj>
.我也无法正确检测到 actionDescriptor.ReturnType
是否存在。是一个 Async<_>
.这并不让我感到惊讶,但我不确定如何解决这个问题。
最佳答案
作为一个选项(浏览器编译的代码,可能包含错误)
let (|Async|_|) (ty: Type) =
if ty.IsGenericType && ty.GetGenericTypeDefinition() = typedefof<Async<_>> then
Some (ty.GetGenericArguments().[0])
else
None
type AsyncApiActionInvoker() =
inherit Controllers.ApiControllerActionInvoker()
static let AsTaskMethod = typeof<AsyncApiActionInvoker>.GetMethod("AsTask")
static member AsTask<'T> (actionContext: Controllers.HttpActionContext, cancellationToken: CancellationToken) =
let action = async {
let task =
actionContext.ActionDescriptor.ExecuteAsync(
actionContext.ControllerContext,
actionContext.ActionArguments,
cancellationToken
)
let! result = Async.AwaitTask task
let! asyncResult = result :?> Async<'T>
return actionContext.ActionDescriptor.ResultConverter.Convert(actionContext.ControllerContext, box asyncResult)
}
Async.StartAsTask(action, cancellationToken = cancellationToken)
override x.InvokeActionAsync(actionContext, cancellationToken) =
if actionContext = null then
raise <| ArgumentNullException("actionContext")
match actionContext.ActionDescriptor.ReturnType with
| Async resultType ->
let specialized = AsTaskMethod.MakeGenericMethod(resultType)
downcast specialized.Invoke(null, [|actionContext, cancellationToken|])
| _ -> base.InvokeActionAsync(actionContext, cancellationToken)
关于asp.net - 在 F# 中,如何判断对象是否为 Async<_>,以及如何将其转换为 Async<_>?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28734476/