Интернет-журнал "Домашняя лаборатория", 2007 №6 - Усманов
Описание примера
Изучаемый ниже пример разрабатывался с целью демонстрации ряда тонких моментов, связанных с контекстами, потоками и пользовательскими атрибутами. На основе использования этого примера мы проведем серию экспериментов, которые помогут прояснить излагаемые вопросы.
Как и в предыдущем разделе консольное клиентское приложение делает вклад на счет, поддерживаемый другим ранее запущенным консольным серверным приложением. Серверное приложение содержит три компонента, представляемые классами Account, Tax и News.
Компонент Account поддерживает счет, позволяя клиентам сделать вклад (метод Add) и узнать величину текущего счета (метод Total).
Компоненты Tax и News представляют соответственно налоговую службу и агентство новостей. Оба компонента получают уведомления о вкладах на счет (метод Notify) и выводят соответствующую информацию на консоль.
Компонент Tах активируется компонентом Account, который добровольно информирует Tax о каждом сделанном вкладе в процессе выполнения вызова метода Add. В свою очередь компонент Tах активирует компонент News, которому и передает полученную от Account информацию для придания ее гласности. Не полагаясь исключительно на компонент Tах, компонент Account получает от Tах ссылку на компонент News и самостоятельно напрямую посылает уведомление этому компоненту.
Для демонстрации пользовательских атрибутов, позволяющих задавать набор сервисов, доступных компонентам серверного приложения, мы будем использовать два атрибута:
• SynchronizationAttribute
Этот атрибут синхронизации реализован в .NET и уже применялся в примере предыдущей главы. Как уже отмечалось выше, семантика этого атрибута весьма не проста, и для ее полного понимания полезно познакомиться с кодом этого атрибута, представленным в SSCLI (файл sscli clr scr bcl system runtime remoting synchronizeddispatch.es). Этот код содержит 1010 строк (вместе с комментариями). Мы не будем здесь его разбирать полностью, однако основные сведения, полученные при его изучении, будут в данной главе изложены и продемонстрированы в экспериментах.
• MyCallTraceAttribute
Код этого атрибута трассировки вызовов приводится в данной главе. Надо заметить, что атрибуты с семантикой трассировки вызовов очень популярны среди авторов, пишущих на темы .NET. Приведенный здесь код содержит фрагменты из ряда опубликованных примеров (в частности, из кода к статье [АОРЗ]) и используется исключительно в демонстрационных целях.
Весь код примера содержится в трех файлах:
• MyApp.cs
Этот файл содержит код консольного клиентского приложения.
• MyServer.cs
Файл содержит код консольного серверного приложения и трех компонентов (Account, Tax, News).
• MyCallTrace.cs
Этот файл содержит код атрибута трассировки вызовов.
Ниже приводится makefile, который можно использовать для компиляции и сборки клиентского и серверного приложений
all: МуАрр MyServer
clean:
@del МуАрр. exe MyServer.exe
МуАрр: МуАрр. ехе
МуАрр. exe: MyApp.cs MyServer.exe
csc /r: MyServer.exe MyApp.cs
MyServer: MyServer.exe
MyServer.exe: MyServer.cs MyCallTrace.cs
csc MyServer.cs MyCallTrace.cs
Из этого кода видно, что и клиентское, и серверное приложение являются приложениями типа .ехе и запускаются в различных доменах приложений. Для использования этого makefile достаточно запустить nmake, в результате чего будут получены файлы МуАрр. ехе и MyServer.ехе.
Серверное приложение
Ниже приводится код из файла MyServer.cs, который является некоторым расширением одноименного файла, рассмотренного в предыдущей главе.
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using System.Threading;
using System.Runtime.Remoting.Contexts;
namespace SPbU.AOP_NET {
public interface IAccumulator {
void Add(int sum);
}
public interface IAudit {
int Total();
}
[Synchronization()]
[MyCallTrace("LogFile")]
public class Account: ContextBoundObject,
IAccumulator, IAudit {
private Tax _tax;
private int _sum = 0;
public Account() {
_tax = new Tax ();
Console.WriteLine("Account context = " +
Thread.CurrentContext.ContextID + "n" +
"Account constructor thread = " +
Thread.CurrentThread.GetHasheode() +
" IsPoolThread = " +
Thread.CurrentThread.IsThreadPoolThread);
}
public void Add(int sum) {
_sum += sum;
_tax.Notify("new Account operation: +" + sum); _
_tax.news.Notify("direct notification from Account");
Console.WriteLine("Account Add thread = " +
Thread.CurrentThread.GetHasheode() +
" IsPoolThread = " +
Thread.CurrentThread.IsThreadPoolThread);
}
public int Total() {
return _sum;
}
}
[Synchronization()]
[MyCallTrace("LogFile")]
public class Tax: ContextBoundObject {
private News _news;
public Tax() {
_news = new News();
Console.WriteLine("Tax context = " +
Thread.CurrentContext.ContextID + "n" +
"Tax constructor thread = " +
Thread.CurrentThread.GetHasheode() +
" IsPoolThread = " +
Thread.CurrentThread.IsThreadPoolThread);
}
public void Notify(String msg) {
Console.WriteLine("Tax notification: " + msg);
Console.WriteLine("Tax Notify thread = " +
Thread.CurrentThread.GetHasheode() +
" IsPoolThread = " +
Thread.CurrentThread.IsThreadPoolThread);
_news.Notify(msg);
}
public News news {
get {
return _news;
}
}
}
[Synchronization()]
[MyCallTrace("LogFile")]
public class News: ContextBoundObject {
public News(){
Console.WriteLine("News context = " +
Thread.CurrentContext.ContextID + "n" +
"News constructor thread = " +
Thread.CurrentThread.GetHasheode() +
" IsPoolThread = " +
Thread.CurrentThread.IsThreadPoolThread);
}
public void Notify(String msg) {
Console.WriteLine("News notification: " + msg);
Console.WriteLine("News Notify thread = " +
Thread.CurrentThread.GetHasheode() +
" IsPoolThread = " +
Thread.CurrentThread.IsThreadPoolThread);
}
}
public class AccountApp {
public static void Main(){
HttpChannel myChannel = new HttpChannel(8080);
ChannelServices.RegisterChannel(myChannel);
RemotingConfiguration.RegisterWellKnownServiceType (
typeof(Account), "Account",
WellKnownObjectMode.Singleton);
Console.WriteLine("Server is listening");
Console.ReadLine();
Console.WriteLine("Bye");
}
}
}
Некоторые комментарии:
1. Определяемые в этом коде классы включаются в новое пространство имен — SPBU. AOP_NET. В этом же пространстве имен
Откройте для себя мир чтения на siteknig.com - месте, где каждая книга оживает прямо в браузере. Здесь вас уже ждёт произведение Интернет-журнал "Домашняя лаборатория", 2007 №6 - Усманов, относящееся к жанру Газеты и журналы / Сделай сам / Хобби и ремесла. Никаких регистраций, никаких преград - только вы и история, доступная в полном формате. Наш литературный портал создан для тех, кто любит комфорт: хотите читать с телефона - пожалуйста; предпочитаете ноутбук - идеально! Все книги открываются моментально и представлены полностью, без сокращений и скрытых страниц. Каталог жанров поможет вам быстро найти что-то по настроению: увлекательный роман, динамичное фэнтези, глубокую классику или лёгкое чтение перед сном. Мы ежедневно расширяем библиотеку, добавляя новые произведения, чтобы вам всегда было что открыть "на потом". Сегодня на siteknig.com доступно более 200000 книг - и каждая готова стать вашей новой любимой. Просто выбирайте, открывайте и наслаждайтесь чтением там, где вам удобно.


