11

基本クラスで抽象としてマークされているライブラリ クラスでプロパティ set-accessor を呼び出します。実行時に、クラスが基本クラスの基になるインターフェイスのみを実装し、そこから派生していないライブラリの別のバージョンに対してアプリケーションを強制的に実行します。

興味深いことに、.NET はコードを実行しますが、プロパティを設定しても効果はありません。舞台裏で何が起こっているのですか?

問題のあるコード:

MyDbParameter param = new MyDbParameter();
param.ParameterName = "p";
Console.Out.WriteLine("ParameterName: " + param.ParameterName);

ライブラリ 2.0 (コンパイル済み)

public sealed class MyDbParameter : System.Data.Common.DbParameter
{
    public override string ParameterName
    {
       get { return _name; }
       set { _name = value; }
    }
    //...
}

ライブラリ 1.0 (実行)

public sealed class MyDbParameter : MarshalByRefObject, IDbDataParameter, IDataParameter
{
    public string ParameterName
    {
        get { return _name; }
        set { _name = value; }
    }
    //...
}

呼び出しコードの MSIL を見ると、仮想呼び出しは基本クラスの MetodTable を介して解決されていると思います。

IL_0001: newobj instance void [Library]Library.MyDbParameter::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldstr "p"
IL_000d: callvirt instance void [System.Data]System.Data.Common.DbParameter::set_ParameterName(string)

しかし、コードの実行時には基底クラスは存在しません。どちらも存在しませんDbParameter.set_ParameterName()。.NETがそれについて文句を言わないのはどうしてですか? 実際に呼び出されるメソッドはどれですか?


アップデート:

サミュエルが示唆したように、クラスを逆コンパイルしSystem.Data.Common.DbParameter、両方のライブラリに採用しました。私がどこから派生したか、MarshalByRefObjectまたはすべてをコメントアウトしたかに関係なく、動作は再現されます-これにより、メイソンの答えを改ざんしたと思います。

しかし、プロセス中に何が起こるかを発見しました: 実際には、ライブラリ 1の他のプロパティのセッター/ゲッターです。前のケースでは、他のプロパティのセッターを実装して、指定された値を無視したため、効果が見られませんでした。それらすべてに自動ゲッター/セッターがある場合、私のコードの出力は実際には正しいです。MyDbParameterSizeint

疑問が残ります: .NET は、実行時に欠落しているメソッドについて文句を言わないのはなぜですか?

4

1 に答える 1

3

私はあなたの涅槃が満ちていると信じていますMarshalByRefObjects。それらは、フレームワークによって一意に処理されます。これは、それらをリモート オブジェクトのプロキシとして扱うために、それらへのすべてのアクセスを計測するためです。MBRO は問題のあるコードの要求を実際に満たすことができません (v1 クラスが をサポートしていないためDbParameter::set_ParameterName)。通常、MBRO には要求されたメンバーが欠落しているため、これは として扱われませんMissingMethodException。そのため、ランタイムははるかに寛大です。

ただし、問題のあるコードを変更して、プロパティを設定する前に param をキャストしようとした場合はIDbDataParameter、v1 と v2 の両方がそのインターフェイスをサポートしているため、うまくいくと思います。

于 2013-01-25T21:20:40.553 に答える