C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

デシリアライズの方法について


(過去ログ 4 を表示中)

[トピック内 8 記事 (1 - 8 表示)]  << 0 >>

■3885 / inTopicNo.1)  デシリアライズの方法について
  
□投稿者/ あらら 一等兵(22回)-(2006/05/25(Thu) 09:23:14)

分類:[C#] 


分類:[C#] 

いつもお世話になっております。

TCP/IP通信で、Client側で、BinaryFormatterを使用しシリアライズした構造体のデータを
Server側で受信したいと思っております。
下記のように記述した場合
「フィールド'Sample_Server.Form1.StructTEST.str1'は割り当てられません。常に既定値
nullを使用します。」
の警告がコンパイル時に表示されるのですが、どのように記述すれば、値を割り当てること
ができるのでしょうか?
(先日、送信でこちらの掲示板で質問させていただいたのですが、今度は受信側です。。。)

ご教授を頂ければ幸いです。

--------------------
/* Server側のプロジェクト */
// データ受信箇所抜粋
private Socket mySock;
private NetworkStream netStream;

netStream = new NetworkStream(mySock);
BinaryFormatter formatter = new BinaryFormatter();
StructTEST sTest = new StructTEST();
sTest = (StructTEST)formatter.Deserialize(netStream);

// 構造体
[Serializable]
struct StructTEST
{
public string str1;
public string str2;
}

--------------------
また、Clietn側は問題なく動いているように見えますが、下記のようにしてデータを渡しています。
/* Client側のプロジェクト */
// データ送信箇所抜粋
private NetworkStream netStream

StructTEST sTest = new StructTEST();
sTest.str1 = "123";
sTest.str2 = "456";
BinaryFormatter formatter = new BinaryFormatter()
formatter.Serialize(netStream, sTest);

// 構造体
[Serializable]
struct StructTEST
{
public string str1;
public string str2;
}


0
引用返信 編集キー/
■3887 / inTopicNo.2)  Re[1]: デシリアライズの方法について
□投稿者/ 中博俊 神(458回)-(2006/05/25(Thu) 10:30:20)
中博俊 さんの Web サイト

分類:[C#] 

そのstructTestは同じバージョンのものですか?
バージョンを自動生成していたりしたらうまくやり取りできないかもしれません。

0
引用返信 編集キー/
■3888 / inTopicNo.3)  Re[2]: デシリアライズの方法について
□投稿者/ あらら 一等兵(23回)-(2006/05/25(Thu) 10:53:42)

分類:[C#] 

返信ありがとうございます。

> そのstructTestは同じバージョンのものですか?
すみません。。。バージョンの確認方法がわかりません。。。
"AssemblyInfo.cs"に記述してある。
[assembly: AssemblyVersion("1.0.0.0")]
のことでいいのでしょうか?
これであれば、サーバ側、クライアント側どちらも"1.0.0.0"と
記述してありました。


0
引用返信 編集キー/
■3889 / inTopicNo.4)  Re[3]: デシリアライズの方法について
□投稿者/ 中博俊 神(459回)-(2006/05/25(Thu) 11:20:10)
中博俊 さんの Web サイト

分類:[C#] 

同じDLLを使ってますか?

#ソース見てないんであれだけど(^^;;


0
引用返信 編集キー/
■3890 / inTopicNo.5)  Re[4]: デシリアライズの方法について
□投稿者/ あらら 一等兵(24回)-(2006/05/25(Thu) 11:34:37)

分類:[C#] 

返信ありがとうございます。

> 同じDLLを使ってますか?
はい。同じDLLを使用しています。

0
引用返信 編集キー/
■3891 / inTopicNo.6)  Re[4]: デシリアライズの方法について
□投稿者/ Hongliang 伍長(40回)-(2006/05/25(Thu) 11:54:05)
Hongliang さんの Web サイト

分類:[C#] 

その型のいずれかのフィールドがコード内のどこからも初期化されていないときに出される警告ですね。
本来は private/internal のフィールドが初期化されていないときに出されるべき警告です。private/internal のフィールドは、コード内で初期化しない限り外部から設定できないからです(つまり初期化忘れの可能性が高い)。
型自体が private/internal な時は、当然ながらその型を外部から利用することはできませんから、同じようにこの警告の対象となります。
// DllImport で使う構造体はしょっちゅうこの警告に引っかかります……。

この警告は、コード内でその型のインスタンスを new しない限り現れません。
Deserialize で返ってきたオブジェクトにフィールドが設定されているかどうかは一切考慮されません。
さて、その上でこのコードですが

> BinaryFormatter formatter = new BinaryFormatter();
> StructTEST sTest = new StructTEST();
> sTest = (StructTEST)formatter.Deserialize(netStream);

二行目で new した StructTEST のインスタンスは、次の行には新しく Deserialize で作成されたインスタンスに取って代わられています。これ、new する意味がないですよね?
で、ここで new していて、しかも StructTEST を new しているのがここだけで、かつ Name を初期化していませんので、これは初期化忘れじゃないかと警告しているわけです。



ところで、ここまで書いてふと思いましたが、この StructTEST、「同じもの=同じ DLL で定義されたもの」じゃないですね? どこか別々のところで定義していますね?
両者を共有する場合は public でなければならないし、それならこの警告は出ませんから。
ちなみに C# の型のデフォルトアクセス修飾子は internal または private です。

0
引用返信 編集キー/
■3914 / inTopicNo.7)  Re[5]: デシリアライズの方法について
□投稿者/ あらら 一等兵(26回)-(2006/05/25(Thu) 15:53:57)

分類:[C#] 

返信ありがとうございます。

教えて頂いたように下記のように記述すれば警告はでなくなりました。
-------------
BinaryFormatter formatter = new BinaryFormatter();
StructTEST sTest;
sTest.str1 = "";
sTest.str2 = "";
sTets = (StructTEST)formatter.Deserialize(netStream);
-------------

ですが、上記の5行目で例外が発生します。(受信時にループでまわしているので、数回例外が発生します。)
<発生した例外>
「アセンブリ'Sample_Client,Version=1.0.0.0, Culture=neutral, PublicKeyToken = null"が見つかりません。」
「入力ストリームは有効なバイナリ形式ではありません開始コンテンツ(バイト)06-03・・・・・・mscorlib」
「バイナリストリーム'0'に、有効なBinaryHeaderが含まれていません。シリアル化と逆シリアル化の途中で、無効なストリームまたはオブジェクトのバージョン変更が発生した可能性があります。」

たびたびで申し訳ないのですが、さらに質問させてください。
・シリアライズしたバージョン?とデシリアライズするときのバージョン?を同じにするにはどうしたらよいのでしょうか?


>この StructTEST、「同じもの=同じ DLL で定義されたもの」じゃないですね? どこか別々のところで定義していますね?
同じPCで作成したものなので、DLLも同じだと思っておりました。。。StructTEST自体は別々のプロジェクトで宣言しています。

アドバイス等いただければ幸いです。

0
引用返信 編集キー/
■3947 / inTopicNo.8)  Re[6]: デシリアライズの方法について
□投稿者/ Hongliang 伍長(41回)-(2006/05/26(Fri) 03:39:32)
Hongliang さんの Web サイト

分類:[C#] 

> BinaryFormatter formatter = new BinaryFormatter();
> StructTEST sTest;
> sTest.str1 = "";
> sTest.str2 = "";
> sTets = (StructTEST)formatter.Deserialize(netStream);

Deserialize は新しいインスタンスを作って返します。
ですので、ここでその前に StructTEST を作るのは無駄です。


> 「アセンブリ'Sample_Client,Version=1.0.0.0, Culture=neutral, PublicKeyToken = null"が見つかりません」

これは、シリアライズした型とデシリアライズする型が異なる事によって発生している例外ですね。
シリアライズされたデータには型の完全修飾型名が含まれますが、この型の完全修飾型名とは、名前空間、型名、アセンブリの名前やバージョンなど、を組み合わせたもので、その型の ID となれる名前です。
// ちなみに、typeof(Hoge).AssemblyQualifiedName で Hoge 型の完全修飾型名を取得できます。
// しかしドキュメントによって完全修飾名だったり完全限定名だったりアセンブリ修飾型名だったり、どうにも統一されていないような。きっちりした使い分けがあるんだろうか。
デシリアライズする時にどの型のオブジェクトなのかを完全修飾型名から判断しますが、ここで型の属するアセンブリが Sample_Client だと言っているのに、そのアセンブリが見つからないと言うわけです。

> 同じPCで作成したものなので、DLLも同じだと思っておりました。。。StructTEST自体は別々のプロジェクトで宣言しています。

と言う事で、シリアライズした型とデシリアライズする型は同じでなければなりません。
アセンブリが違えば別の型になるのですから、逆に言えば同じアセンブリにしてしまえばいいのです。
つまり、新たにこの構造体定義を含むアセンブリ(dll)を作成し、クライアントとサーバが両方その dll を参照します。
シリアライズする時もデシリアライズする時も、この dll で定義されている構造体型を使います。


> 「入力ストリームは有効なバイナリ形式ではありません開始コンテンツ(バイト)06-03・・・・・・mscorlib」
> 「バイナリストリーム'0'に、有効なBinaryHeaderが含まれていません。シリアル化と逆シリアル化の途中で、無効なストリームまたはオブジェクトのバージョン変更が発生した可能性があります」

こっちは、
> 受信時にループでまわしているので、数回例外が発生します。
というのから見て、シリアライズ時に一つのネットワークストリームに色々書き込んでるんではないでしょうか。複数回のシリアライズを適用したり。
ストリームの現在の位置が、デシリアライズ開始のはずの位置よりも少し前に来ている時に起こりそうな例外ですが、クライアントが書き込んだを、サーバは正しい手順で読み込んでいますか?

0
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -