【问题标题】:F# wsdl type provider error?F# wsdl 类型提供程序错误?
【发布时间】:2012-10-19 07:31:02
【问题描述】:

虽然我喜欢 F# 类型提供程序的想法,但我第一次认真尝试使用它们时失败了。

我打算使用 WsdlService<"http://someurl/some.svc?wsdl"> 连接到服务 (WCF)

它失败了:

类型提供者 'Microsoft.FSharp.Data.TypeProviders.DesignTime.DataProviders' 报错:tmp6E6C.cs(9409,26): error CS0644: “System.ComponentModel.PropertyChangedEventHandler”不能派生自 特殊类“System.MulticastDelegate” c:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll:(位置 与先前错误相关的符号)

还有很多其他可能不相关的警告:

tmp6E6C.cs(290,28):警告 CS0436:类型 'System.Data.DataRowState' 在 'c:\Users\someuser\AppData\Local\Temp\tmp6E6C.cs' 与 导入类型“System.Data.DataRowState” 'c:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Data.dll'。使用 'c:\Users\someuser\AppData\Local\Temp\tmp6E6C.cs' 中定义的类型。 tmp6E6C.cs(9427,17):(与先前警告相关的符号位置)

这是一个已知功能 ;-) 还是我用错了?

很遗憾,我无法发布 WSDL,而且它相当大,里面有很多类型,所以我必须承认我有些懒惰,也没有对其进行修剪。 OTOH,如果我确实知道 WSDL 的哪一部分有问题或造成了这个错误,我当然会把它放在这里。

更改 WSDL 也不是一个选项,所以我主要想知道为什么 F# WSDL 类型的提供程序不能处理这个 (WCF) WSDL,或者我做错了什么。

当被 C# 和 VS2010 中的 svcutil.exe 使用时效果很好。

我已经尝试了 WsdlTypeProvider 的所有参数,它们确实给出了相同的结果(当然 ForceUpdate 除外)。我应该使用 F# 以其他方式使用这些服务吗?

================================================ ================================= 添加信息(因为我是新手,不想回答。不要问为什么:):

谢谢大家的回答/评论。

我确实部分采用了这种方式(手动使用 svcutil)。正如我上面所说的,我尝试手动使用 svcutil,但在编译生成的 C# 代码(在 F# 之外的库中)时它失败了。

也就是说,我做了以下事情:

1) 通过在 VS 2010 GUI 中设置引用来创建合约。这按预期工作

2) 尝试使用命令行中的 svcutil 创建它。然后该文件的编译失败并出现同样的错误。

在我看来,从 cmd-line 在 svcutil 中发生的事情以及从 GUI 添加相同服务时使用 svcutil(或使用的内容)不会生成具有相同参数的代码时会发生什么。我想这部分是由于我尝试使用的是 WCF 服务而不是“干净”的 WSDL/web 服务,并且类型提供程序假定我尝试使用“干净”的 web 服务。

我没有找到任何 svcutil 处理此问题的参数或任何可能的参数组合,并不是说我确实尝试了所有组合排列,而是尝试了可能基于(试图)深入阅读的组合svcutil 的文档(而且我不是从 cmd-line 使用它的新手)。

到目前为止,我得出的结论是 svcutil 的一些“缺失”参数导致了这种情况,并且 F# 类型提供程序没有错。我仍然非常想以某种方式解决它,仍然使用 F# 类型提供程序,但后备是通过 C# 中的 GUI 生成代码,然后再次在 F# 中引用该部分代码。这不是我试图实现的优雅解决方案,因为我确实有很多服务,我非常想创建一种很好的原型设计和测试这些服务的方式。

另一个后备当然也会放弃整个 F# 部分而只进行一些单元测试等,但这又违背了潜入 F# 并同时学习的目的 ;-)

