En ce moment, je suis confronté à un problème très frustrant. Je vais essayer d'abstraire le problème pour le rendre un peu plus facile. Il doit sérialiser mon objet personnalisé à une base de données dans un processus et le désérialiser dans un autre processus.Désérialiser un MemoryStream - comportement inattendu
J'ai deux assemlies; AppToDB.dll
et AppFromDB.dll
. J'ai un 3ème assemblage - MyCustomObject.dll
- auquel ces deux assemblages contiennent une référence. Le MyCustomObject.dll
s'étend MarshalByRefObject
.
Dans mon AppToDB.dll
j'exécute le code suivant:
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 { }
}
En AppFromDB.dll
j'exécute ce code:
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, dans les deux morceaux de code que vous pouvez voir un objet MemoryStream
. Dans le premier AppToDB
il est créé et si je regarde son contenu il contient 707 octets. Bien. Je l'écris à la base de données et l'enregistre en tant que BLOB. Maintenant, dans AppFromDB
, je récupère le BLOB et le stocke dans un tableau byte[]
. J'écris le tableau byte[]
à nouveau à MemoryStream
, et vois que mes objets MemoryStream
contiennent 707 octets, qui sont tous en place comme l'original. Il semble que j'ai transféré l'objet avec succès!
Maintenant, le problème réside avec object temp = oBFormatter.Deserialize(dbStream);
. Dès que j'essaye de désérialiser, mon object
est un proxy transparent et je suis incapable de lancer le MyCustomObject
!! Comment récupérer mon objet d'origine? Comment dans le nom de # @ & puis-je avoir un objet MemoryStream .... en mémoire ... prêt à être sérialisé ... et tout à coup c'est un proxy transparent à nouveau.
Je suis à perte. L'aide est appréciée. Je vais prier # @ & pour celui qui a la réponse;)
Modifier 1 OK, je dois dire que les choses commencent à donner un sens maintenant (même si le problème persiste). Mon problème: j'ai un objet (y compris l'état) d'un côté et j'ai besoin de le stocker dans la base de données pour pouvoir l'utiliser quelques jours plus tard par un autre processus de l'autre côté.
Mon objet n'est pas sérialisable, car il enveloppe un objet tiers qui n'est pas marqué comme sérialisable. Donc, ma seule option semble être marshal, ce qui renvoie un ObjRef, qui à son tour est sérialisable. Mais bien sûr - quelques jours plus tard - l'objet que je désérialise est simplement la référence et mon objet original est parti.
Comment résoudre mon problème? Plus de gens doivent avoir rencontré et je ne peuvent tout simplement pas trouver la réponse ...
Edit 2 OK, je suppose que je vais écrire ma propre classe sérialisable isomorphe à l'objet 3ème partie. Ensuite, parcourez tout l'objet 3ème partie et, stocker/envelopper ses informations d'état, etc. Puis sérialiser mon objet à la base de données ... Semble être ma seule option.
Édition 3 À partir de ce problème à nouveau après un certain temps. Je me suis juste rendu compte que cette solution publiée dans Edit 2 ne fonctionnera pas. Je dois désérialiser dans un objet que l'assemblée de tiers connaît, puisqu'elle continuera à effectuer des opérations dessus.
double possible de [Comment maréchal un objet et son contenu (aussi des objets)] (http://stackoverflow.com/questions/3068702/how-to-marshal-an-object-and-its- contenu-aussi-objets) – Lucero