Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

C+Sharp+and+.NET [CSharp & .NET] 2001.08.29


Служба Рассылок Subscribe.Ru проекта Citycat.Ru

C Sharp and Dot NET

Содержание

  • 1. О рассылке
  • 2. Письма
  • 3. Reflection и атрибуты
    • 3.1. Создание атрибутов
    • 3.2. Использование атрибутов
    • 3.3. Пример
  • 4. Вопросы
    • 4.1. Как построить прокси-класс

1. О рассылке

Я вижу данную расылку, как аналог премодерируемой конференции.
Т.е. здесь мы, люди изучающие и использующие платформу .NET, сможем обменяться своими находками и идеями.
Присылайте письма с вопросами и ответами на адрес level3@mail.ru, они будут помещены в рассылку с указанием имени и (по желанию) адреса автора, если они соответствуют тематике.
На письма с очень часто задаваемыми вопросами я постараюсь ответить не помещая их в рассылку, таким образом, надеюсь, что подписка будет интересной для Вас.

[к содержанию]

2. Письма

Сегодня было прислано первое письмо, автор которого был весьма лаконичен (видимо я должен был догадаться, что это сайт, созданный с использованием технологий .NET, но у меня к сожалению, закончился траффик до конца месяца, я так и не знаю, что это такое ;) ):

-----Original Message-----
From: Alexei Nazemnov [mailto:nazemnov@technoNOlinkSPAM.ru]
Sent: Wednesday, August 29, 2001 1:52 PM
To: level3@mail.ru
Subject: .NET

http://shop.tl.ru/

[к содержанию]

3. Reflection и атрибуты

В качестве возможных применений - реализация сериализации, маршаллинга, устойчивости, мостов между объектами и реляционными базами, в визуальных дизайнерах (какие еще?)

Атрибуты могут использоваться везде, где раньше использовалась Run Time Type Information (RTTI), кроме того, на уровне методов и атрибутов.

[к содержанию]

3.1. Создание атрибутов

Атрибуты вписываются в текст программы между квадратными скобками и разделяются запятыми. Порядок следования атрибутов не важен. Один атрибут состоит из имени и параметров. Параметры бывают позиционные (те, которые передаются в конструктор атрибута) и именованные. Именованные атрибуты - это имя некоторого свойства, знак равенства и значение свойства.

 
using System;

// Ex 1: [AttributeUsage(AttributeTargets.Class |
AttributeTargets.Interface)]
// Ex 2: [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
// Ex 3: [AttributeUsage(AttributeTargets.Method, Inherited = false)]
[AttributeUsage(AttributeTargets.Method)]
public class SomeAttribute : System.Attribute
{
    ...implementation...

    public SomeAttribute(...parameters...)
    {
        ...
    }
}

При использовании AttributeUsage (точнее System.AttributeUsageAttribute),
свойство ValidOn, передаваемое через конструктор атрибута, задает элементы кода, к которым применим атрибут (в данном случае методы).

Inherited по умолчанию имеет значение true, AllowMultiple - false.

Элементы кода, к которым можно приписать атрибуты:
По группамПо алфавиту
All
ClassMembers

Assembly
Module

Class
Struct
Interface

Method
Constructor

Field
Property

Parameter
ReturnValue
Delegate

Enum

Event
All
Assembly
Class
ClassMembers
Constructor
Delegate
Enum
Event
Field
Interface
Method
Module
Parameter
Property
ReturnValue
Struct

All - атрибут может применяться ко всем элементам

ClassMembers - атрибут может применяться к классам/структурам/интерфейсам и их элементам

Если есть два класса с именами Some и SomeAttribute, то при сопоставлении имени атрибута и имен этих классов будет выбрано более точное совпадение. Однако, если есть класс, оканчивающийся на Attribute, то имя атрибута может быть автоматически дополнено, поэтому рекомендуется добавлять слово Attribute к имени создаваемого класса

 
[AttributeUsage(AttributeTargets.All)]
public class XAttribute: System.Attribute {}

