...

четверг, 24 апреля 2014 г.

Fody и его плагины

image

С выходом Roslyn разговоры о том, что скоро кода можно писать будет меньше вспыхнули с новой силой. Сегодня я расскажу немного о другом подходе как писать меньше кода и соответственно делать меньше ошибок — расскажу о Fody. На хабре упоминание нашёл только вскользь в рамках решения како-то проблемы. Для того, чтобы заинтересовать читателя, ещё не решившего стоит ли тратить своё время на данный текст отмечу, что популярный NotifyPropertyWeaver переехал на Fody и с помощью Fody можно делать всякие там классные AOP.


Итак, Fody — инструмент для постобработки .net сборок с целью внедрения в них своего IL кода через Cecil.Emit. Fody представляет из себя msbuild таску которая имеет конфигурационный файл в каждом из проектов, для которых будет запущена. Вот такая строка будет добавлена в каждый ProjectName.project файл



<Import Project="Fody.targets" />




Всю работу по внедрению IL делают Fody плагины, перечисленные в конфигурационном файле.

<?xml version="1.0" encoding="utf-8" ?>
<Weavers>
<SuperPluginName />
</Weavers>




Максимально ничего не делающий плагин можно себе представить, как:

public class ModuleWeaver {
// Можно писать в MSBuildLog
public Action<string> LogInfo { get; set; }
// Экземпляр Mono.Cecil.ModuleDefinition для текущей сборки
public ModuleDefinition ModuleDefinition { get; set; }
public void Execute() { }
}


Если возникает вопрос зачем Fody вообще нужен, то скажу лишь что это очень удобно. Он инсталлируется через nuget и написав свой плагин можно просто указать его как зависимость. Главное понять, как Fody будет искать этот плагин и создать правильную структуру файлов и папок в packages и всё — вы уже переписываете IL в своих сборках like a boss.


Плагины




Сам по себе fody не имеет большого смысла, поэтому представляю обзор набора плагинов с официального сайта github.com/Fody/Fody. Описание каждого плагина очень краткое, но я надеюсь достаточное чтобы принять решение стоит ли тратить время на чтение документации. Надеюсь будет полезно. У себя в блоге (alexeysuvorov.com) я разбил плагины по категориям полезные/бесполезные*, но тут я себе такого не позволяю, так что всё списком по алфавиту:

Anotar

http://ift.tt/1rozZqS

Заменяет вызов одного метода на создание/резольвинг логгера и его вызов. Имеет несколько встроенных интеграций с основными логгинг системами. Полезность сомнительна, но тут на вкус и цвет.


AssertMessage

http://ift.tt/1rozZqT



Assert.AreEqual(expectedCustomer.Money, actualCustomer.Money); // =>
Assert.AreEqual(expectedCustomer.Money, actualCustomer.Money, "Assert.AreEqual(expectedCustomer.Money, actualCustomer.Money);");




Почему бы и нет. Если Вы пользуетесь Assert — ами и не против подождать несколько лишних секунд при билде пока этот плагин дописывает за Вас строчки.

AsyncErrorHandler

http://ift.tt/1tGgk7V

Заключает async в try-catch блок в котором выполняет

AsyncErrorHandler.HandleException(exception);

Мы не пользуемся, но выглядит заманчиво, один из кандидатов на более плотное тестирование и внедрение при необходимости.


Bix.Mixers

http://ift.tt/1rozZqV

Интеграция с BixMix. Сам BixMix похоже не так давно стартанул и информации очень мало, так что пожелаем парням удачи и пойдём дальше.


Caseless

http://ift.tt/1tGgmfX

Для строк заменяет == на string.Equals с соответствующим StringComparison. Очень сомневаюсь что хочу чтобы за меня это делал IL инжектор.


Catel.Fody

http://ift.tt/1rozZqX

Делает DependencyProperty из обычных если класс унаследован от DataObjectBase или ViewModelBase. Как я понял Catel позиционирует себя как фреймворк для бизнеса поверх .net framework. Если пользуетесь Catel, то наверное будет удобно.


Commander.Fody

http://ift.tt/1tGgk7W

Реализует ICommand для MVVM. В непонятном состоянии, документация не дописана.


Costura

http://ift.tt/1rozZqZ

Для фанатов ILMerge. Склеивает зависимые сборки в одну.


FodyDependencyInjection

http://ift.tt/1tGgk7Z

