10

AppDomain次のコードを使用して、境界を越えて配列をシリアル化しようとしています。

public int Read(byte[] buffer, int offset, int count)
{
    return base.Read(buffer, offset, count);
}

推測として、他の場所で属性に気付いた後、メソッドのパラメーターに属性をマークしました[In][Out]これにより、パラメーターが参照によって渡されたかのように動作するように見えました。

例えば:

public int Read([In, Out] byte[] buffer, int offset, int count)
{
    return base.Read(buffer, offset, count);
}

属性を追加する前は、境界bufferを越えてメソッドから戻った後、変数の内容が失われていました。AppDomain

クラス(SslStream)は継承元でしたが、属性MarshalByRefObjectでマークされていませんでした。Serializableこれは、パラメーターを値渡しする唯一の方法ですか?これらの属性は、クラスがシリアル化されているときに.NETによって何らかの形で認識されていますか?そして、それらは本当にパラメータが参照によって渡される原因になるのでしょうか、それとも内容がコピーされたばかりなのですか?

4

2 に答える 2

12

これは、.NET Remoting の非常に文書化されていない機能です。クラスが [Serializable] であるか、MarshalByRefObject から派生したものであるかは関係ありません。ここで問題となるのは、引数が AppDomain 境界を越えてマーシャリングされる方法です。呼び出し自体は、Remoting によって内部で行われます。配列は呼び出し後に自動的にマーシャリングされません。これは明らかにパフォーマンスの最適化です。[Out] 属性のみが必須で、[In] は暗示されます。MSDN でこれに関する関連ドキュメントを見つけることができませんでした。同じ問題に遭遇した誰かからのブログ投稿です (「Remoting で OutAttribute を使用する」まで下にスクロールしてください)。

遊ぶためのいくつかのコード:

using System;
using System.Runtime.InteropServices;

class Program {
    static void Main(string[] args) {
        var ad = AppDomain.CreateDomain("second");
        var t = (Test)ad.CreateInstanceAndUnwrap(typeof(Test).Assembly.FullName, typeof(Test).FullName);
        var b = new byte[] { 1 };
        t.Read(b);
        System.Diagnostics.Debug.Assert(b[0] == 2);
    }
}

class Test : MarshalByRefObject {
    public void Read([Out]byte[] arg) {
        arg[0] *= 2;
    }
}
于 2012-01-31T03:27:49.920 に答える