我有一个类型,我们称之为Data<TKey>
。我还有一个WCF服务合同,它接受一个类型为Wrapper
的属性(让我们称之为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 IntData
和LongData
。它们只存在是因为......
我不知道如何在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]'具有相同的数据协定名称'{{3} }'已经存在。
我没有在原始问题中提及它,但我的类型有明确的数据合约名称。像这样:
[DataContract(Name = "Data")]
public class Data<TKey> { ... }
在我从属性中删除Name
属性值之前发生了上述错误。希望能帮助其他人。我不知道在这种情况下哪种格式有效。这些没有:
[DataContract(Name = "Data\`1")]
[DataContract(Name = "Data{TKey}")]
任何人都知道怎么做?
编辑2
再次感谢@baretta,他指出正确的语法实际上是:
[DataContract(Name = "Data{0}")]
答案 0 :(得分: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&lt; Int32&gt;生成的名称类型是“DataOfInt32HJ67AK7Y”,其中“HJ67AK7Y” 是字符串“urn:default”生成的哈希,或者类的命名空间(如果有的话)。但是“Data {0}”会将其命名为“DataInt32”。
更多here。请查看页面下方的“为通用类型自定义数据合同名称”部分。
答案 1 :(得分:5)
来自here ...
已知 类型也可以在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。配置允许 已知类型的定义 任意复杂性。例如,如果 需要定义 圈&LT;字典&LT; string,T&gt;&gt;作为 已知类型的形状&lt; 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>
注意使用config元素 带有'type'属性的“parameter” 和'索引'。