WCF泛型 - 为什么DataContract和CollectionDataContract允许格式化命名,但不允许DataMember,OperationContract或ServiceContract? [英] WCF Generics - Why do DataContract and CollectionDataContract allow formatted naming, but not DataMember, OperationContract or ServiceContract?

查看:224
本文介绍了WCF泛型 - 为什么DataContract和CollectionDataContract允许格式化命名,但不允许DataMember,OperationContract或ServiceContract?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  [DataContract(Name ={0} Item)] // This will will格式正确
public class GenericItem< T>
{
[DataMember(Name =The {0})] //这将不会格式正确
public T TheItem {get;组; }
}

[CollectionDataContract(Name ={0} Items)] //这将正确设置格式
public SpecialCollection< T> :Collection< T> {}

[ServiceContract(Name ={0} Service)] //这将不会格式正确
public interface IGenericService< T>
{
[OperationContract(Name =Get {0})] //这将不会格式正确
GenericItem< T>得到< T>();

$ / code>

所以,你有这个...有效和无效...但问题是......为什么?很显然,当使用 DataContract 时,.NET能够创建具体类型并格式化名称。和 CollectionDataContract 并指定类型(即 GenericItem< Foo> SpecialCollection< Foo> / code>。那么为什么不让 DataMember 也可以格式化?



ServiceContract / OperationContract 我可以按照它在上面(sorta)中留下的方式理解,但我不明白的是当您给它一个具体类型时,操作仍然将无法正常工作:

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

public interface IGenericService< T>
{
[OperationContract(Name =Get {0})] //这将不会格式正确
T获取&l吨; T>();
}

同样,为什么?很明显,我在这里声明了一个具体的Foo类型,这意味着IGenericService是一个IGenericService< Foo>所以不应该将OperationContract名称格式化,因为它知道这种类型?






更新:



我只记得为什么我不能使用一般格式化的ServiceContract ...当我有实现服务的时候,我给它一个具体的类型...

  //请参阅!我给它一个具体的类型去! 
[ServiceBehavior(...)]
public class MyService:IGenericService< Foo> {...}






我创建了一个 Microsoft Connect 对此的要求。如果您希望为其他属性使用此功能,请加快速度。 http://visualstudio.uservoice .com / forums / 121579-visual-studio / suggestions / 2327048-enable-generics-for-datamemberattribute-serviceco

解决方案

这似乎是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);




$ b $ p $所以它明确地构建了通用名称。
在ServiceContract的情况下,在 System.ServiceModel.Description.TypeLoader System.ServiceModel.Description.NamingHelper ,并且不会对泛型类型做任何事情(最后并不是我看到的)。



所以我猜这些契约源于不同的程序集和名称空间,它们可能已由不同的团队实施以开始。


Basically as the title says:

[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>();
}

So, there ya have it... what works and doesn't work... but the question is... why? Obviously .NET is able to create a concrete type and format the name when using a DataContract and CollectionDataContract and stating the type (i.e. GenericItem<Foo> or SpecialCollection<Foo>. So why not have the DataMember also be able to format as well?

The ServiceContract/OperationContract I can sort of understand in the manner it's left in above (sorta), but what I don't understand is when you give it a concrete type the operations still won't work properly:

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

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

Again, why? Obviously I'm declaring a concrete type of Foo here which means the IGenericService is an IGenericService<Foo> so shouldn't the OperationContract name be formatted since it KNOWS the type?


Update:

I just remembered why I was upset about not being able to use a Generically formatted ServiceContract... when I have the implement the service I'm giving it a concrete type...

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


I created a Microsoft Connect request for this. Please upvote it if you want this feature for the other attributes. http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/2327048-enable-generics-for-datamemberattribute-serviceco

解决方案

This seems to be an implementation choice by MS. In System.Runtime.Serialization.DataContract it builds up the name by doing:

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);
    }
  }

So it explicitly builds out the generic name. In the case of ServiceContract stuff, that is handled in System.ServiceModel.Description.TypeLoader and System.ServiceModel.Description.NamingHelper, and does not do anything with generic types (at last not that I am seeing).

So I'm guessing since these contracts stem from different assemblies and namespaces, they may have been implemented by different teams to begin with.

这篇关于WCF泛型 - 为什么DataContract和CollectionDataContract允许格式化命名,但不允许DataMember,OperationContract或ServiceContract?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