Атрибуты полезная вещь, которая является одним из основных механизмов .net framework. В этой статье я предлагаю рассмотреть один простой пример использования атрибутов. Данная статья продолжает предыдущую статью и использует определенные там методы расширения.
Иногда существует потребность разом проверить некоторую валидность состояния объекта. К примеру, может потребоваться быть уверенным, что все необходимые поля и свойства объекта инициализированы и не равны null. Для решения такой задачи применимы атрибуты.
Вот простой пример объявления атрибута:
Объявляется атрибут для полей и свойств, который не будет наследоваться, и не будет иметь возможности задаваться несколько раз. Для обработки этого атрибут требуется некоторая логика, которую я привожу ниже (здесь и применяются один из методов расширения о которых шла речь в первой статье):
Где это применимо? Как известно, при разработке страницы или контрола на aps.net можно объявить публичное свойство и инициализировать его в разметке, примерно так:
Теперь применим для этого кода атрибут и добавим логику проверки:
В данном коде произойдет проверка BranchId на null и в случае, если BranchId не имеет значения возникнет исключение.
Комментарий: в Check передается и тип и экземпляр класса. Делается это в связи с тем, что в период выполнения тип страницы по this получить нельзя, asp.net оборачивает каждую страницу в пространство имен ASP. Все приватные поля страницы не будут видны если взять тип через this.GetType(). В связи с этим, программисту придется самому явно указать какой именно тип обрабатывать. Возможно решение не идеально, буду рад выслушать альтернативные варианты.
Иногда существует потребность разом проверить некоторую валидность состояния объекта. К примеру, может потребоваться быть уверенным, что все необходимые поля и свойства объекта инициализированы и не равны null. Для решения такой задачи применимы атрибуты.
Вот простой пример объявления атрибута:
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, Inherited = false, AllowMultiple = false)] sealed public class CheckNullAttribute : Attribute { public CheckNullAttribute() { } }
Объявляется атрибут для полей и свойств, который не будет наследоваться, и не будет иметь возможности задаваться несколько раз. Для обработки этого атрибут требуется некоторая логика, которую я привожу ниже (здесь и применяются один из методов расширения о которых шла речь в первой статье):
public class CheckNullMembers { public static void Check(Type p_type, object p_obj) { if (p_type == null || p_obj == null) throw new Exception(“Недопустимые параметры”); MemberInfo[] _members = p_type.FindMembers(MemberTypes.Field | MemberTypes.Property, BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, null); foreach (MemberInfo member in _members) { bool _isDef = Attribute.IsDefined(member, typeof(CheckNullAttribute)); if (_isDef) { if (member.GetValue(p_obj) == null) throw new Exception(String.Format("{0} не инициализировано и равно null", member.Name)); } } } }
Где это применимо? Как известно, при разработке страницы или контрола на aps.net можно объявить публичное свойство и инициализировать его в разметке, примерно так:
public int? BranchId { get; set; } <uc3:BranchHint ID="BranchHint1" runat="server" BranchId=”12” />
Теперь применим для этого кода атрибут и добавим логику проверки:
[CheckNull()] public int? BranchId { get; set; } protected void Page_Load(object sender, EventArgs e) { if (this.Visible) { CheckNullMembers.Check(this.GetType().BaseType, this); } }
В данном коде произойдет проверка BranchId на null и в случае, если BranchId не имеет значения возникнет исключение.
Комментарий: в Check передается и тип и экземпляр класса. Делается это в связи с тем, что в период выполнения тип страницы по this получить нельзя, asp.net оборачивает каждую страницу в пространство имен ASP. Все приватные поля страницы не будут видны если взять тип через this.GetType(). В связи с этим, программисту придется самому явно указать какой именно тип обрабатывать. Возможно решение не идеально, буду рад выслушать альтернативные варианты.