Добавить в цитаты Настройки чтения

Страница 213 из 372

Простое решение проблемы — создать контекст синхронизации, в который и поместить серверный компонент. В этом случае новый поток блокируется при входе этот контекст, если в нем исполняется какой-либо другой поток. Для этого достаточно пометить наш класс Account атрибутом [Synchronization ()] и привязать его к контексту, в котором он будет создаваться. Для этого класс Account должен наследовать классу ContextBoundObject, который в свою очередь является производным от класса MarshalByRefObject.

Ниже приведен полный код сервера, для которого вышеописанных проблем синхронизации больше нет

using System;

using System.Runtime.Remoting;

using System.Runtime.Remoting.Cha

using System.Runtime.Remoting.Cha

using System.Threading;

using System.Runtime.Remoting.Contexts;

namespace MyServer {

public interface IAccumulator {

       void Add(int sum);

}

public interface IAudit {

        int Total();

}

[Synchronization()]

public class Account: ContextBoundObject, IAccumulator, IAudit {

         protected int _sum = 0;

         public void Add(int sum) {

             int s = _sum;

             Thread.Sleep(1);

             _sum = s + sum;

         }

         public int Total() {

             return _sum;

         }

}

public class AccountApp {

         public static void Main() {

              HttpCha





              Cha

              RemotingConfiguration.RegisterWellKnownServiceType {

                    typeof(Account),

                    "Account",

                    WellKnownObjectMode.Singleton);

              Console.WriteLine("Server is listening");

              Console.ReadLine();

              Console.WriteLine("Bye");

          }

}

}

И несколько комментариев. В.NET синхронизацию можно обеспечить либо с помощью критических секций, встраиваемых в код компонента, либо декларативно с помощью контекста синхронизации. Последнее похоже на использование понятия активности в СОМ+.

Привязка объекта к контексту позволяет использовать при работе с этим объектом различные сервисы (например, синхронизации, поддержки транзакций и т. п.). Но зато и обращаться к такому объекту извне его контекста можно только через прокси. Однако это прозрачно для клиента, не нужно создавать и регистрировать какие-либо каналы (при работе в рамках одного домена приложения). Если объект не привязан к контексту, то он располагается в специальном контексте по умолчанию. К контексту по умолчанию имеют прямой доступ все потоки, исполняемые в данном домене приложения.

Набор сервисов, доступных объектам привязанным к контексту, можно расширять вводя новые атрибуты и реализуя перехват вызовов методов этих объектов. Подробнее эти важные вопросы будут рассмотрены в следующем разделе.

NET и аспектно-ориентированное программирование

Введение

Говоря про компонентное программирование нельзя не упомянуть про парадигму аспектно-ориентированного программирования (АОП). Элементы этой парадигмы встречаются в области технологии программирования уже достаточно давно. Это субъектно — ориентированное программирование (subject — oriented programming) [SOP1, SOP2], композиционные фильтры (composition filters) [CF1, CF2], адаптивное программирование (adaptive programming) [AP1, АР2]. В наиболее явной форме формулировка данной парадигмы представлена в работе [АОР1]. Хороший обзор по АОП представлен в диссертации [АОР2]. И, наконец, связи между АОП и .NET отражены в статье [АОР3].

С точки зрения АОП в процессе разработки достаточно сложной системы программист решает две ортогональные задачи:

• Разработка компонентов

• Разработка сервисов, поддерживающих взаимодействие компонентов

Такие языки программирования как, например, C++, VB и т. п. ориентированы прежде всего на решение первой задачи. Код компонента представляется в виде класса, т. е. он хорошо локализован и, следовательно, его легко просматривать, изучать, модифицировать, повторно использовать. С другой стороны, при программировании процессов, в которые вовлечены различные объекты, мы получаем код, в котором элементы, связанные с поддержкой такого процесса, распределены по коду всей системы. Эти элементы встречаются в коде множества классов, их совокупность в целом не локализована в обозримом сегменте кода. В результате мы сталкиваемся с проблемой "запутанного" кода (code tangling).

В рамках АОП утверждается, что никакая технология проектирования не поможет решить данную проблему, если только мы будем оставаться в рамках языка, ориентированного только на разработку компонентов. Для программирования сервисов, обеспечивающих взаимодействие объектов, нужны специальные средства, возможно специальные языки.

Понятие аспект в рамках АОП в диссертации [АОР2] определено так: "Некоторая модель является аспектом другой модели, если она пересекает (crosscuts) ее структуру". Иными словами понятие аспекта относительно. Если, например, в качестве модели некоторой системы мы рассматриваем совокупность компонентов, представляющих такие сущности как вкладчик, счет, банк, то аспектами являются сервисы, обеспечивающие синхронизацию доступа к счету, распределенные транзакции, безопасность. То есть автоматически выполняемые сервисы, обеспечивающие слаженную, надежную, безопасную работу компонентов.

Итак, согласно парадигме АОП, для программирования компонентов и аспектов нужны различные, специфические языки программирования. После этапа кодирования компонентов и аспектов на соответствующих языках выполняется автоматическое построение оптимизированного для выполнения (но не для просмотра и модификации) кода (например, на С). Этот финальный процесс называется слиянием (weaving).

В рамках СОМ+ элементы идей АОП присутствуют в виде использования декларативного программирования для задания сервисов, услугами которых будут пользоваться компоненты. Сами компоненты разрабатываются на языках, ориентированных на разработку компонентов (C++, VB). При конфигурировании компонента в СОМ+ приложении задается некоторый набор атрибутов, определяющий тот набор сервисов, которыми будет пользоваться данный компонент.

В СОМ+ набор возможных сервисов и, соответственно, задающих их атрибутов, фиксирован. Программист не может разработать новый сервис, который можно было бы декларативно связать с некоторым компонентом, приписав последнему соответствующий атрибут. Ситуация изменилась в .NET. Хотя и осталась возможность использовать все сервисы из СОМ+, появилась новая возможность разработки новых сервисов, подключаемых к компонентам декларативно, посредством определения новых атрибутов. Весь этот механизм основан на таких понятиях как контекст и пользовательский атрибут.

Прежде чем мы перейдем к рассмотрению контекстов и атрибутов необходимо заметить, что в документации к .NET отсутствует информация о ряде важнейших классов и интерфейсов, которые нам предстоит использовать. Указывается, что эти классы и интерфейсы предназначены для использования самой системой (CLR), и что не предполагается их использование разработчиками приложений. Тем не менее получить информацию об этих классах и интерфейсах возможно. Имеются статьи (например, [АОРЗ]), код, в которых демонстрируется использование данных классов и интерфейсов.

Важнейшим новым источником информации является опубликованный Microsoft весной 2002 года код объемом около 1.9 млн строк и документация к нему — Shared Source Common Language Infrastructure (SSCLI). Этот код является одной из возможных реализаций спецификации языка C# и Common Language Infrastructure (CLI), принятых европейской организацией стандартизации ЕСМА в конце 2001 года .NET Framework является коммерческой реализацией этой же спецификации.