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