我在一个库类上调用一个属性集访问器,它在它的基类中被标记为抽象。现在在运行时,我强制应用程序针对库的另一个版本运行,其中该类仅实现基类的底层接口,但不是从它派生的。
有趣的是,.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 怎么可能不抱怨呢?哪个方法实际被调用?
更新:
正如Samuel所建议的那样,我已经反编译了该类System.Data.Common.DbParameter
并在我的两个库中都采用了它。无论我从哪里得出MarshalByRefObject
或将其全部评论出来,这种行为都会重现 - 在此我相信我已经伪造了梅森的回答。
但是在这个过程中我发现了发生了什么:实际上它是库 1中一些其他属性的设置器/获取器,例如(它是类型 !) - 它取决于代码中的属性顺序。在前一种情况下,我实现了其他属性的设置器,因此我忽略了提供的值,因此我看不到任何效果。现在,如果它们都具有自动 getter/setter,那么我的代码输出实际上是正确的。MyDbParameter
Size
int
问题仍然存在:为什么 .NET 在运行时不抱怨缺少的方法?