Общие принципы 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, поэтому не следует ли форматировать имя OperationContract, поскольку оно ЗНАЕТ тип?


Обновить:

Я только что вспомнил, почему я расстроился из-за того, что не смог использовать 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 и т. Д.).

Другие вопросы по тегам