fody - aop
TRANSCRIPT
FodyХалявная реализация АОП для .NET
АОП
Аспектно-ориентированное программирование – парадима программирования, основанная на понятии сквозной функциональности, т.е. служебной функциональности.
Если реализовывать сквозную функциональность вместе с бизнес-логикой, то код становится полнейшей гадостью.
Примеры сквозной функциольности:
•Логирование
•Обработка исключений
•Проверка прав доступа
•Проверка правильности аргументов
•Кеширование
Fody
Fody – это фреймворк для внедрения сквозной функциональности во время компиляции.
Fody позволяет манипулировать IL кодом сборки.
Fody
В действительности Fody – это не совсем АОП.Цель у них одна, но у Fody теоретических возможностей больше, а практических меньше.Поскольку Fody сам по себе нам не интересен, мы будем рассматривать его плагины.
Fody / лицензия
Fody распространяется под MIT License
Разрешено:
• Коммерческое использование
• Изменение
• Распространение
Не разрешено:
• Жаловаться на качество
Необходимо:
• Включать копирайт(если вы собираетесь расширять Fody)
Fody / PropertyChanged
Облегчает жизнь при написании классов, реализующих INotifyPropertyChanging.
Нету необходимости дергать event PropertyChanged вручную -> снижается количество кода на объявление свойств
Fody / PropertyChanged / Атрибуты
[ImplementPropertyChanged]
Вешается на класс и все свойства автоматически начинают уведомлять о изменениях самих себя.
Все классы-наследники тоже начинают ввести себя подобным образом.
Те свойства, которые уже уведомляли о изменениях не будут уведомлять дважды.
Написанный программистом код
public int Age { get; set; }
private int age;
public int Age
{
get
{
return this.age;
}
set
{
this.age = value;
this.RaisePropertyChanged();
}
}
=>
Скомпилированный код
Fody сам отслеживает дерево завимостей свойств.
Т.е. если меняется свойство FirstName и от него зависит свойство FullName, то происходит автоматическое уведомление о изменении обоих свойств.
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName { get { return this.FirstName + this.LastName; } }
Fody / PropertyChanged / Атрибуты
[DoNotNotify]
Вешается на свойство для того, чтобы Fody не пытался уведомлять о его изменениях.
Типичное применение – для свойств, которые содержат какую-то страшную кастомную логику
Fody / PropertyChanged / Атрибуты
[AlsoNotifyFor]
Вешается на свойство для того, чтобы уведомить о изменениях другого свойства.
[AlsoNotifyFor(“FullName”)]
public string FirstName { get; set; }
public string FullName { get; set; }
Fody / PropertyChanged / Атрибуты
[DependsOn]Вешается на свойство для того, чтобы происходили уведомления о его изменении, при изменении других.
public string FirstName { get; set; }
[DependsOn(“FirstName”)]
public string FullName { get; set; }
On{PropertyName}Changed()
Если в классе есть есть метод с сигнатурой подобной
void On{PropertyName}Changed()
, то при изменении свойства PropertyName будет вызываться этот метод.
OnPropertyChanged()
Если в классе есть есть метод с сигнатурой
void OnPropertyChanged(string name, object before,object after)
, то при изменении свойств будет вызываться этот метод.
Fody / Ionad
Позволяет заменять статические вызовы одних методов статическими вызовами других.[StaticReplacement(typeof(DateTime))]public static class DateTimeSubstitute{
public static IDateTime Current { get; set; }
public static DateTime Now { get { return Current.Now; } }}
public void SomeMethod(){
var time = DateTime.Now;// ...
}
public void SomeMethod(){
var time = DateTimeSubstitute.Now;// ...
}
=>
Fody / NullGuard
Автоматический выброс исключений, если входное значение или выходное значение равно null.
Контроль осуществляется с помощью двух атрибутов:
[NullGuard] – вешается на сборку или класс
[AllowNull] – вешается на аргумент, возвращаемое значение или целое свойство
Fody / NullGuard
Конструктор [NullGuard] принимает перечисление ValidationFlags:
• Properties = 1,
• Arguments = 2,
• OutValues = 4,
• ReturnValues = 8,
• NonPublic = 16,
• Methods = Arguments | OutValues | ReturnValues,
• AllPublicArguments = Properties | Arguments,
• AllPublic = Properties | Methods,
• All = AllPublic | NonPublic
Fody / NullGuard / Примеры использования:abstract void Method([AllowNull] string arg);
[return: AllowNull]
abstract string MethodAllowsNullReturnValue() { return null; }
[AllowNull]
public string NullProperty { get; set; }
public string NullPropertyOnSet { get; [param: AllowNull] set; }
Fody / NullGuard / Замечания
Не рекомендуется его использовать на UI-шной сборке.
Более адекватным видится использование в DataAccess-слое и вью-моделях.
Fody / Equals
Занимается генерацией методов Equals(), GetHashCode(), операторов сравнения и заставляет класс реализовывать интерфейс IEquatable<T>.
Fody / Equals / Средства контроля
Атрибут [Equals] – вешается на класс, который должен будет поддерживать сравнение.
При создании можно указать следующие параметры:
• bool DoNotAddEqualityOperators
• bool DoNotAddGetHashCode
• bool DoNotAddEquals
• TypeCheck (перечисление, которое содержит возможности проверки типа (тот же тип; тот же или наследник)
Fody / Equals / Средства контроля
Атрибут [IgnoreDuringEquals] – вешается на свойство, которое нужно исключить из сравнения.
Атрибут [CustomEqualsInternal] – вешается на метод для кастомной части сравнения. Этот метод должен возвращать булево значение.
Fody / Equals / Средства контроля
Недоработка авторов плагина: [IgnoreDuringEquals] исключает свойство из генерации хеш-кода и нет возможности описать метод кастомного обсчета хеш-кода
Fody / MethodCache
Кеширование возвращаемых значений метода.
Что надо сделать:
1. В классе оставить свойство вида
private ICache Cache { get; set; }
2. В это свойство положить нашу реализацию кеша.
3. Навешать атрибут [Cache] на нужный метод.
Fody / MethodCache
Небольшой фейл разработчика. Ключ для кеширования метода, принимающего два параметра выглядит так:
string.Format("Namespace.Class.Add_{0}_{1}", new object[] { a, b });
Т.е. параметры a и b должны реализовывать хороший ToString() метод