当属性名称与类名称匹配时该怎么办?

14
在我们的 C# 代码中,有一个名为 Project 的类。我们的基础 BusinessObject 类(所有业务对象都继承自它)定义了一个属性:
public Project Project { get; set; }
只要我们在 C# 代码库中保持不变,这通常不是问题。但是,这些业务对象类在 web 服务中公开。一些使用语言(例如 Flex 的 actionscript)无法处理具有与其类相同名称的属性。
在我们的代码中,这种命名冲突随处可见。有时更改属性或类的名称很容易。有时则非常困难。我们已经竭尽全力,无法想出一个有效的标准方法来处理此问题。可以将 Project 类重命名为 ProjectType 或 ProjectInfo,但这很丑陋并且会破坏所有消费方现有的代码。我们可以将类型名称保持不变,并将属性名称更改为 ProjectInfo,但会导致相同的问题。
是否有任何指导或最佳实践可以应对这种情况?
编辑:
回应一些给出的建议:
- 方法不会公开,因此我们无法使用方法。 - 我希望有一个符合 Microsoft 自己命名规范的标准命名约定。 - 为 Flex 公开不同的合同可能是一个选项。但是,我们正在使用 Weborb 进行 Flex 互操作性。Weborb 使用反射完全匹配属性名称,而不是使用 XML 或 SOAP 序列化。如果有人了解有关使用 Weborb 进行自定义序列化的更多信息,那将非常有帮助。
第二次编辑:
供参考,我们最终将属性重命名为类似以下内容:
public Project ProjectInfo { get; set; }
6个回答

4
似乎你已经有了一个名字有问题的网络服务,这是一个棘手的问题。如果你不能更改任何内容而不破坏现有客户端,并且如果你不能保持原样而不破坏Flex,那么就必须做出取舍。
你可以在不同的URL上公开一个并行API。我同意shahkalpesh的建议,使用Get/Set方法来处理属性问题。好处是你只需要做出决定一次,然后保持一致,而不需要每次都考虑这个问题。这也意味着你可以根据第一个API自动创建第二个API。

我们的目标是找到一个不会破坏Flex的解决方案。我们可以重构.NET代码,只是需要一些时间。我希望也许有一个标准的命名约定,可以防止这个问题再次发生。 - davogones
如上所述,方法不会通过网络公开,因此它们无法帮助。公开不同的契约可能是一个选项。但是,我们正在使用Weborb,它有自己的序列化方案,使用反射来查找确切的成员名称,而不是使用xml序列化。 - davogones
标准的.NET命名约定并不试图解决这个问题,因为通常这不是一个问题。听起来你正在使用的技术可能不太适合这项工作 :( - Jon Skeet

2

我认为最好的解决方案是重构你的项目,将对象Project重命名为WnProject、ProjectBase或其他与项目相关的名称。

这是你的API,任何使用它的人都必须理解可能会有破坏性变更,这是依赖外部资源的成本。


0

那么老的方法呢?(GetProject/SetProject或者像.NET一样的方式-Thread.CurrentThread)


除了 Web 服务代理对象上的属性是基于元数据的,没有方法,只有数据... - Marc Gravell
是的,方法不会通过网络公开,只有属性和字段。所以很遗憾这样做行不通。 - davogones

0

我知道这是一个老问题,但它可能会帮助其他人。

为什么不为不支持相同属性名称和类型的消费者提供不同的WSDL?
在WSDL中重命名复杂类型(而不是元素名称!)

从现在你(应该)拥有的内容:

<xs:element name="Project" type="Project"/>

<xs:complexType name="Project">
  <xs:sequence>
    <xs:element name="Title" type="xs:string"/>
    <xs:element name="Description" type="xs:string"/>
  </xs:sequence>
</xs:complexType>

至:

<xs:element name="Project" type="ProjectType"/>

<xs:complexType name="ProjectType">
  <xs:sequence>
    <xs:element name="Title" type="xs:string"/>
    <xs:element name="Description" type="xs:string"/>
  </xs:sequence>
</xs:complexType>

在这种情况下,SOAP消息将保持完全相同,这意味着您无需重新编译解决方案或提供另一个服务。
此外,其他消费者也不必更改任何内容。

到现在为止,我已经好几年没有在.NET中使用Web服务了!如果我的记忆没有出错的话,WSDL是自动生成的,不能自定义。是否有一种属性可以允许您自定义自动生成的属性名称? - davogones
我没有测试过,但我认为你要找的属性是:System.Xml.Serialization.XmlRootAttribute,如http://msdn.microsoft.com/en-US/library/awac9czf(v=vs.80).aspx所示。或者,您可以禁用向消费者显示WSDL(在URL中添加?wsdl),并根据消费者技术为他们提供单独的WSDL(https://dev59.com/XU_Ta4cB1Zd3GeqPDsE1)。 - Nullius
已经过了好几年,我的.NET知识有些生疏了,但似乎XmlRootAttribute用于类型而不是属性。至于提供单独的WSDL/端点,那将是一个相当繁重的维护负担。我们有许多服务和合同需要维护和公开。在项目的整个生命周期中,我从未手动触碰过WSDL文件。 - davogones

-1

虽然这对于外部语言并没有太大帮助,但是可以给命名空间取别名(假设类Project在与具有属性Project的类不同的命名空间中),方法如下:

using ns = MyProject.Namespace;

然后你只需要做:

var newProject = new ns.Project();

我真的不太明白这与问题有什么关系,因为它涉及到通过WSDL公开对象,而不是他的内部代码。 - Chris Marisic

-3

一个变量的名称在一种语言中有什么关系与Web服务?

如果在XML绑定中暴露了实现细节,那么某些人就必须非常懒惰。

整个WSDL/SOA的重点是你拥有一个独立于实现的消息规范。如果你从源代码生成消息规范,或者从规范生成源代码而不允许生成对象的变化,那么你最终会得到紧密耦合的系统。这种紧密耦合的一个症状是得到不合法标识符的变量/属性名称。服务(而不是RPC)没有紧密耦合。你不应该因为服务的实现而改变你的服务实现 - 如果你必须这样做,那么你的堆栈中有些东西是错误的。这也适用于成员变量/属性以及方法。


谁提到了变量?类/属性名称是基于WSDL的Web服务的元数据的一部分。所选择的名称是有效的(如果不幸的话)- 如果有什么问题,那就是Flex绑定器不够标准... - Marc Gravell
成员变量是“属性”的另一种术语。 - Pete Kirkham

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接