[X]               // refers to XAttribute
class Class1 {}
[XAttribute]      // refers to XAttribute
class Class2 {}

Метод Attribute.GetCustomAttributes игнорирует классы, не являющиеся наследниками класса System.Attribute, поэтому рекомендуется наследовать создаваемый класс от класса System.Attribute.

[к содержанию]

3.2. Использование атрибутов

Чтобы узнать значение атрибута во время выполнения программы, нужно воспользоваться классами из библиотеки System.Reflection

[к содержанию]

3.3. Пример

В данном примере стоит обратить внимание на то, как читаются private-члены класса (для этого указываются соответствующие BindingFlags)

 

using System;
using System.Reflection;
using System.Security.Permissions;

//[assembly: ReflectionPermission(SecurityAction.RequestMinimum,
// MemberAccess = true, TypeInformation = true)]

namespace ComponentTests
{
 [AttributeUsage(AttributeTargets.Class)]
 class BuildProxyAttribute : Attribute
 {
 }

 [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
 class MappingAttribute : Attribute
 {
  string strFieldName;
  public string field
  {
   get
   {
    return strFieldName;
   }
  }
  public MappingAttribute(string strFieldName)
  {
   this.strFieldName = strFieldName;
  }
 }

 [BuildProxy]
 class TestClass
 {
  [Mapping("AlphaPoint")]
  string strA;
  [Mapping("BetaPoint")]
  string strB;
  public string Alpha
  {
   get
   {
    return strA;
   }
   set
   {
    strA = value;
   }
  }
  public string Beta
  {
   get
   {
    return strB;
   }
   set
   {
    strB = value;
   }
  }
 }

 class MainClass
 {
  static void Main(string[] args)
  {
   Console.WriteLine("Test of model");
   // Get executing assembly
   Assembly a = Assembly.GetExecutingAssembly();
   // Enumerate all types in assembly looking for
[BuildProxy] attribute
   foreach (Type t in a.GetTypes())
   {
    BuildProxyAttribute attr
     =
(BuildProxyAttribute)Attribute.GetCustomAttribute(
     t, typeof(BuildProxyAttribute));
    if(null != attr)
    {
     ProcessType(t);
    }
   }
  }
  private static void ProcessType(Type t)
  {
   Console.WriteLine("Class " + t.FullName);
   // Note   You must specify Instance or Static along
   // with Public or NonPublic or no members will be
returned.
   foreach (MemberInfo mi in t.GetMembers(
    BindingFlags.Instance |
    BindingFlags.Public |
    BindingFlags.NonPublic))
   {
    object[] marr =

mi.GetCustomAttributes(typeof(MappingAttribute), true);
    if (marr.Length == 0)
    {
     Console.WriteLine("Member " +
mi.Name);
    }
    else
    {
     MappingAttribute ma =
(MappingAttribute)marr[0];
     Console.WriteLine("Member "  +
mi.Name + " - mapped to - " + ma.field);
    }
   }
  }
 }
}

4. Вопросы

4.1. Как построить прокси-класс

Кто-нибудь пробовал построить прокси-класс для некоторого класса с помошью System.Reflection.Emit?

Иногда бывает нужно перехватить все обращения к некоторому экземпляру класса, например, если нужно иметь возможность временно разрушить объект, а затем создать его заново так, чтобы клиенты не знали об этом (типа stateless session beans)

Как запрограммировать вызов методов внутри кода прокси-класса?


Буду рад услышать о других практических применениях упомянутых и неупомянутых классов - пишите на адрес level3@mail.ru

С уважением и наилучшими пожеланиями,
Сергей Радкевич.


http://subscribe.ru/
E-mail: ask@subscribe.ru
Отписаться
Убрать рекламу
Рейтингуется SpyLog

В избранное