2

基本的にはタイトルの通り:

[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 は具体的な型を作成し、型を表すDataContractandを使用するときに名前をフォーマットすることができますCollectionDataContract(つまりGenericItem<Foo>、 or 。では、も同様にフォーマットできるようにし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<Foo> であることを意味します。型を認識しているため、OperationContract 名をフォーマットするべきではありませんか?


アップデート:

一般的にフォーマットされた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

4

2 に答える 2

1

これは、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 の場合、それは and で処理されSystem.ServiceModel.Description.TypeLoaderSystem.ServiceModel.Description.NamingHelperジェネリック型では何もしません (最後に私が見ているものではありません)。

したがって、これらのコントラクトは異なるアセンブリと名前空間に由来するため、そもそも異なるチームによって実装された可能性があると推測しています。

于 2011-06-28T20:23:00.070 に答える
0

これを読んでください:http://msdn.microsoft.com/en-us/library/ms731045.aspx#Y1254

基本的に、命名システムは当初、名前をフォーマットできないように設計されていたようですが、最終的に DataContract 命名システムは (ハッシュのために) 多くの人々を悩ませ、名前をフォーマットする機能を追加しました。

編集:

「ただし、この既定の名前を変更する理由がある場合があります。1 つの理由は、既存の型が既存のデータ コントラクトに準拠する必要があるデータを処理できるようにすることです。たとえば、Person という名前の型が存在しますが、データ コントラクトは、 XML スキーマでは、名前が Customer である必要があります。プロパティ値を Customer に設定することで、コントラクトを満たすことができます。

2 つ目の理由は、型名として無効な名前の生成を許可することです。たとえば、データ コントラクトが型名として許可されていない名前を要求する場合は、プロパティ値をその許可されていない名前に設定します。たとえば、文字列「$value」は型名としては許可されていませんが、Name プロパティの値としては許可されています。"

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

繰り返しますが、他のもの (OperationContract、ServiceContract などを含む) のデフォルト名を変更する必要はないと思います。

于 2011-06-28T20:08:15.560 に答える