Очень странный плагин. Резольвит зависимости из одного из 3-х IoC контейнеров Ninject, Autofac или Spring.Net в свойства объектов минуя конструктор. Не стал разбираться что там и как внутри, потому что посыл изначально неправильный. Я считаю, что все зависимости должны быть объявлены как параметры конструктора, а иначе черт ногу сломит разбираться в коде.


EmptyConstructor

http://ift.tt/1rozZr0

Добавляет пустой конструктор к классу если он не определён. Сомнительно полезен.


EmptyStringGuard

http://ift.tt/1tGgk81

Переписывает сеттеры и публичные методы принимающие строки, добавляет проверку на то, что строка не пустая. Если строка может быть пустая, то её можно пометить атрибутом AllowEmpty. Возможно некоторые найдут полезным, но меня больше беспокоят null чем пустые строки.


EnableFaking.Fody

http://ift.tt/1roA25Z

Ещё один «антиплагин» (первый был FodyDependencyInjection), всем классам добавляет virtual для всех мемберов публичных классов (на самом деле там ряд условий). Предполагается что это удобно для тестирования и перед продакшеном это нужно выключать. Если нужно использовать этот плагин, значит с дизайном что-то не так.


Equals

http://ift.tt/1tGgmg3

Для помеченных объектов реализует методы Equals на основе свойств входящих в объект. Если у Вас куча DTO объектов и правила их сравнения примитивно просты, то возможно это то, что нужно.


ExtraConstraints

http://ift.tt/1roA2mo

Позволяет задать delegate, enum и struct ограничения на тип параметр. C# не поддерживает такие ограничения, но в IL они вполне себе валидны. Возможно появятся в следующих версиях С# http://ift.tt/1tGgkoj.


Fielder

http://ift.tt/1roA264

Кровь кишки и расчленёнка — перефарширует все проеперти в филды. Самый безумный плагин по моему мнению.


Freezable

http://ift.tt/1tGgmg5

Во все классы унаследованные от спец интерфейса IFreezable инжектится код, который бросается исключениями на проперти сеттерах после вызова метода Freeze. Мой проеденный f# с его immutability мозг не может себе представить сценарии когда это можно использовать вместо объектов где readonly проперти задаются в конструкторе и не имеют свойств, но возможно будет полезен.


InfoOf

http://ift.tt/1roA266

Предоставляет methodof, propertyof и fieldof, но конечно никакой магии и всё нужно писать строками, которые потом перепишутся в соответствующие IL команды (да, methodof, propertyof и fieldof есть в IL). На любителя.


Ionad

http://ift.tt/1tGgmg9

Заменяет все вызовы методов статических классов на Ваши имплементации с такими же сигнатурами. Наверное, полезно для тестинга, но Fake (бывший moles) делает всё лучше.


Janitor

http://ift.tt/1roA51y

Автоматически реализует IDisposable для всех классов унаследованных от IDisposable. Использует volatile int для определения что Dispose уже был вызван. Если Вы разделяете взгляд автора плагина на то, как должен быть реализовал IDisposable, то это неплохой плагин.


JetBrainsAnnotations

http://ift.tt/1tGgkop

Jet Brains и тут подсуетился, молодцы чё.


MethodCache

http://ift.tt/1roA2mr

Мемоизация методов помеченных аттрибутами. Реализация кеша оставлена нам, что конечно радует. С удовольствием посмотрю поближе и потестирую если возникнет подходящая задача.


MethodDecorator

http://ift.tt/NfpXsJ

Декорирует методы помеченные атрибутами. Позволяет поймать момент входа в метод, выхода из него и эексепшен если произошёл. Широко используем в проекте, правда не оригинальную, а мой форк, который я допиливал под нужды проекта и заодно заимплементил несколько пожеланий из обсуждения оригинального плагина. Умеет захватывать параметры передаваемые в метод. Я про него писал. Не стесняйтесь файлить в Issues на гитхабе, постараюсь оперативно фиксить/расширять при возможности.


MethodTimer

http://ift.tt/1roA2mv

Облегчённая версия MethodDecorator, только меряет время которое заняло выполнение метода. Гадит в Debug или в логгер, который Вы ему предоставите. Возможно полезен, хотя MethodDecorator на мой взгляд удобнее.


Mixins.Fody

http://ift.tt/1roA2mx

Множественное наследование через примеси. Альтернатива Castle's dynamic proxy mixins. Я не поборник морали, так что вполне себе допускаю что вернусь к этому плагину, как только .net загонит меня в необходимость наследоваться и от класса Framework и от моего класса. Действительно было такое один раз.


ModuleInit

http://ift.tt/1tGgmwE

