2009-06-10 60 views
8

我有一個類型,我們稱之爲Data<TKey>。我還有一個WCF服務契約,它接受一個類型爲Object的類型(讓我們稱它爲Wrapper)(由於我不會介入的原因,這不是可選的)。如何在通用配置中指定WCF已知類型?

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

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

現在,我要送兩個類IntDataLongData

[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> 

這是什麼正確的語法?

(還請注意,我不能把Wrapper[KnownType(...)]屬性,因爲它不是我喜歡的類型。配置似乎是唯一的出路。)

編輯

@巴雷塔的回答很好地工作。但請注意,最初我收到此錯誤:

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.

我沒有在原始問題中提到它,但我的類型具有明確的數據合同名稱。事情是這樣的:直到我刪除從屬性Name屬性值

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

發生上述錯誤。希望也能幫助別人。我不知道在這種情況下工作的格式是什麼。這些沒有:

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

任何人都知道如何做到這一點?

EDIT 2

再次感謝@baretta誰指出,正確的語法是事實:

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

是的,我知道! :)我編輯了我的答案 – baretta 2009-07-03 16:20:42

回答

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> 

編輯:我還可以補充的是,如果組件信息需要爲類型參數中指定(althoug它並不適合在mscorlib程序的東西的情況下),則嵌套「[]」被使用。

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

編輯:您可以使用字符串格式模式在數據協定中自定義泛型類型的名稱。

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

默認情況下,該數據<的Int32>類型所產生的名字是一樣的東西「DataOfInt32HJ67AK7Y」,其中「HJ67AK7Y」 是從字符串生成一個散列「甕:默認」,或命名空間的類,如果你有任何。但是「數據{0}」會給它起名「DataInt32」。

更多here。查看頁面下方的「爲泛型類型定製數據合同名稱」部分。

+0

謝謝Baretta。這個簡潔的答案完美工作,一旦我用name屬性來解決問題(請參閱我的編輯)。 – 2009-07-03 15:14:14

5

here ...

Known types can also be defined in config as shown below.

<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> 

The above config specifies that the generic parameter for Circle is the same as the generic parameter for the declared type Shape. The config allows the definition of known type of arbitrary complexity. For example if it is needed to define Circle< Dictionary< string, T >> as the known type of Shape< T > (of course this is purely academic) it can be done as follows.

<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> 

Note the use config element 「parameter」 with the attributes ‘type’ and ‘index’.

相關問題