【问题标题】:WCF Generics - Why do DataContract and CollectionDataContract allow formatted naming, but not DataMember, OperationContract or ServiceContract?WCF 泛型 - 为什么 DataContract 和 CollectionDataContract 允许格式化命名,但不允许 DataMember、OperationContract 或 ServiceContract?
【发布时间】:2011-06-28 19:56:41
【问题描述】:

基本上如标题所说:

[DataContract(Name = "{0}Item")] //This will format properly
public class GenericItem<T>
{
    [DataMember(Name = "The{0}")] //This will NOT format properly
    public T TheItem { get; set; }
}

[CollectionDataContract(Name = "{0}Items")] //This will format properly
public SpecialCollection<T> : Collection<T> { }

[ServiceContract(Name = "{0}Service")] //This will NOT format properly
public interface IGenericService<T>
{
    [OperationContract(Name = "Get{0}")] //This will NOT format properly
    GenericItem<T> Get<T>();
}

那么,你有它...什么有效,什么无效...但问题是...为什么?显然.NET能够创建一个具体的类型和格式使用DataContractCollectionDataContract 并说明类型时的名称(即GenericItem&lt;Foo&gt;SpecialCollection&lt;Foo&gt;。那么为什么不让DataMember 也能够格式化呢?

ServiceContract/OperationContract 我可以理解为上面留下的方式(排序),但我不明白的是,当你给它一个具体的类型时,操作仍然无法正常工作:

[ServiceContract(Name = "FooService")]
public interface FooService : IGenericService<Foo> { }

public interface IGenericService<T>
{
    [OperationContract(Name = "Get{0}")] //This will NOT format properly
    T Get<T>();
}

再次,为什么?显然,我在这里声明了一个具体的 Foo 类型,这意味着 IGenericService 是一个 IGenericService 所以不应该格式化 OperationContract 名称,因为它知道类型吗?


更新:

我只记得为什么我对无法使用通用格式的 ServiceContract 感到不安......当我实现服务时,我正在给它一个具体的类型......

//See! I gave it a concrete type to go by!
[ServiceBehavior(...)]
public class MyService : IGenericService<Foo> { ... }

我为此创建了一个Microsoft Connect 请求。如果您希望将此功能用于其他属性,请对其进行投票。 http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/2327048-enable-generics-for-datamemberattribute-serviceco

【问题讨论】:

  • +1 只是因为我不知道你在任何情况下都能做到这一点。如果我不得不猜测,我会说 MS 在定义泛型类型并且需要区分的两个地方实现了它。例如,您不能让List&lt;string&gt;List&lt;DateTime&gt; 的数据合同名称都为“List”,因此他们必须这样做才能使 WCF 在内部工作。浏览 Reflector 或任何工具中的代码,看看他们在哪里实现它会很有趣。读取DataContractDataCollectionContract 属性的任何类都必须不同于读取其他属性的类。

标签: wcf generics wsdl xsd operationcontract


【解决方案1】:

这似乎是 MS 的实现选择。 在System.Runtime.Serialization.DataContract 中,它通过以下方式建立名称:

private static XmlQualifiedName GetDCTypeStableName(Type type, DataContractAttribute dataContractAttribute)
{
  string localName;
  if (dataContractAttribute.IsNameSetExplicit)
  {
    string str = dataContractAttribute.Name;
    if (str == null || str.Length == 0)
    {
       ...
    }
    else
    {
      if (type.IsGenericType && !type.IsGenericTypeDefinition)
        str = DataContract.ExpandGenericParameters(str, type);
      localName = DataContract.EncodeLocalName(str);
    }
  }

所以它明确地构建了通用名称。 对于 ServiceContract 的东西,它在 System.ServiceModel.Description.TypeLoaderSystem.ServiceModel.Description.NamingHelper 中处理,并且对泛型类型没有任何作用(最后不是我看到的)。

所以我猜测,由于这些合同源自不同的程序集和命名空间,它们可能一开始就由不同的团队实施。

【讨论】:

  • 有道理...团队 1 决定为命名加倍努力,团队 2 不...去想...将通用命名添加到下一个 WCF 的愿望清单中。 叹息
【解决方案2】:

阅读:http://msdn.microsoft.com/en-us/library/ms731045.aspx#Y1254

基本上,命名系统似乎最初设计时无法格式化名称,但最终 DataContract 命名系统惹恼了足够多的人(因为哈希),他们增加了格式化名称的能力。

编辑:

“但是,可能有理由更改此默认名称。原因之一是允许现有类型处理必须符合现有数据协定的数据。例如,存在一个名为 Person 的类型,但数据协定,体现在 XML 模式中,要求名称为 Customer。可以通过将属性值设置为 Customer 来满足合同。

第二个原因是允许生成作为类型名称无效的名称。例如,如果数据协定需要一个不允许作为类型名称的名称,请将属性值设置为该不允许的名称。例如,字符串“$value”不允许作为类型名称,但允许作为 Name 属性值。”

来源:http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractattribute.name.aspx

我的猜测是,没有这种需要来更改其他(包括 OperationContract、ServiceContract 等)的默认名称。

【讨论】:

  • 我读到了。它从 DataContract 的角度解释了一些事情,但没有说明为什么其他合同没有固定以允许格式化和泛型。
猜你喜欢
  • 2010-11-01
  • 2012-01-27
  • 1970-01-01
  • 2021-04-19
  • 1970-01-01
  • 1970-01-01
  • 2010-10-04
相关资源
最近更新 更多