Pull to refresh

Comments 20

Неплохо. Но гораздо удобнее генерировать динамический код через System.Linq.Expressions, в 4.5 помимо функциональщины добавили еще немного императивщины.
Абсолютно согласен. Конечно у Reflection.Emit больше возможностей, но гораздо проще ошибиться и словить VerificationException. Пожалуй, что на досуге я добавлю ещё одну реализацию, использующую деревья выражений. Хотя опуститься на уровень IL было интересно, много нового для себя открыл.
А можно таким макаром заменить в рантайме метод из какого-либо класса? Например, метод, который что-то проверяет и возвращает True, а мы раз и делаем False
Можно. Гуглить по .NET CLR Injection, например вменяемая статья с примерами кода codeproject
Хотелось бы предупредить, что, если целитесь на подмену метода, проверяющего наличие лицензии, реализованного, скажем, с помощью LicFileLicenseProvider, то может не сработать.
Такая задачка будет посложнее. Нужно знать структуру внутренних объектов CLR. Один из подходов к перехвату .NET'овских методов, про который я читал ещё давно вот тут состоит в том, чтобы подменять адрес JIT'овской заглушки целевого метода на метод-перехватчик. Но работать это будет только если хук поставить до JIT-компиляции. Со сборками, по которым прошлись NGEN'ом поэтому такой трюк не прокатит. Статья эта 2009 года, с тех пор многие структуры могли измениться. Другой подход, описанный тут, основан на использовании CLR Profiler API. Эта апишка используется и в Visual Studio для реализации edit-and-continue, то есть для применения правок к коду прямо во время отладки. И ещё есть готовый продукт — библиотека CodeCop, которая позволяет перехватывать метод до его выполнения, после его выполнения, или вообще целиком подменить метод. Бесплатная версия позволяет установить максимум 25 хуков, а за полный функционал разработчики просят денежку. Как реализован CodeCop ничего не могу сказать — репозиторий на BitBucket естественно закрытый. Но предполагаю, что они используют именно CLR Profiler API, потому что с RyeJit они пока не умеют дружить, как говорится здесь, а в блоге команды .NET как раз было упоминание, что при включении нового JIT'а функция Edit & Continue перестаёт работать.
Советую для этих целей easyhook.github.io
Очень удобное API и возможно хукать всё что движется.
Скажите, а что за прикладная задача требует подобного сравнения объектов?
Объекты из моей задачи представляют собой параметры запуска различных измерительных тестов. Поведения у таких объектов нет никакого, они являются просто-напросто контейнерами свойств. Для каждого теста известны типовые (дефолтные) параметры запуска. Так вот в UI требуется по-разному отображать тесты с дефолтными и недефолтными параметрами.
ммм. А вам не кажется, что гораздо проще было бы добавить одно единственное свойство сигнализирующее что параметры не дефолтные и заполнять его при изменении параметров в интерфейсе, чем городить заметную кучу рефлекшн кода?
Проще-проще, Вы правы. Но к сожалению, добавить такое свойство не представлялось возможным (организационно). Если бы можно было изменить все эти классы, то я бы реализовал для них всех интерфейс IEquatable<T>. Как я написал в статье, это как раз пример accidental complexity.
И еще. Вы сравниваете два ссылочных типа по свойствам. А вас не смущает, что для них может быть специальным образом переопределен метод equals, который определяет, что два объекта равны, если у них равны не все свойства, а только часть? В результате ваш метод вернет что объекты не равны, а они вообще-то равны.
В моей задаче было достаточно именно такого сравнения, поскольку сравниваемые объекты, как я ответил выше, моделируют параметры запуска тестов и являются контейнерами свойств без всякого поведения. Но Ваше замечание справедливо и в реализации ещё много чего можно улучшить. Помимо вызова переопределённого метода Equals, было бы неплохо настраивать способ сравнения строк (StringComparison) и макс. допустимое для сравнения double/float. Плюс коллекции, которые реализуют IList<T&gt (или IReadOnlyList<T>), возможно, что было бы более эффективно сравнивать не с помощью Enumerable.SequenceEqual, а циклом for. Кроме того в текущей реализации DynamicCodeComparer не учитывается, что структуры тоже могут быть коллекциями, а, например, в Roslyn такое сплошь и рядом, взять хотя бы SeparatedSyntaxList<TNode>. А ещё мне самому не очень нравится название класса DynamicCodeComparer. Задачу необходимо было решить в сжатые сроки, поэтому действительно не всё ещё доведено до ума.
UFO just landed and posted this here
Вообще говоря, нет гарантии, что свойства будут сериализованы всегда в одном и том же порядке.
UFO just landed and posted this here
И в ту же копилку, у вас нет никакой (обработки) циклических ссылок. (Раз уж мы говорим об универсальном решении).
image
Теперь мне покажут мультик?
В контакте кстати одна девушка пишет тут, что на картинке как минимум 16 отличий: «из неочевидных: зеркальное отображение и угол наклона».
Sign up to leave a comment.

Articles

Change theme settings