Чтение онлайн

на главную - закладки

Жанры

Интернет-журнал "Домашняя лаборатория", 2007 №6
Шрифт:

Заметим, что при наличии нескольких атрибутов, приписанных классу, пригодность старого контекста для активации в нем нового экземпляра этого класса считается установленной, если вызовы метода IsContextOK для каждого атрибута возвратили true.

? Виртуальный метод GetPropertiesForNewContext объявлен в интерфейсе IContextAttribute. В качестве аргумента этот метод принимает сообщение ctorMsg типа IConstructionCallMessage. Данный метод вызывается средой выполнения CLR если контекст, из которого был сделан запрос на активацию объекта, не удовлетворяет

его требованиям (вызов IsContextOK вернул false). Здесь мы включаем в сообщение ctorMsg ссылку на объект, который будет играть роль нового свойства контекста — (IContextProperty) this. Благодаря этой ссылке все объекты, которые будут жить в новом контексте, смогут пользоваться данным свойством контекста, вызывая явно в своем коде его методы и свойства.

? Метод GetServerContextSink объявлен в интерфейсе IContributeServerContextSink и не имеет реализации в классе ContextAttribute. Этот метод должен вернуть ссылку на объект, реализующий интерфейс IMessageSink, т. е. на перехватчик, который будет подключен в конец существующей цепочки перехватчиков, через которую идут все вызовы в данный контекст. Единственным аргументом является ссылка nextSink на конец имеющейся в данный момент цепочки перехватчиков. В данной реализации этого метода формируется экземпляр класса MyCallTraceServerContextSink, который будет прокомментирован ниже.

Ссылка на этот экземпляр (новый перехватчик) и возвращается как результат вызова GetServerContextSink.

Данный метод вызывается средой выполнения в случае, когда в новый контекст добавляется новое свойство контекста, которое при этом реализует интерфейс IContributeServerContextSink, сигнализируя о том, что нужно добавить новый перехватчик вызовов.

? Последний метод (LogMessage) класса MyCallTraceAttribute является внутренним для сборки и будет вызываться из класса MyCallTraceServerContextSink. Данный метод обеспечивает запись переданной в качестве аргумента строки в конец файла с именем, хранящемся в поле _logFileName свойства типа MyCallTraceAttribute с именем MyCallTrace текущего контекста. Объекты, живущие в данном контексте, могут вызывать этот метод явно в своем коде, получив ссылку на это свойство контекста по его имени. Однако в данном примере будет продемонстрировано использование свойства контекста в стиле аспектно-ориентированного программирования. Поэтому метод LogMessage будет в нашем случае вызываться перехватчиком, а не самим объектом, получившим вызов.

Реализации метода LogMessage весьма не эффективна. При каждом вызове этого метода файл открывается для записи в конец, производится запись и файл закрывается. Для обеспечения потокобезопасности весь метод включается в критическую секцию, препятствующую параллельному выполнению этого метода несколькими потоками. Для этого методу приписан атрибут [MethodImpl(MethodImplOptions. Synchronized)].

Цикл

while (logFile == null) {

logFile = File. AppendText(_logFileName);

}

обеспечивает выполнение повторных попыток открытия файла до тех пор, пока очередная такая попытка не увенчается успехом. Не смотря на то, что операции открытия и закрытия файла выполняются в рамках одной критической секции, в силу асинхронности этих операций открытие файла может произойти с некоторой задержкой после успешного выполнения команды закрытия файла.

4. Комментарий К коду класса MyCallTraceContextSink

? Данный внутренний класс реализует интерфейс IMessageSink и, следовательно, реализует некоторый перехватчик,

? Поле _nextsink будет хранить ссылку на следующий перехватчик в той цепи перехватчиков, в конец которой будет добавлен данный перехватчик,

? Поле _property предназначено для хранения ссылки на свойство контекста типа MyCallTraceAttribute. Перехватчик порождается благодаря методу GetPropertiesForNewContext, реализованного этим свойством контекста. Однако сейчас нам это свойство важно тем, что именно его метод LogMessage будет вызываться перехватчиком при перехвате нового вызова,

