如何在配置中指定通用的WCF已知类型?

Dre*_*kes 8 .net generics wcf known-types

我有一个类型,我们称之为Data<TKey>.我还有一个WCF服务合同,它接受一个带有类型Wrapper属性的类型(让我们调用它)Object(原因我不会进入,这不是可选的).

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

[DataContract]
public class Wrapper
{
    [DataMember]
    public object DataItem { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

现在,我要送两个类IntDataLongData:

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

[DataContract]
public class LongData : Data<long> { /*empty*/ }
Run Code Online (Sandbox Code Playgroud)

它们都是在已知类型的配置文件中配置的.配置类似于以下内容:

<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>
Run Code Online (Sandbox Code Playgroud)

在这一点上,一切正常.

但我要添加第三个类型,我不喜欢多余的,空的.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>
Run Code Online (Sandbox Code Playgroud)

这个的正确语法是什么?

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

编辑

@ baretta的答案很好用.但请注意,最初我收到此错误:

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

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

[DataContract(Name = "Data")]
public class Data<TKey> { ... }
Run Code Online (Sandbox Code Playgroud)

在我Name从属性中删除属性值之前发生了上述错误.希望能帮助其他人.我不知道在这种情况下哪种格式有效.这些没有:

[DataContract(Name = "Data\`1")]
[DataContract(Name = "Data{TKey}")]
Run Code Online (Sandbox Code Playgroud)

有人知道怎么做吗?

编辑2

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

[DataContract(Name = "Data{0}")]
Run Code Online (Sandbox Code Playgroud)

bar*_*tta 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>
Run Code Online (Sandbox Code Playgroud)

编辑:我还可以补充一点,如果需要为类型参数指定程序集信息(虽然mscorlib中的东西不是这种情况),则使用嵌套的"[]".

<knownType type="Data`1[[System.Int32, mscorlib]], MyAssembly"/>
Run Code Online (Sandbox Code Playgroud)

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

[DataContract(Name = "Data{0}")]
public class Data<TKey>
{...}
Run Code Online (Sandbox Code Playgroud)

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

更多这里.请查看页面下方的"为通用类型自定义数据合同名称"部分.


Ste*_*nan 5

这里 ......

已知类型也可以在配置中定义,如下所示.

<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>
Run Code Online (Sandbox Code Playgroud)

上面的配置指定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>
Run Code Online (Sandbox Code Playgroud)

请注意使用配置元素"parameter",其属性为"type"和"index".