Как вызвать DynamicMethod в DynamicMethod

Как передать IL для вызова DynamicMethod при создании DynamicMethod?

При вызове ILGenerator.Emit(OpCodes.Callvirt, myDynamicMethod); IL, который выдает результат MissingMethodException при выполнении.

Я воспроизвел проблему с этим минимальным кодом:

var dm1 = new DynamicMethod("Dm1", typeof(void), new Type[0]);
dm1.GetILGenerator().Emit(OpCodes.Ret);
var dm2 = new DynamicMethod("Dm2", typeof(void), new Type[0]);
var ilGenerator = dm2.GetILGenerator();
ilGenerator.Emit(OpCodes.Callvirt, dm1);
ilGenerator.Emit(OpCodes.Ret);

dm2.Invoke(null, new Type[0]); // exception raised here
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
154
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы действительно можете вызвать DynamicMethod из другого DynamicMethod.

var ilGenerator = dm2.GetILGenerator();
ilGenerator.Emit(OpCodes.Call, dm1);

OpCodes.Callvirt следует использовать при вызове виртуального метода объекта (например, ToString()). Это не относится к DynamicMethod.

Вместо этого следует использовать OpCodes.Call.

Теперь получаю исключение Invalid Program.

Sellorio 27.07.2019 08:37

Из того, что я понял из других ошибок, DynamicMethods может быть только статикой, верно? Я копирую свой IL из существующего метода и заменяю вызовы методов динамическими, что означает, что вместо вызова string.GetHashCode() (например) он вызывает динамический GetHashCode(string). Исходя из моего базового понимания IL, 2 должны быть эквивалентны (т.е. просто вопрос замены инструкции вызова, а остальное должно просто работать).

Sellorio 27.07.2019 08:46

@Sellorio Я запускаю код в Visual Studio 2017 и не получаю ошибки. попробуй сменить ctor на new DynamicMethod("Dm1", typeof(void), new Type[0], typeof(object), true);

Mr Anderson 27.07.2019 08:47

Да, базовый код работает, но мой основной код еще не работает. (см предыдущий комментарий)

Sellorio 27.07.2019 08:47

Правильно, это только статика. Единственный способ добавить методы экземпляра во время выполнения — это использовать System.Reflection.Emit.TypeBuilder, а не существующие типы. Вы можете заставить свой DynamicMethod имитировать метод экземпляра, если первый параметр будет этого типа. Однако это никак нельзя назвать виртуально

Mr Anderson 27.07.2019 08:52

Да, я так и думал. Если я правильно понимаю, string.GetHashCode() можно тривиально заменить на GetHashCode(string) (динамический), а IL, окружающий вызов, идентичен (поскольку param0 используется для this в вызовах экземпляра и param0 для статических вызовов... верно?)

Sellorio 27.07.2019 08:55

Да, это точно. Ldarg0 будет использоваться для this экземпляра и первого параметра статического

Mr Anderson 27.07.2019 08:56

Тогда я не знаю, что происходит. У меня есть ветка с моими изменениями, если хотите проверить: github.com/Sellorio/JazSharp/tree/switch-to-reflection-emit

Sellorio 27.07.2019 08:59

Помещаете ли вы аргумент(ы) в стек перед инструкцией Call?

Mr Anderson 27.07.2019 09:07

Эй, извините, я потратил на это слишком много часов подряд. Звонок работает. Проблема заключается в коде внутри метода, поэтому не беспокойтесь об этом. Спасибо за вашу помощь!

Sellorio 27.07.2019 09:09

К вашему сведению, забыл указать тип при использовании Newarr OpCode во втором динамическом методе.

Sellorio 27.07.2019 09:16

Другие вопросы по теме

Как получить все методы решения Visual Studio?
Как установить свойства объекта и его значение, если этот объект является свойством объекта, который находится внутри списка с использованием отражений
Как выполнить универсальный метод, установив двойной общий метод с использованием отражения
Почему объявлены поля, включая $change и serialVersionUID
Десериализовать объект JSON в конкретный экземпляр, созданный на лету во время выполнения, по строковому имени класса
JsonConvert.DeserializeObject выдает исключение при десериализации JSON с шестнадцатеричным значением в свойство sbyte
Используя С# Reflection, как получить свойства объекта и их значения, если этот объект является свойством объекта, который находится внутри списка
Почему ArrayList.class.isInstance(ArrayList.class) возвращает false?
Как распознать, какие методы являются геттерами и сеттерами?
Как использовать отражение для настройки всех реализаций интерфейса для DI как IOptions<>?