2

現在、私は非常にイライラする問題に直面しています。少し簡単にするために、問題を抽象化しようとします。カスタムオブジェクトをあるプロセスでデータベースにシリアライズし、別のプロセスでデシリアライズする必要があります。

2 つのアセンブリがあります。AppToDB.dllAppFromDB.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に投稿されたソリューションが機能しないことに気付きました。サード パーティのアセンブリが認識しているオブジェクトに逆シリアル化する必要があります。これは、サード パーティのアセンブリが操作を実行し続けるためです。

4

1 に答える 1

1

ObjRef元のオブジェクトではなく、参照を転送するためのすべての情報を含む「リモート参照」をシリアル化しています。

MSDN から (強調鉱山):

ObjRef には、マーシャリングされるオブジェクトの Type とクラス、その正確な場所、およびオブジェクトが配置されているリモート サブディビジョンに到達する方法に関する通信関連の情報を記述する情報が含まれています。

MarshalByRefObject を実装するクラスがマーシャリングされると、それを表す ObjRef がチャネルを介して別のアプリケーション ドメイン (別のプロセスまたはコンピューター内の可能性がある) に転送されます。ObjRef がターゲット アプリケーション ドメインで逆シリアル化されると、リモート MBR オブジェクトの透過プロキシを作成するために解析されます。この操作はアンマーシャリングと呼ばれます。

編集(提供された新しい情報のため):

問題を解決するには、いくつかの方法があります。それらのすべてには独自の制限があります。ここでまとめます。

  • で XML シリアル化を使用しますXmlSerializer。XML シリアル化は、フィールドやカスタム データをシリアル化するのではなく、オブジェクトのすべてのパブリック プロパティをシリアル化および逆シリアル化するという点で異なります (シリアル化さISerializableれるオブジェクトによって実装されている場合)。したがって、サードパーティ オブジェクトが単なるデータ コンテナーであり、パブリック プロパティをシリアル化するだけで十分であり、既定のコンストラクターを提供する場合は、このソリューションで問題ありません。

  • リフレクションを使用してフィールドを取得し、それらをシリアル化して、独自の「低レベル」のシリアル化コードを作成します。通常、このアプローチでは、アプリケーションを完全な信頼で実行する必要があります (リフレクションを介してプライベート フィールドを反映および変更するには、通常、下位の信頼には存在しないアクセス許可が必要です)。ここで役立つメソッドは次のとおりです。シリアライズするフィールドを取得するFormatterServices.GetSerializableMembers ()、オブジェクト インスタンスからフィールド データを取得するFormatterServices.GetObjectData() 、逆シリアル化して新しいインスタンスを作成するときのFormatterServices.GetSafeUninitializedObject() 、初期化されていないインスタンス (コンストラクターは呼び出されません)、およびFormatterServices.PopulateObjectMembers()フィールドを新しいインスタンスに書き戻します。object[]フィールドでシリアライズ可能な単純なデータ型しかない場合は、フィールド データの格納に使用するものをシリアライズおよびデシリアライズできます。

  • あなたの現在のアイデアは、サードパーティ オブジェクトのレプリカを手動で作成することです。これは非常に苦痛であり、基本的には XML シリアライゼーションも機能する場合にのみ機能します。プロパティが sinatce に対して読み取り専用である場合、このアプローチではうまくいきません。

于 2010-06-23T09:39:09.233 に答える