2012-03-15 7 views
2

すべてWCFは、オブジェクトのシリアライズすることはできません(System.Byteは、[*]と入力)

基本的に私のWCFサービスは、DCOMサーバーに接続し、「VARIANT」フィールドを含む構造体を取得し、私のWCFにそれを渡す必要がありますサービスクライアント。私はこのデータコントラクトを期待するので、ネイティブDCOMサービス

[DataContract] 
[ComVisible(true)] 
[StructLayout(LayoutKind.Sequential)] 
public struct tagProcReadAns 
{ 
    [DataMember] 
    [MarshalAs(UnmanagedType.Struct)] 
    public object vItemValue;   //VARIANT: marshalled as object in C# 
    [DataMember] 
    public ushort wQuality; 
    [DataMember] 
    public Int32 Error;}    

から得

この本のための私のWCFデータ契約が構造体ですが、私が持っている理由です、COMオブジェクトとして登録し、再びC++コードにマーシャリングすることができます[ComVisible]と[MarshalAs]の部分

とにかく、vItemValueはDCOM Serverから正常に取得したVARIANTオブジェクトです(内容を確認しました)。しかし、例外が発生したときに私はWCFに渡そうとしました。

私は私がVARIANT.vt値があることを見たので、vItemValue VARIANTに含まれるデータは、「バイト配列型」であることを期待「VTUI1 | VT_ARRAY」ので、私は

[DataContract] 
[KnownType(TypeOf(byte[])] //new 
[ComVisible(true)] 
[StructLayout(LayoutKind.Sequential)] 
public struct tagProcReadAns 
{ 
    [DataMember] 
    [MarshalAs(UnmanagedType.Struct)] 
    public object vItemValue;   //VARIANT: marshalled as object in C# 
    [DataMember] 
    public ushort wQuality; 
    [DataMember] 
    public Int32 Error;} 

を以下のようのDataContractを変更します私は再びコードを実行するときしかし、私はまだ例外をecountered、トレースを追加することによって、私は、次のエラーメッセージ

There was an error while trying to serialize parameter http://tempuri.org/:aryAns. The InnerException message was 'Type 'System.Byte[*]' with data contract name 'ArrayOfunsignedByte:http://schemas.microsoft.com/2003/10/Serialization/Arrays' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.'. Please see InnerException for more details. 

を持っているデータ型は[]が、バイト[*]をバイトされていないようです?私は何か悪いことはありますか? 例外が示唆しているように、私は何らかの形でこの問題を解決するためにDataContractResolverを使用できます。何か解決策を提案できますか?

+0

上記のシリアライゼーションの問題を回避する方法を理解しています。 – BloodroseWu

答えて

1

私は

...上記のシリアル化の問題を回避する方法を見つけ出す基本的に私は前にやったことを直接、私はC++コードから得られた後、直列化のためのWCFサービスを介して、それを渡すvItemValueを割り当てています。

フォロー@Marc Gravell提案、私はデータ契約がVT_ARRAYとVARIANTとして、次のように定義する必要があることを把握している| VT_ *タイプは、デフォルトではタイプのSystem.Array(を持つオブジェクトとしてマネージコードにマーシャリングされますバイトの代わりにSystem.Byte []など)。addtionで

[DataContract] 
[KnownType(typeof(string))]  
[KnownType(typeof(byte))] 
[KnownType(typeof(uint))] 
[KnownType(typeof(UInt16))] 
[KnownType(typeof(UInt64))] 
[KnownType(typeof(ulong))] 
[KnownType(typeof(System.Array))] //here !!!!! for System.Byte[*] 
[KnownType(typeof(byte[]))] 
[ComVisible(true)] 
[StructLayout(LayoutKind.Sequential)] 
public struct tagProcReadAns 
{ 
    [DataMember] 
    [MarshalAs(UnmanagedType.Struct)] 
    public object vItemValue;   //VARIANT type has to be carefully marshalled 
    [DataMember] 
    public ushort wQuality; 
    [DataMember] 
    public Int32 Error;   
} 

C++コードから得られたバリアントオブジェクトを通過し、WCFの境界上を通過するとき、私は直接

System.Array result = System.Array.CreateInstance(typeof(byte), ((System.Array)ans[i].vItemValue).Length); 
((System.Array)ans[i].vItemValue).CopyTo(result, 0); 

代わりのANSに結果を代入した[I] .vItemValue

これを行うことで、私はWCF境界を越えてオブジェクトを渡すことができます...

ありがとうございました!

0

byte[*](またはより具体的にどんなT[*])ありがとう明示的ベクトルない1次元配列である(ベクトルは1次元配列の特別なカテゴリ、ゼロベースです) 。そのような型の参照は、C#で言語として直接存在しないため(ベクトル以外の1次元配列との対話にはArrayを使用する必要があります)、かなり難しいです。

私のアドバイス:ここに専用のDTOを紹介してください。シリアライズに既存のオブジェクトモデルを使用しようとするのは良い出発点ですが、トリッキーな場合はDTOを使用します。私は次のように追加し、マッピングし、この手動にWCFの近くにどこにも行か前になります:COMと話をするとき

[DataContract] 
public class TagAnswer // or whatever this is 
{ 
    [DataMember] 
    public byte[] Data {get;set;} 
    [DataMember] 
    public ushort Quality {get;set;} 
    [DataMember] 
    public Int32 ErrorCode {get;set;} 
} 

あなたのCOM /構造体は大丈夫ですが、サービスの境界上の一切の場所を持っていません。

+0

関連するブログ記事、方法:http://marcgravell.blogspot.com/2010/03/when-is-int-not-int.html –

+0

こんにちは、マーク:このような迅速な対応に感謝します。私はあなたが提案したこのアプローチを考慮しました。しかし、私は次のような懸念があります:(1)C言語のVARIANTは、BSTR、int、バイトから配列への任意の型である可能性がありますので、私はまだ動的な型(2)を持つオブジェクトを含む類似の構造体を作成する必要があることを意味しますオブジェクトはWCFクライアント側でC++コードに直接渡すことができます。私は回避しようとしているC++構造体にもう一度マッピングする必要があります。 。助言がありますか?ありがとうございます。 – BloodroseWu

+0

@BloodroseWu私は、実際には、**あなたがDTOを使用しているべきである理由を実際には非常に良いケースにしていると思います。 WCFがあなたのCOMコードの内部について心配するのは妥当ではなく、現在のところAPIはあまりにもあまりにも曖昧で、呼び出し元にとっては便利ではありません。 –

関連する問題