【问题标题】:Auto-alias generated SOAP proxies自动别名生成的 SOAP 代理
【发布时间】:2014-04-01 14:31:48
【问题描述】:

我目前正准备在 .NET 项目 (C#) 中使用 SOAP web service,但是用于服务类型和操作的命名约定很糟糕 与C# .NET 项目的典型命名约定

我的问题本质上是:有没有办法在我的客户端实现中自动为生成的 SOAP Web 服务代理类型/方法设置别名?

我希望有某种方法可以使用别名映射执行 WSDL 的转换,这样生成的(或重新生成的)类型使用诸如 Contact 之类的名称,但映射到底层的 contactObject 定义。

由于我不知道可以在生成过程中执行的任何转换,因此我目前正在手动(或至少在 T4 的帮助下)为类编写包装器,但这似乎是不必要的间接;更不用说,很痛苦。

我正在阅读Svcutil 上的文档,但没有找到任何适用的标志。

【问题讨论】:

  • 在我提出更复杂的答案之前,让我知道this question 的答案是否有帮助。我之所以这么问,是因为 SOAP 服务中那些糟糕的名称似乎必须来自同一个来源,即自动生成的 DataContractFormat。您是否有权访问 SOAP 服务的程序集?如果可以仅重写 Web 服务接口层并使用其依赖项,那么您只需要 [XmlSerializerFormat] 属性。
  • @MarkBailey 我无权访问服务器端应用程序代码;它完全是第三方。糟糕的 SOAP 名称(我推测)可能是第三方命名约定的结果,很可能源自他们正在使用的任何平台的约定 (PHP, Java, *shrug*) 如果问题只是“字段”被附加到成员,我就接受它。
  • @MarkBailey 我刚刚发现 this answer 关于 Web Service Software Factory。也许类似的东西可以为我提供完成此任务所需的定制;我得读一读。不过,与此同时,我全神贯注于您复杂的答案;-)
  • 嗯,显然 Web 服务软件工厂不想安装,根据我正在阅读的内容,这似乎是一个“陷入困境”的情况......

标签: .net soap wsdl naming-conventions svcutil.exe


【解决方案1】:

我已将此发布到您的other question,但您说得对,它更适合这个:

我假设您通过使用“添加服务引用...”添加此第三方服务来使用它,该服务会为 Reference.cs 中的每个类自动生成一些代码,其签名可能看起来像这样:

[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.thirdpartyguys.net")]
public partial class qux: object, System.ComponentModel.INotifyPropertyChanged {

你希望它不是 qux,而是 Qux。如果到目前为止这一切都与您的模型相似,那么您只需将 qux 更改为 Qux,但将 TypeName="qux" 添加到 XmlTypeAttribute,并更改引用中对此类的所有引用。这会在 SOAP 中维护正确的 xml 架构,但让我们在项目中更改名称:

[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.thirdpartyguys.net", TypeName = "qux")]
public partial class Qux: object, System.ComponentModel.INotifyPropertyChanged {

当然,如果该 XmlType 属性尚未在定义命名空间的类上,您可以添加它。它只是没有命名空间参数。我刚刚对此进行了测试,它确实允许我使用该服务,并且只需在我使用它的任何地方以不同的名称调用一个对象。

这对你有用吗?

编辑:(向未来的读者简要介绍 SchemaImporterExtension 的想法) 据我了解,当从 WSDL 添加服务引用时,此扩展类可以调用与默认代码生成行为的偏差。您最终仍然拥有一些 Reference.cs 作为您的项目和服务之间的链接,但您可以更改生成的内容。因此,如果我们希望对象始终以大写字母开头,例如,我认为我们的想法是做这样的事情(未经测试):

public class test : SchemaImporterExtension
{
    public override string ImportSchemaType(string name, string ns, XmlSchemaObject context,
        XmlSchemas schemas, XmlSchemaImporter importer, CodeCompileUnit compileUnit,
        CodeNamespace codeNamespace, CodeGenerationOptions options, CodeDomProvider codeGenerator)
    {
        if (name[0].CompareTo('a') >= 0) //tests if first letter is lowercase
        {
            CodeExpression typeNameValue = new CodePrimitiveExpression(name);
            CodeAttributeArgument typeNameParameter = new CodeAttributeArgument("TypeName", typeNameValue);
            CodeAttributeDeclaration xmlTypeAttribute = new CodeAttributeDeclaration("XmlTypeAttribute", typeNameParameter);
            compileUnit.AssemblyCustomAttributes.Add(xmlTypeAttribute);
            return name.Substring(0, 1).ToUpper() + name.Substring(1);
        }
        return null;
    }
}

理论上,这将写入 XmlType 属性并将名称更改为正确的大小写,从而在 SOAP 中保持正确的 XML 映射。理论上,使用 SchemaImporterExtension 的优点是对服务引用的更新不会覆盖更改。此外,可以进行一般更改,而不是针对每个特定参考。

欢迎成功使用 SchemaImporterExtension 的人发表评论或编辑。

【讨论】:

  • 太棒了,谢谢@MarkBailey。正如我们discussed in chat,我将看看SchemaImporterExtension 方法,否则回退到XmlTypeAttribute + 重命名“所有的东西”;-)
  • 哇,SchemaImporterExtension 上的好例子。我仍在处理这个过程,但是当我回到我的机器并附加一个代码示例时,我将把它标记为答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-02
  • 1970-01-01
  • 2014-06-25
  • 2011-02-08
相关资源
最近更新 更多