【问题标题】:F# TypeProvider cannot load typeF# TypeProvider 无法加载类型
【发布时间】:2015-01-24 06:21:47
【问题描述】:

我正在尝试使用 F# 类型提供程序编写一个简单的 SOAP 客户端。完整的程序是:

open System
open System.Runtime.Serialization
open System.ServiceModel
open Microsoft.FSharp.Data.TypeProviders

type EntrezService = WsdlService<"http://eutils.ncbi.nlm.nih.gov/soap/v2.0/eutils.wsdl">

[<EntryPoint>]
let main argv =
    let client = EntrezService.GeteUtilsServiceSoap()
    try
        let req = EntrezService.ServiceTypes.eSearchRequest()
        let res = client.run_eSearch req
        printfn "%A" res
    with
        | ex ->
            let rec inner (ex : Exception) =
                if ex.InnerException <> null then
                    inner ex.InnerException
                printfn "%s" ex.Message
            inner ex
    0

不幸的是,看起来应用在进行 SOAP 调用之前就崩溃了,并出现以下 TypeLoadException:

无法从程序集“EntrezGeneAdaptor”加载类型“UrlTypeLNG”, 版本=0.0.0.0,文化=中性,PublicKeyToken=null '。

此类型在 WSDL 中定义。我不知道为什么 .NET 会尝试从我的程序集中加载它。

堆栈跟踪表明异常是从System.Xml.Serialization.XmlReflectionImporter.ImportMembersMapping 引发的。

这是怎么回事,有没有简单的解决方法?等效程序在 C# 中运行良好,那么这是 F# 类型提供程序的问题吗?

【问题讨论】:

  • 您的应用程序使用的目标 .NET 框架版本是什么? .NET 框架从您的程序集中加载类型,因为 WsdlService 生成了类型提供程序,并且它在您的程序集中以真实类型编译所有类型。顺便说一句,一切都在我的 FSI screencast.com/t/H6ax57QAM1
  • 我使用的是 .NET 4.5。有趣的是它对你有用。我会尝试从另一个盒子运行我的程序。也许我有某种配置问题。
  • 我在另一个盒子里试了一下,得到了同样的错误。 FWIW,我正在编译而不是从 FSI 运行。
  • FWIW,我也能够在 FSI 中使用它。知道为什么编译时它不起作用吗?
  • 真正的魔法 ;) 行为取决于服务。你能从你的机器上尝试另一个 wsdl 服务吗?

标签: .net soap f# wsdl type-providers


【解决方案1】:

在两种情况下,我遇到了类型提供程序运行编译但在 FSI 中没有(反之亦然)的问题。您可能已经发现第三个单一类型的提供商仍然有点前沿......

  1. 在使用类型提供程序的应用程序中缺少程序集绑定重定向。在这里查看一些 assembly redirect instructions 的 FSharp.Core。
  2. GAC 或 Visual Studios 执行目录中的库。我曾经有一个 nuget 包将自己解压缩到 Visual Studio 的 Common7 目录结构中,从那时起,FSI(和类型提供程序)总是使用那里的版本,因为 Visual Studio 在启动时加载它们向上。我花了几个月的时间才弄清楚发生了什么。

不知道这些是否是您的问题,但可能值得一试。

【讨论】:

    【解决方案2】:

    看起来问题是由 WSDL 引起的。该服务定义了一个名为“UrlType”的复杂类型,其中包含一个名为“LNG”的属性。不知何故,这被错误地组合成“UrlTypeLNG”。我手动编辑了 WSDL 以使用纯字符串而不是复杂类型,现在它似乎可以工作了。

    【讨论】:

    • 这也是一项公共服务。
    【解决方案3】:

    如果您正在使用无法编辑其 WSDL 的 3rd 方服务,您仍然可以绕过此问题。诀窍是在定义 WSDL 服务类型时使用LocalSchemaFileForceUpdate。在LocalSchemaFile 中指定.wsdlschema 文件名会创建所述文件并定期将缓存的WSDL 存储在其中。为防止定期重新生成此文件,还包括ForceUpdate = false。这允许您更改您的类型提供程序使用的临时 WSDL。确保每次都重建以使更改生效。另请注意,如果更改了 3rd 方服务的 WSDL,您可能必须手动重做此过程。

    类型定义可能如下所示:

    type SomeService = WsdlService<"http://3rdparty.net/wsdl/srv.wsdl",
                                   LocalSchemaFile = "srv_local.wsdlschema",
                                   ForceUpdate = false>
    

    【讨论】:

    • 是的,这就是我所做的。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-14
    相关资源
    最近更新 更多