asp.net - 在 F# 中,如何判断对象是否为 Async<_>,以及如何将其转换为 Async<_>?

标签 asp.net reflection asp.net-web-api f#

我目前正在尝试创建一个 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/

相关文章:

swift - 创建一个 [字符串 : Class] dictionary in Swift 4

c# - .NET core Web API,如何更改使用 IAsyncEnumerable 时返回的 XML 的根名称?

javascript - Breeze 部分初始化器

c# - 更新到 2.1 后 SignalR 不起作用?

c# - 如何获得 com+ 应用程序的所有 com+ 组件的列表?

c# - 如果它是反射中的集合,如何知道属性的类型?

c# - 在 Javascript 中获取属性背后的代码?

c# - .NET Core 中的程序集加载

c# - 如何更改默认的 ASP.NET MVC Web API 媒体格式化程序?

c# - 如何在Web api中压缩HttpClient post并接收数据