如何在配置中指定WCF已知类型是通用的? [英] How to specify a WCF known type in config that is generic?
问题描述
我有一个类型,我们称之为 Data< TKey>
。我也有一个WCF服务契约,它接受一个类型为 Object
的类型(让它称为 Wrapper
)(因为我不会介入的原因,这不是可选的)。
[DataContract]
public class Data< ; TKEY的> {...}
[DataContract]
public class Wrapper
{
[DataMember]
public object DataItem {get;组; }
}
现在我发送两个类 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>
< / configuration>
此时,一切正常。
<但我正要添加第三种类型,我不喜欢拥有不必要的空.NET类
IntData
和 LongData code>。它们只存在,因为...
我不知道如何在WCF配置中指定泛型类型!
我想做这样的事情,但不知道确切的语法。
< ;结构>
< system.runtime.serialization>
< dataContractSerializer>
< declaredTypes>
< add type =Wrapper,TheirAssembly>
<! - 此语法错误 - >
< knownType type =Data {System.Int32},MyAssembly/>
< knownType type =Data {System.Int64},MyAssembly/>
< / add>
< / declaredTypes>
< / dataContractSerializer>
< / 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> {...}
直到我移除名称
属性值。希望也能帮助别人。我不知道在这种情况下工作的格式是什么。这些没有:
[DataContract(Name =Data\`1)]
[DataContract Name =Data {TKey})]
任何人都知道如何做到这一点?
编辑2
再次感谢@ baretta指出正确的语法实际上:
[DataContract(Name =Data {0})]
解决方案如果字符串遵循以下模式,泛型类型可以从字符串中实例化:
类名后跟一个`字符,后跟类型参数的数目(在本例中为1),后跟类型参数包含在[]中,并使用逗号作为类型参数分隔符。
<配置>
< system.runtime.serialization>
< dataContractSerializer>
< declaredTypes>
< add type =Wrapper,TheirAssembly>
<! - 这个语法都很好 - >
< knownType type =Data`1 [System.Int32],MyAssembly/>
< knownType type =Data`1 [System.Int64],MyAssembly/>
< / add>
< / declaredTypes>
< / dataContractSerializer>
< / configuration>
编辑:我还可以补充说,如果需要为类型参数指定程序集信息(althoug mscorlib中的东西并不是这样),然后使用嵌套的[]。
pre $ < knownType type =数据`1 [[System.Int32,mscorlib]],MyAssembly/>编辑:您可以使用字符串格式模式自定义数据协定中泛型类型的名称。
$ b [DataContract(Name =Data {0})]
public class Data< TKey>
{...}
默认情况下,为Data< Int32>类型就像DataOfInt32HJ67AK7Y,其中HJ67AK7Y
是一个由字符串urn:default生成的散列,或者类的名称空间(如果有的话)。但是Data {0}会给它起名字DataInt32。
更多这里。查看页面中的为泛型类型定制数据合同名称部分。
I have a type, let's call it Data<TKey>
. I also have a WCF service contract that accepts a type (lets call it Wrapper
) with a property of type Object
(for reasons I won't go into, this isn't optional).
[DataContract]
public class Data<TKey> { ... }
[DataContract]
public class Wrapper
{
[DataMember]
public object DataItem { get; set; }
}
Right now I'm sending two classes IntData
and LongData
:
[DataContract]
public class IntData : Data<int> { /*empty*/ }
[DataContract]
public class LongData : Data<long> { /*empty*/ }
They're both configured in the known types config file. The config resembles something like this:
<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>
At this point, everything works fine.
But I'm about to add a third type and I don't like having the unnecessary, empty .NET classes IntData
and LongData
. They only exist because...
I don't know how to specify generic types in WCF configuration!
I want to do something like this, but don't know the exact syntax.
<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>
What is the correct syntax for this?
(Note too that I cannot put [KnownType(...)]
attributes on Wrapper
as it's not my type. Config seems to be the only way.)
EDIT
@baretta's answer worked nicely. Note however that initially I received this error:
Type 'MyAssembly.Data`1[System.Int64]' cannot be added to list of known types since another type 'MyAssembly.Data`1[System.Int32]' with the same data contract name 'http://www.mycompany.com/MyAssembly:Data' is already present.
I didn't mention it in the original question, but my type has an explicit data contract name. Something like this:
[DataContract(Name = "Data")]
public class Data<TKey> { ... }
The above error occurred until I removed the Name
property value from the attribute. Hope that helps someone else out too. I don't know what format works in this scenario. These didn't:
[DataContract(Name = "Data\`1")]
[DataContract(Name = "Data{TKey}")]
Anyone know how to do this?
EDIT 2
Thanks again to @baretta who pointed out that the correct syntax is in fact:
[DataContract(Name = "Data{0}")]
解决方案 A generic type is instantiable from a string, if the string follows this pattern:
Class name followed by a "`" character, followed by the number of type parameters(in this case it's 1), followed by the type parameters enclosed within "[]", and using comma as type parameter separator.
<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>
Edit: I might also add, that if assembly information needs to be specified for the type parameters(althoug it's not the case for stuff in mscorlib), then nested "[]" is used.
<knownType type="Data`1[[System.Int32, mscorlib]], MyAssembly"/>
Edit: You can customize names of generic types in data contracts, using the string format pattern.
[DataContract(Name = "Data{0}")]
public class Data<TKey>
{...}
By default, the name generated for the Data<Int32> type is something like "DataOfInt32HJ67AK7Y", where "HJ67AK7Y"
is a hash generated from the string "urn:default", or the namespace of your class, if you have any. But "Data{0}" would give it the name "DataInt32".
More here. Have a look at the "Customizing Data Contract Names for Generic Types" part down the page.
这篇关于如何在配置中指定WCF已知类型是通用的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!