Я вызываю свойство set-accessor в классе библиотеки, который в своем базовом классе помечен как абстрактный. Теперь во время выполнения я принудительно приложение запускается против другой версии библиотеки, где класс реализует только базовые интерфейсы базового класса, но isn 't, полученных из него.
Интересно, что .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 не жалуется на это? Какой метод действительно вызван?
UPDATE:
Как было предложено Samuel, я декомпилировал класс System.Data.Common.DbParameter
и принял его в обеих моих библиотеках. Поведение воспроизводится независимо от того, что я получил от MarshalByRefObject
или прокомментировал все это - таким образом, я считаю, что я фальсифицировал ответ Мейсона.
Но во время процесса я обнаружил, что происходит: на самом деле это сеттер/получатель другого свойства MyDbParameter
в библиотеке 1, что называется, например. Size
(который имеет тип int
!) - он зависит от порядка свойств в коде. В предыдущем случае я реализовал сеттеры других свойств, чтобы игнорировать предоставленные значения, поэтому я не видел никакого эффекта. Теперь, если у всех из них есть автоматические getters/seters, вывод моего кода действительно правильный.
Остается вопрос: почему .NET не жалуется на недостающий метод во время выполнения?