8

我有一个类型,我们称之为Data<TKey>Wrapper我还有一个 WCF 服务合同,它接受具有类型属性的类型(让我们称之为) Object(出于我不会讨论的原因,这不是可选的)。

[DataContract]
public class Data<TKey> { ... }

[DataContract]
public class Wrapper
{
    [DataMember]
    public object DataItem { get; set; }
}

现在我正在发送两个IntData课程LongData

[DataContract]
public class IntData : Data<int> { /*empty*/ }

[DataContract]
public class LongData : Data<long> { /*empty*/ }

它们都在已知类型配置文件中配置。配置类似于这样:

<configuration>
  <system.runtime.serialization>
    <dataContractSerializer>
      <declaredTypes>
        <add type="Wrapper, TheirAssembly">
          <knownType type="IntData, MyAssembly"/>
          <knownType type="LongData, MyAssembly"/>
        </add>
      </declaredTypes>
    </dataContractSerializer>
  </system.runtime.serialization>
</configuration>

在这一点上,一切正常。

但我即将添加第三种类型,我不喜欢不必要的空 .NET 类IntDataLongData. 它们的存在只是因为...

我不知道如何在 WCF 配置中指定泛型类型!

我想做这样的事情,但不知道确切的语法。

<configuration>
  <system.runtime.serialization>
    <dataContractSerializer>
      <declaredTypes>
        <add type="Wrapper, TheirAssembly">
          <!-- this syntax is wrong -->
          <knownType type="Data{System.Int32}, MyAssembly"/>
          <knownType type="Data{System.Int64}, MyAssembly"/>
        </add>
      </declaredTypes>
    </dataContractSerializer>
  </system.runtime.serialization>
</configuration>

什么是正确的语法?

(还要注意,我不能设置[KnownType(...)]属性,Wrapper因为它不是我的类型。配置似乎是唯一的方法。)

编辑

@baretta 的回答效果很好。但是请注意,最初我收到此错误:

无法将类型“MyAssembly.Data`1[System.Int64]”添加到已知类型列表中,因为另一个类型“MyAssembly.Data`1[System.Int32]”具有相同的数据合同名称“ http://www.mycompany .com/MyAssembly:Data ' 已经存在。

我在原始问题中没有提到它,但我的类型有一个明确的数据合同名称。像这样的东西:

[DataContract(Name = "Data")]
public class Data<TKey> { ... }

Name直到我从属性中删除了属性值,才会出现上述错误。希望也能帮助别人。我不知道在这种情况下哪种格式有效。这些没有:

[DataContract(Name = "Data\`1")]
[DataContract(Name = "Data{TKey}")]

有人知道怎么做吗?

编辑 2

再次感谢@baretta,他指出正确的语法实际上是:

[DataContract(Name = "Data{0}")]
4

2 回答 2

18

如果字符串遵循以下模式,则泛型类型可以从字符串中实例化: 类名后跟“`”字符,然后是类型参数的数量(在本例中为 1),然后是包含在“[ ]",并使用逗号作为类型参数分隔符

<configuration>
  <system.runtime.serialization>
    <dataContractSerializer>
      <declaredTypes>
        <add type="Wrapper, TheirAssembly">
          <!-- this syntax is all good -->
          <knownType type="Data`1[System.Int32], MyAssembly"/>
          <knownType type="Data`1[System.Int64], MyAssembly"/>
        </add>
      </declaredTypes>
    </dataContractSerializer>
  </system.runtime.serialization>
</configuration>

编辑:我还可以补充一点,如果需要为类型参数指定程序集信息(尽管 mscorlib 中的内容不是这种情况),则使用嵌套的“[]”。

<knownType type="Data`1[[System.Int32, mscorlib]], MyAssembly"/>

编辑:您可以使用字符串格式模式自定义数据协定中通用类型的名称。

[DataContract(Name = "Data{0}")]
public class Data<TKey>
{...}

默认情况下,为 Data<Int32> 类型生成的名称类似于“DataOfInt32HJ67AK7Y”,其中“HJ67AK7Y”是从字符串“urn:default”或类的命名空间(如果有)生成的哈希值。但是“Data{0}”会给它命名为“DataInt32”。

更多在这里。查看页面下方的“自定义通用类型的数据协定名称”部分。

于 2009-06-10T17:22:35.130 回答
5

这里...

已知类型也可以在 config 中定义,如下所示。

<configuration>
  <system.runtime.serialization>
    <dataContractSerializer>
      <declaredTypes>
         <add type="MyCompany.Library.Shape`1,
              MyAssembly, Version=2.0.0.0, Culture=neutral,
              PublicKeyToken=XXXXXX, processorArchitecture=MSIL">
            <knownType type="MyCompany.Library.Circle`1,
                       MyAssembly, Version=2.0.0.0, Culture=neutral,
                       PublicKeyToken=XXXXXX, processorArchitecture=MSIL">
                    <parameter index="0"/>
            </knownType>
         </add>
      </declaredTypes>
    </dataContractSerializer>
  </system.runtime.serialization>
</configuration>

上面的配置指定 Circle 的泛型参数与声明类型 Shape 的泛型参数相同。该配置允许定义任意复杂度的已知类型。例如,如果需要将 Circle< Dictionary< string, T >> 定义为 Shape< T > 的已知类型(当然这纯粹是学术性的),可以如下进行。

<configuration>
  <system.runtime.serialization>
    <dataContractSerializer>
      <declaredTypes>
         <add type="MyCompany.Library.Shape`1,
              MyAssembly, Version=2.0.0.0, Culture=neutral,
              PublicKeyToken=XXXXXX, processorArchitecture=MSIL">
            <knownType type="MyCompany.Library.Circle`1,
                       MyAssembly, Version=2.0.0.0, Culture=neutral,
                       PublicKeyToken=XXXXXX, processorArchitecture=MSIL">
                   <parameter type="System.Collections.Generic.Dictionary`2">
                      <parameter type="System.String"/>
                      <parameter index="0"/>
                   </parameter>                
            </knownType>
         </add>
      </declaredTypes>
    </dataContractSerializer>
  </system.runtime.serialization>
</configuration>

请注意使用配置元素“参数”与属性“类型”和“索引”。

于 2009-06-10T17:11:11.720 回答