如何在配置中指定WCF已知类型是通用的? [英] How to specify a WCF known type in config that is generic?

查看:120
本文介绍了如何在配置中指定WCF已知类型是通用的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类型,我们称之为 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