0

C# でのレイト バインディング呼び出しを簡素化するためのライブラリを構築しようとしていますが、参照パラメーターで問題が発生しています。メソッド呼び出しで使用されるパラメーターを追加する次のメソッドがあります

    public IInvoker AddParameter(ref object value)
    {
        //List<object> _parameters = new List<object>();
        _parameters.Add(value);          

        //List<bool> _isRef = new List<bool>();
        _isRef.Add(true);

        return this;
    }

値型はオブジェクトとしてボックス化され、変更されないため、これは機能しません。例えば:

int param1 = 2;
object paramObj = param1;
//MulFiveRef method multiplies the integer passed as a reference parameter by 5:
//void MulFiveRef(ref int value) { value *= 5; }
fi.Method("MulFiveRef").AddParameter(ref paramObj);

それはうまくいきません。遅延バインディング呼び出しは成功し、パラメーター (_parameters ) を保持する内部リストは変更されますが、呼び出しの外側の値は変更されません。

この制限を克服する簡単な方法を知っている人はいますか? AddParameter シグネチャは変更できません。遅延バインディング呼び出しと同様に、パラメーターのタイプを事前に知ることはできません (また、呼び出しを行う前にオブジェクト配列内に呼び出しのすべてのパラメーターを挿入します)。

前もって感謝します。

4

3 に答える 3

1

とにかくあなたのメソッドは変更valueされていません-なぜ参照渡しなのですか? それは理にかなっているかもしれませんが、私にははっきりしていません。ref引数はパラメーターとまったく同じ型である必要があるため、提供したサンプルコードはコンパイルされないことに注意してください。

(また、C# 4.0 と .NET 4.0 には遅延バインディングのサポートが組み込まれることをご存知ですか? 言語統合バージョンは、ライブラリのみのバージョンよりも使いやすいでしょう。費やす価値があると確信していますか?この時点で図書館の時間は?)

編集:提供したコードは実際にはコンパイルされません。ref引数とパラメーターの型がまったく同じでなければならないという理由だけで、パラメーターのボックス化は行われません。それを証明するサンプルコードを次に示します。

public class Test
{
    static void Main()
    {
        int i;
        Foo(ref i); // Won't compile - error CS1502/1503
    }

    static void Foo(ref object x)
    {
    }
}

現在のコードコンパイルされている場合、それは質問で提示したコードではありません。おそらく、AddParameterを受け入れる別のオーバーロードがありますref intか?

于 2008-11-12T10:19:00.643 に答える
1

method 内で値が変化している場合は、一時 ( object) 変数を宣言して ( ref) をメソッドに渡し、後でそれを自分でアンボックスする必要があります。

    int i = 3;
    //...
    object obj = i;
    Foo(ref obj);
    i = (int)obj;

これにより、イベント後に値を更新できないことに注意してください。イベントやコールバックのようなものは、変更を呼び出し元に戻す別の方法かもしれません。

また、C# 4.0 には、COM 呼び出しのコンテキストでのみref objectこれを支援するいくつかのトリックがあることに注意してください (これは非常に一般的です [もちろんdynamic、Jon が指摘するように、レイト バインディングの場合も])。

于 2008-11-12T10:19:23.247 に答える
0

わかりました、Jon Skeet の訂正と Mark Gravell のコードのおかげで、私はこのインターフェースを思いつきました:

        //This will be created with a factory
        IOperationInvoker invoker = new OperationInvoker(Activator.CreateInstance<MyLateBindingTestType>());

        int param1 = 2;
        object paramObj = param1;

        invoker.AddParameter(ref paramObj).Invoke("MulFiveRef");

        param1 = (int)invoker.Parameters[0];

想像したとおりではありませんが、以前のインターフェースよりもはるかに簡単で読みやすいです。

        IOperationInvoker invoker = new OperationInvoker(Activator.CreateInstance<MyLateBindingTestType>());
        int refValue = 10;
        object[] args = Args.Build(refValue);

        invoker.Call("MulFiveRef", Args.ByRefIndexs(0), args);

        refValue = (int)args[0];

助けてくださった方々、どうもありがとうございました:)

于 2008-11-12T12:17:04.337 に答える