WCF Generics - Why do DataContract and CollectionDataContract allow formatted naming, but not DataMember, OperationContract or ServiceContract?
Asked Answered
S

2

2

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

Singhalese answered 28/6, 2011 at 19:56 Comment(1)
+1 just because I didn't know you could do that in any case. If I had to guess, I'd say MS implemented it on the 2 places where generic types are defined and need to be differentiated. For example you can't have a List<string> and a List<DateTime> both have a data contract name of "List" so they had to do it to make WCF work internally. It would be interesting to poke through the code in Reflector or whatever tool, and see where they implemented this. Whatever class reads the DataContract and DataCollectionContract attributes must be different than the one that reads the others.Trinomial
T
1

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.

Trinomial answered 28/6, 2011 at 20:23 Comment(1)
Makes sense... team 1 decides to go the extra mile for naming, team 2 doesn't... go figure... add generic naming to a wishlist for the next WCF. sighSinghalese
H
0

Read this: http://msdn.microsoft.com/en-us/library/ms731045.aspx#Y1254

Basically, it seems like the naming system was originally designed without being able to format the names, but eventually the DataContract naming system annoyed enough people (because of the hash) that they added the ability to format the names of them.

EDIT:

"However, there may be reasons to change this default name. One reason is to allow an existing type to process data that must conform to an existing data contract. For example, there exists a type named Person but the data contract, embodied in an XML schema, requires that the name be Customer. The contract can be satisfied by setting the property value to Customer.

A second reason is to allow the generation of names that are invalid as type names. For example, if a data contract demands a name that is not allowable as a type name, set the property value to that disallowed name. For instance, the string "$value" is disallowed as a type name but is allowed as a Name property value."

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

My guess, again, is that no such need to change the default name of the others (including OperationContract, ServiceContract, etc.) has come up.

Hoboken answered 28/6, 2011 at 20:8 Comment(1)
I read that. It explains things from the point of view of DataContract, but it doesn't say why the other contracts were not fixed to allow formatting and generics.Singhalese

© 2022 - 2024 — McMap. All rights reserved.