Общие принципы WCF. Почему DataContract и CollectionDataContract допускают форматированное именование, но не DataMember, OperationContract или ServiceContract?
В основном, как следует из названия:
[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 может создавать конкретный тип и форматировать имя при использовании DataContract
а также CollectionDataContract
и с указанием типа (т.е. GenericItem<Foo>
или же SpecialCollection<Foo>
, Так почему бы не иметь 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
Обновить:
Я только что вспомнил, почему я расстроился из-за того, что не смог использовать Generically отформатированный 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
2 ответа
Похоже, это выбор реализации 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.TypeLoader
а также System.ServiceModel.Description.NamingHelper
и ничего не делает с родовыми типами (наконец-то не то, что я вижу).
Поэтому я предполагаю, что, поскольку эти контракты основаны на разных сборках и пространствах имен, они, возможно, были реализованы разными командами с самого начала.
Прочитайте это: http://msdn.microsoft.com/en-us/library/ms731045.aspx
По сути, кажется, что система имен изначально была разработана без возможности форматировать имена, но в итоге система имен DataContract раздражала достаточно людей (из-за хеша), что они добавили возможность форматировать их имена.
РЕДАКТИРОВАТЬ:
"Однако могут быть причины для изменения этого имени по умолчанию. Одна из причин - позволить существующему типу обрабатывать данные, которые должны соответствовать существующему контракту данных. Например, существует тип с именем Person, но контракт данных, воплощенный в XML-схема требует, чтобы имя было Customer. Контракт можно выполнить, установив значение свойства Customer.
Вторая причина - разрешить генерацию имен, которые недопустимы в качестве имен типов. Например, если контракт данных требует имя, которое недопустимо в качестве имени типа, задайте для свойства значение этого запрещенного имени. Например, строка "$value" запрещена в качестве имени типа, но разрешена в качестве значения свойства Name ".
Источник: http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractattribute.name.aspx
Мое предположение, опять же, состоит в том, что нет такой необходимости изменять имя по умолчанию других (включая OperationContract, ServiceContract и т. Д.).