3

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

我打算通过以下方式连接到服务(WCF)WsdlService<"http://someurl/some.svc?wsdl">

它失败了:

类型提供程序 '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:“c:\Users\someuser\AppData\Local\Temp\tmp6E6C.cs”中的“System.Data.DataRowState”类型与导入的“System.Data”类型冲突。 'c:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Data.dll' 中的 DataRowState'。使用 '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# 并同时学习的目的;-)

4

2 回答 2

3

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

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

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

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

于 2012-10-19T16:16:19.193 回答
0

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

我现在做了以下事情:

  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)\参考 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 部分添加引用时,如何在运行 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”报告错误:错误:无法为传递给 /collectionType 选项的值 System.Collections.Generic.List'1 加载任何类型。确保通过 /reference 选项指定此类型所属的程序集。

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

有什么想法可以进一步调查或解决这个问题?

于 2012-10-29T12:30:16.720 回答