Собеседуя кандидатов я выяснил для себя то, что не все .net программисты в курсе, что сборка содержит в себе модули. Это плагин позволяет задать конструктор для модуля. Для тех, кто понимает.


Mutable.Fody

http://ift.tt/1roA2mA

Антипод к Freeze. Делает иммутабельное мутабельным, правда уже после того как компилятор всё скомпилировал. Имеет смысл если в F# нужно десериализовать из XML, но Newton.Json уже добавил нормальную десериализцию для immutable f# типов, так что не вижу большого смысла, только если не legacy xml.


NullGuard

http://ift.tt/1tGgkEO

Первый в очереди на использование. Генерирует проверки на null если явно неуказано что null возможен. По моему мнению такие вещи просто необходимы в языках, допускающих null.


Obsolete

http://ift.tt/1roA2mC

Позволяет использовать Obsolete аттрибут эффективно. Можно задать версию с которой при обращении к Obsolete будут происходить ошибки компиляции и версию сборки начиная с которой она не скомпилируется с классом помеченным таким атрибутом. Очень удобно я думаю.


PropertyChanged

http://ift.tt/NUPybl

Бывший NotifyPropertyWeaver. Для тех, кто не знаком – этот плагин добавляет оповещение (вызов) PropertyChanged эвента для всех сеттеров пропертей объектов, унаследованных от INotifyPropertyChanged или помеченных атрибутов. Совершенно незаменимая вещь если вы хоть раз пытались писать под WPF и его подмножества. Строго рекомендую к использованию если у вас есть UI на WPF.


PropertyChanging

http://ift.tt/1roA2mG

Тоже самое, но для интерфейса INotifyPropertyChanging.


Publicize

http://ift.tt/1roA51H

Делает приватные поля публичными «скрытыми». Мотивацию автор не стал уточнять, оставим это на его совести.


RemoveReference.Fody

http://ift.tt/1roA51J

Можно указать в атрибуте уровня сборки какие сборки вы хотите удалить из References после билда. Насколько я понял таким шаманством автор предлагает лечить вот этот баг http://ift.tt/1roA51N. Он всё ещё открыт.


Resourcer

http://ift.tt/1tGgkEV

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


Scalpel

http://ift.tt/1roA5i4

Вырезает тестовые методы и классы из сборок с кодом по конвеншену или по атрибуту. Судя по всему, Саймон (автор Fody и большинства плагинов) практикует тестирование «не отходя от кассы». Мне трудно представить мотивацию, но конечно это не самый безумный плагин, хотя уверенно входит в топ 5.


Stamp

http://ift.tt/1tGgkEX

Добавляет в AssemblyVersionInformation хешик последнего git коммита. На вкус и цвет.


Stiletto

http://ift.tt/1tGgkEY

Ещё один вариант IoC контейнера. Может похвастаться завидной всеядностью потому как работает там, где нет Reflection.Emit. Если пишете на Xamarin под iOS, то посмотрите в эту сторону, возможно это не даст совсем загрустить без IoC.


ToString

http://ift.tt/1tGgmMW

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


Usable

http://ift.tt/1tGgmMY

Заворачивает в using локальные переменные имплементирующий IDisposable. Пишите лучше ручками, надёжнее и понятней.


Validar

http://ift.tt/1roA2D1

Позволяет встроить реализацию IDataErrorInfo и INotifyDataErrorInfo в класс, реализующий INotifyPropertyCanged. Во все классы, помеченные атрибутом InjectValidation будет заинжекчена реализация IDataErrorInfo и INotifyDataErrorInfo из класса с именем ValidationTemplate конструктор которого принимает INotifyPropertyChanged. Если пишите под WPF – обязательно посмотрите, возможно это именно то, что нужно.


Visualize

http://ift.tt/1tGgkF1

Расставляет DebuggerDisplay атрибуты и если класс содержит поля, то генерирует «правильный» код который позволяет смотреть значение полей в режиме дебаггера. Интересно, что для последовательностей генерируется прокси класс. Очень интересная возможность, но я не очень люблю сидеть в отладчике предпочитая ему юнит тесты, так что платить временем сборки проекта за возможность всё посмотреть я бы не стал.


Это всё. Надеюсь я сэкономил Вам несколько часов блуждания по гитхабу в поисках фоди плагинов. Спасибо за внимание.


*Все плагины я оценивал исходя из глубин своего невежества, так что прошу не судить строго, а оппонировать в комментариях.


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Комментариев нет:

Отправить комментарий