【问题讨论】:

  • “当被 C# 和 VS2010 中的 svcutil.exe 使用时效果很好”。这很有趣。我花了几天时间尝试将类型提供程序与真正的 Web 服务(包括 WSDL)一起使用,但在 F# 示例之外没有任何东西可以工作。所以我很想知道这可能是 F# 特有的问题,而不是一般的 .NET 问题...
  • 我肯定地认为这不是一个 .net 问题(它在使用 svcutil 时有效...提供者实现中未考虑 WSDL 的使用。当然也可能是我做错了什么。或所有的组合。 “很好”听到其他人在使用它时遇到了问题。您在尝试使用 WsdlProviders 时遇到了哪些错误?它也是 WCF 服务还是以其他方式创建的服务?
  • 在 VS2010 GUI 中添加引用时效果很好。如果从 cmd-line 使用 svcutil,如果从服务描述生成文件到 CS 文件,它会产生相同的错误。
  • 如果没有看到确切的 C# 和确切的 F# 代码,很难说“这在 C# 中有效,但在 F# 中失败”。如果有任何方法可以用两种语言发布一小部分代码来演示该问题,那将非常有帮助。说两种不同语言的代码相同是很长的一段话。
  • 是什么阻止您发布 WSDL?默默无闻的安全性?

标签: wcf f# wsdl svcutil.exe type-providers


【解决方案1】:

WSDL 类型提供程序(以及其他一些提供程序)在后台使用 SvcUtil 来完成繁重的工作。如果您打开 taskmgr 的 ProcExp 或其他类似工具,您可以看到在将 TP 代码粘贴到 Visual Studio 后生成了 SvcUtil 进程。至少使用 ProcExp,您可以看到带有参数的完整命令行。

因此,准确找出 TP 为您的服务调用的 SvcUtil 命令行,并检查它是否在 F# 环境之外工作。

SvcUtil 在 C#/VS 2010 中工作的事实很有趣。我假设如果您使用的是 F# TP,那么您现在就在 VS 2012 上。如果是这样,SvcUtil 本身的版本可能不同,这可能是相关的。

具体错误似乎与here 解释的相同,因此您的服务代码中可能有一些不完整的注释。

【讨论】:

  • 我认为该链接并不完全相关(可能是我不完全理解手头的问题!)。为什么我认为这在原始帖子的补充中得到了更多解释,简而言之,因为在 VS 2010 中使用 GUI 添加服务时,我能够生成正确的代码。在这两种情况下生成的代码是不同的。 Cmdline svcutil 假定一个“干净”的 wsdl,但 GUI 的东西“理解”它是一个 WCF(或其他)并以不同的方式处理 PropertyChangedEventHandler。
  • C# GUI 和 F# TP 都使用 SvcUtil 生成客户端代码。 SvcUtil 的使用中有 2 个变量 - SvcUtil 本身的版本,以及传递给它的参数。如果它在 VS 2010 C# 中工作,但不是在 VS 2012 F# 中工作,那么要么工具的版本不同,要么参数不同,或两者兼而有之。找出我们的区别是什么,这应该指向您下一步的修复/解决方法。我提供了链接以提示该工具可能失败的原因 - 也许最新版本比以前的版本更严格。
  • 我从 2010 年开始尝试使用 svcutil 的 cmdline 版本。在编译 C# 代码时它给出了相同的错误...似乎它也使用 2012 cmdline 生成了相同的代码。
  • @latkin "C# GUI 和 F# TP 都在使用 SvcUtil 来生成客户端代码":VS 2008 并非如此,请参阅 link。我认为 VS 2010 也不是这样:当我通过对话框添加服务引用时,svcutil.exe 永远不会在任务管理器中启动。我不知道 VS 2012。
  • @MarcSigrist - 你是对的,我之前的评论是不正确的。感谢您为未来的读者指出我的错误!我猜想回去,VS“添加服务引用”GUI确实使用了svcutil,但自从VS 2008以来,情况不再如此。现在我们最终发现这两种方法之间存在不一致 - 令人震惊!
【解决方案2】:

我无法离开这个问题......

我现在做了以下事情:

  1. 使用普通设置运行 svcutil:svcutil http://some.address/some/path.svc
  2. 使用更多设置运行:svcutil /r:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.5\System.dll" /r:"C:\Program Files ( x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.5\System.Data.dll"http://some.address/some/path.svc

这确实会在 C# 文件中产生以下差异(它存在于 1)中,而显然不存在于 2)中):

namespace System.ComponentModel
{
    using System;


    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
    [System.SerializableAttribute()]
    public partial class PropertyChangedEventHandler : System.MulticastDelegate
    {

        public PropertyChangedEventHandler(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : 
                base(info, context)
        {
        }
    }
}
namespace System.Data
{
    using System;
    using System.Runtime.Serialization;


    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
    [System.FlagsAttribute()]
    [System.Runtime.Serialization.DataContractAttribute(Name="DataRowState", Namespace="http://schemas.datacontract.org/2004/07/System.Data")]
    public enum DataRowState : int
    {

        [System.Runtime.Serialization.EnumMemberAttribute()]
        Detached = 1,

        [System.Runtime.Serialization.EnumMemberAttribute()]
        Unchanged = 2,

        [System.Runtime.Serialization.EnumMemberAttribute()]
        Added = 4,

        [System.Runtime.Serialization.EnumMemberAttribute()]
        Deleted = 8,

        [System.Runtime.Serialization.EnumMemberAttribute()]
        Modified = 16,
    }
}

这再次使文件在 2) 中编译,否则按预期进行。

然后有点奇怪的是:为什么在运行 svcutil 时 F# wsdl 提供程序中没有使用 System.dll? System.Data.dll 我有点理解,因为在运行 svcutil 时不是默认使用的(至少根据文档)。

OTOH 我还认为文档说如果程序集在 GAC 中,它应该使用它们。那么如何验证它们是否存在,和/或如果不存在则将它们加载到程序集中?

运行 gacutil -i System.dll(在 System.dll 的 4.5 版上)给出:

将程序集添加到缓存失败:尝试加载一个 格式不正确的程序。

是 64/32 位问题吗? (如果确实有任何相关性,我在 64 位窗口上)

或者换个说法:当我无法通过 WsdlProvider-part 直接添加引用时,如何在运行 svcutil 时将 System.dll 和 System.Data.dll 获取到部分引用?

我很确定它不使用 System.dll,因为如果我将 collectiontype 参数添加到 wsdlprovider:

WsdlService<"http://some.url/some/path.svc", "c:\\temp\\wsdl\\some.wsdlschema", true, ".", true, true, false, false, "System.Collections.Generic.List'1">

它还抱怨以下内容:

类型提供者 'Microsoft.FSharp.Data.TypeProviders.DesignTime.DataProviders' 报错:Error: No type could be loaded for the value System.Collections.Generic.List'1 传递给 /collectionType 选项。确保此类型所属的程序集是通过 /reference 选项。

如果引用 System.dll 应该可以直接使用(我认为)。

有进一步调查或解决此问题的想法吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多