? Поле _replyMsg типа IMessage будет хранить ответ вызванного метода, полученный данным перехватчиком от перехватчика nextsink. о Конструктор данного класса принимает два аргумента:

property

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

nextSink

Это ссылка на следующий перехватчик в цепи перехватчиков.

Данные значения присваиваются соответственно полям _property и _nextsink.

? Виртуальный метод SyncProcessMessage объявлен в интерфейсе IMessageSink. Этот метод реализует обработку синхронных вызовов, т. е. вызовов, после инициализации которых клиенты блокируются до получения ответа.

Единственный аргумент данного метода — сообщение reqMsg (request message), содержащее вызов, полученный от клиента и уже, возможно, обработанный перехватчиками, находящимися в цепочке ближе к клиенту.

Прежде всего выясняется тип полученного сообщения. Если это сообщение типа IMethodMessage, то это сообщение представляет собой именно вызов некоторого метода, который и должен перехватить наш перехватчик. При получении сообщения другого типа данный перехватчик пропускает его дальше без какой-либо обработки.

Обработка вызова состоит в том, что перехватчик выводит с помощью LogMessage информацию о типе, о методе и о входных ([IN]) аргументах. Пример (слегка отредактированный для удобства просмотра) выводимой информации в случае вызова метода Notify экземпляра класса News приведен ниже:

===SPbU.AOP_NET.News, MyServer, Version = 0.0.0.0,

Culture = neutral, PublicKeyToken = null

Notify

<<<IN>>> parameters: {

msg = new Account operation: +5)

}

В процессе обработки перехваченного вызова сообщение reqMsg приводится к типу IMethodMessage и блокируется свойство контекста _property. Эта блокировка позволит при записи информации в файл посредством вызова LogMessage группировать все строки, относящиеся к одному вызову, вместе, т. е. не допускать в файле с именем _logFileName чередования строк, относящихся к различным вызовам.

Поделиться:
Популярные книги

Дайте поспать!

Матисов Павел
1. Вечный Сон
Фантастика:
юмористическое фэнтези
постапокалипсис
рпг
5.00
рейтинг книги
Дайте поспать!

Пустоцвет

Зика Натаэль
Любовные романы:
современные любовные романы
7.73
рейтинг книги
Пустоцвет

Его темная целительница

Крааш Кира
2. Любовь среди туманов
Фантастика:
фэнтези
5.75
рейтинг книги
Его темная целительница

Камень. Книга вторая

Минин Станислав
2. Камень
Фантастика:
фэнтези
8.52
рейтинг книги
Камень. Книга вторая

Стеллар. Заклинатель

Прокофьев Роман Юрьевич
3. Стеллар
Фантастика:
боевая фантастика
8.40
рейтинг книги
Стеллар. Заклинатель

Последняя Арена

Греков Сергей
1. Последняя Арена
Фантастика:
боевая фантастика
постапокалипсис
рпг
6.20
рейтинг книги
Последняя Арена

Последняя Арена 3

Греков Сергей
3. Последняя Арена
Фантастика:
постапокалипсис
рпг
5.20
рейтинг книги
Последняя Арена 3

Возвышение Меркурия. Книга 15

Кронос Александр
15. Меркурий
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 15

Её (мой) ребенок

Рам Янка
Любовные романы:
современные любовные романы
6.91
рейтинг книги
Её (мой) ребенок

Польская партия

Ланцов Михаил Алексеевич
3. Фрунзе
Фантастика:
попаданцы
альтернативная история
5.25
рейтинг книги
Польская партия

Идеальный мир для Лекаря 18

Сапфир Олег
18. Лекарь
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 18

Ненаглядная жена его светлости

Зика Натаэль
Любовные романы:
любовно-фантастические романы
6.23
рейтинг книги
Ненаглядная жена его светлости

Пушкарь. Пенталогия

Корчевский Юрий Григорьевич
Фантастика:
альтернативная история
8.11
рейтинг книги
Пушкарь. Пенталогия

Темный Лекарь 2

Токсик Саша
2. Темный Лекарь
Фантастика:
фэнтези
аниме
5.00
рейтинг книги
Темный Лекарь 2