現在、私は非常にイライラする問題に直面しています。少し簡単にするために、問題を抽象化しようとします。カスタムオブジェクトをあるプロセスでデータベースにシリアライズし、別のプロセスでデシリアライズする必要があります。
2 つのアセンブリがあります。AppToDB.dll
とAppFromDB.dll
。私は 3 番目のアセンブリを持っています - MyCustomObject.dll
- これらのアセンブリの両方に参照が含まれています。MyCustomObject.dll
拡張しますMarshalByRefObject
。
私AppToDB.dll
は次のコードを実行します:
public bool serializeToDB(MyCustomObject obj)
{
OdbcDataAdapter da = new OdbcDataAdapter();
MemoryStream memStream = new MemoryStream();
try
{
ObjRef marshalledObj = RemotingServices.Marshal((System.MarshalByRefObject)obj);
// Serialize the object; construct the desired formatter
IFormatter oBFormatter = new BinaryFormatter();
// Try to serialize the object
oBFormatter.Serialize(memStream, marshalledObj);
// Create byte array
byte[] serialized = memStream.ToArray();
// Build the query to write to the database
string queryString =
"INSERT INTO MyCustomObject(id, object) VALUES(?, ?)";
OdbcCommand command = new OdbcCommand(queryString, connection);
command.Parameters.AddWithValue("id", 1);
command.Parameters.AddWithValue("object", serialized);
// Write the object byte array to the database
int num = command.ExecuteNonQuery();
}
catch { }
}
私はAppFromDB.dll
このコードを実行します:
public OCR.Batch deserializeFromDB()
{
MemoryStream memStream = new MemoryStream();
try
{
string queryString = "SELECT object FROM FCBatch";
OdbcCommand command = new OdbcCommand(queryString, connection);
OdbcDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess);
// Size of the BLOB buffer.
int bufferSize = 100;
// The BLOB byte[] buffer to be filled by GetBytes.
byte[] outByte = new byte[bufferSize];
// The bytes returned from GetBytes.
long retval;
// The starting position in the BLOB output.
long startIndex = 0;
MemoryStream dbStream = new MemoryStream();
while (reader.Read())
{
// Reset the starting byte for the new BLOB.
startIndex = 0;
// Read bytes into outByte[] and retain the number of bytes returned.
retval = reader.GetBytes(0, startIndex, outByte, 0, bufferSize);
// Continue while there are bytes beyond the size of the buffer.
while (retval == bufferSize)
{
dbStream.Write(outByte, 0, bufferSize);
dbStream.Flush();
// Reposition start index to end of last buffer and fill buffer.
startIndex += bufferSize;
retval = reader.GetBytes(0, startIndex, outByte, 0, bufferSize);
}
// Write the remaining buffer.
dbStream.Write(outByte, 0, (int)retval);
dbStream.Flush();
}
// Close the reader and the connection.
reader.Close();
dbStream.Position = 0;
object temp = oBFormatter.Deserialize(dbStream);
MyCustomObject obj = (MyCustomObject)temp;
return null;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return null;
}
}
OK、両方のコードでMemoryStream
オブジェクトを確認できます。最初AppToDB
に作成され、その内容を見ると、707 バイトが含まれています。罰金。それをデータベースに書き込み、そこに BLOB として保存します。次にAppFromDB
、BLOB を取得してbyte[]
配列に格納します。byte[]
配列をMemoryStream
再度aに書き込むと、MemoryStream
オブジェクトに 707 バイトが含まれていることがわかります。これらはすべて、元のように配置されています。オブジェクトの転送に成功したようです。
問題は にありますobject temp = oBFormatter.Deserialize(dbStream);
。逆シリアル化しようとするとすぐに、私object
は透過プロキシであり、キャストできませんMyCustomObject
!! 元のオブジェクトを取り戻すにはどうすればよいですか? #@& の名前でどのように MemoryStream オブジェクトを持つことができますか....メモリ内...シリアル化する準備ができています...そして突然、再び透過プロキシになります。
私は途方に暮れています。助けていただければ幸いです。答えを持っている人のために #@& に祈ります ;)
編集 1 わかりました。(問題は解決しませんが) 物事が理にかなっていると言わざるを得ません。私の問題: 片側にオブジェクト (状態を含む) があり、それをデータベースに保存して、数日後に反対側の別のプロセスで使用できるようにする必要があります。
シリアライズ可能とマークされていないサードパーティのオブジェクトをラップしているため、私のオブジェクトはシリアライズ可能ではありません。したがって、私の唯一のオプションは、順番にシリアライズ可能な ObjRef を返すマーシャリングのようです。しかしもちろん、数日後、デシリアライズしているオブジェクトは単なる参照であり、元のオブジェクトは失われています。
問題を解決するにはどうすればよいですか? もっと多くの人がこれに遭遇したにちがいなく、私は答えを見つけることができないようです...
編集 2 OK、サード パーティ オブジェクトに同形の独自のシリアル化可能なクラスを作成するつもりだと思います。次に、サードパーティのオブジェクト全体を実行し、その状態情報などを保存/ラップします。次に、オブジェクトをデータベースにシリアル化します...私の唯一のオプションのようです。
編集3 しばらくしてからこの問題を再開します。Edit 2に投稿されたソリューションが機能しないことに気付きました。サード パーティのアセンブリが認識しているオブジェクトに逆シリアル化する必要があります。これは、サード パーティのアセンブリが操作を実行し続けるためです。