System.MissingMethodException после добавления необязательного параметра

Я получаю сообщение об ошибке System.MissingMethodException после того, как у меня есть необязательный параметр в одном компоненте, а другой компонент, который вызывает его, не был построен, поскольку он вызывает его со старым количеством параметров.

Только компонент, в котором добавлен параметр, был собран как патч. Вызывающий компонент устарел, так как в нем нет изменений.

При запуске вызывающего компонента выдает ошибку:

Информация об исключении

Тип исключения: System.MissingMethodException Сообщение: Метод не найден: «LabelURLs IPSD.BnB.Transaction.Postage.GetLabelURLs(System.String)». Данные: System.Collections.ListDictionaryInternal TargetSite: Void GenerateScanForm(Int32, Int32) HelpLink: NULL Источник: BnBDispenseQueueProcess

Насколько я знаю, это не должно вызывать ошибку, так как новый параметр является необязательным. Еще одна вещь, вызывающая компонент (EXE), запускается как служба Windows.

мы нашли очень сложный обходной путь, чтобы заставить его работать. Удалив измененный компонент один раз и запустив вызывающий компонент, который скажет, что DLL не найдена. Поместите ту же DLL снова, и вызывающий компонент работает нормально :).

Я думаю, что мне не хватает некоторых внутренностей .net.

Дайте мне знать, если нужна дополнительная информация.


person sandeep    schedule 27.03.2012    source источник
comment
Мы добавили необязательный параметр в одну из наших общих библиотек. Это сломало все работающие модули (нам повезло, это было при тестировании env). Это причудливые функции времени разработки .net, похоже, мы должны глубоко понять их, прежде чем использовать. Спасибо, что спросили об этом.   -  person CreativeManix    schedule 04.02.2015
comment
@CreativeManix, пожалуйста, дайте мне знать о вашей находке. так и не смог до конца понять, почему он так себя вел. может быть какой-то трюк с компиляцией происходит за кулисами   -  person sandeep    schedule 19.02.2015
comment
@Sanddep, как упомянул Джон Скит, необязательные параметры - это функция времени компиляции. Во время компиляции в сборке вызывающего объекта необязательные значения параметров передаются со значениями по умолчанию. поэтому, если вы добавили необязательный параметр в общую библиотеку, убедитесь, что вы также компилируете сборку вызывающей стороны. Если вы не хотите компилировать всю сборку вызывающей стороны, лучше не используйте необязательный параметр, вместо этого используйте перегруженный метод;   -  person CreativeManix    schedule 20.02.2015
comment
@CreativeManix спасибо, что поделились информацией :)   -  person sandeep    schedule 26.02.2015


Ответы (1)


Только компонент, в котором добавлен параметр, был собран как патч. Вызывающий компонент устарел, так как в нем нет изменений.

В нем должны быть изменения, потому что старый код вызывает метод, которого больше не существует!

Насколько я знаю, это не должно вызывать ошибку, так как новый параметр является необязательным.

Это не решение времени выполнения — это решение времени компиляции. Если у вас есть такой метод:

void Foo(int x, int y = 5)

и вы называете это так:

Foo(10);

то компилятор эффективно преобразует это в вызов:

Foo(10, 5);

Вызов имеет полный список аргументов в двоичном формате. Если вы хотите перейти от версии с одним параметром к версии с несколькими параметрами таким образом, чтобы это не повлияло на двоичную совместимость, вам нужно вместо этого добавить перегрузку, например.

void Foo(int x)
{
    Foo(x, 5);
}

void Foo(int x, int y)
{
    ...
}

Кроме того, вы можете перестроить вызывающий код и повторно развернуть его.

Я очень подозрительно отношусь к вашему обходному пути. Вы уверены, что когда вы вернули DLL на место, вы заменили ее новой версией (с необязательным параметром), а не старой версией?

person Jon Skeet    schedule 27.03.2012
comment
да я заменяю только новой версией. Ваш ответ имеет смысл. Но из-за обходного пути это выглядит не совсем верно в моем случае. - person sandeep; 27.03.2012
comment
@sandeep: я сильно подозреваю, что в вашем диагнозе обходного пути есть что-то неверное. Сколько раз вы пробовали это? Вы точно видели это с использованием нового кода? Вы точно не заменили код вызова? Это просто не должно работать - в C# нет ничего, что можно было бы сделать, если только вы не используете динамическую типизацию. - person Jon Skeet; 27.03.2012
comment
@sandeep: Извините, я не понимаю, что означает ваш предыдущий комментарий. - person Jon Skeet; 27.03.2012
comment
Одно обновление, связанное с заменой DLL... Я не заменяю вызываемый компонент. Когда я получаю сообщение об ошибке, я просто удаляю вызывающий компонент и запускаю службу Windows, служба выдает ошибку и не может запуститься, поскольку dll отсутствует. И снова поместите ту же вызывающую dll и запустите службу, теперь она работает нормально. Так что я предполагаю, что это что-то связанное с JIT-компилятором. но не уверен, как это работает, только если я один раз удалю dll :). - person sandeep; 27.03.2012
comment
@sandeep: Нет, этого действительно не должно быть. Если у вас все еще есть несовпадающие двоичные файлы, это действительно, действительно не должно работать. Вы уверены, что заменили его старым двоичным файлом, а не перекомпилированным? - person Jon Skeet; 27.03.2012
comment
Да 100% правда Я заменяю только старую dll. Еще одна вещь: мы вызываем метод во время выполнения через отражение, а не прямую ссылку. Имеет ли это значение. - person sandeep; 27.03.2012
comment
@sandeep: Да, это будет иметь огромное значение. Это не объясняет обходной путь, но делает все остальное несколько неуместным. Вы действительно должны думать о такой важной информации, когда задаете вопрос. Пожалуйста, опубликуйте код, который вы используете для вызова метода. - person Jon Skeet; 27.03.2012
comment
По какой-то причине я не могу дать код, но могу объяснить вам, что происходит. давайте предположим, что есть три компонента C1, C2 и C3. C1 динамически загружает C2 и вызывает функцию foo из C2 и C2, в свою очередь вызывает функцию foo3 в C3, которая является прямой ссылкой. Надеюсь, это понятно..... Мы добавили необязательный параметр в foo3 для C3 и сборки C3 и развернули его. сборка C1 и C2 не производилась, поэтому теперь C2 выдает ошибку при вызове foo3 из C3... И этот обходной путь работает, я проверял его много раз :( - person sandeep; 28.03.2012
comment
@sandeep: Честно говоря, не совсем понятно. Даже если вы не можете дать настоящий код, вы должны быть в состоянии дать короткую, но полную программу, которая демонстрирует, как вы вызываете метод, что является важной частью , после всего. - person Jon Skeet; 28.03.2012