- •1. Язык программирования c# 3
- •2. Базовые элементы .Net Framework 67
- •3. ТЕхнология .Net Remoting 144
- •Введение
- •1. Язык программирования c#
- •1.1. Платформа .Net – обзор архитектуры
- •1.2. Язык c# - общие концепции синтаксиса
- •1.3. Система типов языка c#
- •1.4. Преобразования типов
- •1.5. Идентификаторы, ключевые слова и литералы
- •1.6. Объявление переменных, полей и констант
- •1.7. Выражения и операции
- •1.8. Операторы языка c#
- •1.9. Объявление и вызов методов
- •1.10. Массивы в c#
- •1.11. Работа с символами и строками в c#
- •1.12. Синтаксис объявления класса, Поля и методы класса
- •1.13. Свойства и индексаторы
- •1.14. Конструкторы класса и Жизненный цикл объекта
- •1.15. Наследование классов
- •1.16. Перегрузка операЦий
- •1.17. Делегаты
- •1.18. События
- •1.19. Интерфейсы
- •1.20. Структуры и перечисления
- •1.21. Пространства имен
- •1.22. Генерация и обработка исключительных ситуаций
- •1.23. Нововведения в языке c# 2.0
- •1.24. Обобщенные типы (generics)
- •2. Базовые элементы .Net Framework
- •2.1. Метаданные и механизм отражения
- •2.2. Пользовательские и встроенные атрибуты
- •2.3. Пространство имен system.Collections
- •2.4. Работа с файлами и директориями
- •2.5. Использование потоков данных
- •2.6. Сериализация
- •2.7. Сериализация объектов в нестандартном формате
- •2.8. Введение в xml
- •2.9. Работа с xml-документами в .Net framework
- •2.10. МНогопоточное программирование
- •2.11. Синхронизация потоков
- •2.12. Асинхронный вызов методов
- •2.13. Состав и взаимодействие сборок
- •2.14. Конфигурирование сборок
- •3. ТЕхнология .Net Remoting
- •3.1. Домены приложений
- •3.2. Архитектура .Net Remoting
- •3.3. Активация удаленных объектов и их время жизни
- •3.4. Программная настройка Remoting
- •3.5. Удаленные Объекты с клиентской активацией
- •3.6. Настройка Remoting при помощи конфигурационных файлов
- •3.7. Хостинг распределенных приложений
- •3.8. Объекты-сообщения
- •3.9. Пользовательские канальные приемники
- •4.1. Архитектура ado.Net
- •4.2. Учебная база cd Rent
- •4.3. Соединение с базой данных
- •4.4. Выполнение команд и запросов к базе данных
- •4.5. Чтение данных и объект DataReader
- •4.6. Параметризированные запросы
- •4.7. Рассоединенный набор данных
- •4.8. Заполнение Рассоединенного набора данных
- •4.9. Объект класса DataColumn – колонка таблицы
- •4.10. Объекты класса DataRow – строки таблицы
- •4.11. Работа с объектом класса DataTable
- •4.12. DataSet и схема рассоединенного набора данных
- •4.13. Типизированные DataSet
- •4.14. Поиск и фильтрация данных в DataSet
- •4.15. Класс DataView
- •4.16. СиНхронизация набора данных и базы
- •5.1. Архитектура и общие концепции asp.Net
- •5.2. Пример aspx-страницы. Структура страницы
- •5.3. Директивы страницы
- •5.4. Класс System.Web.Ui.Page. События страницы
- •5.5. Серверные элементы управления
- •5.6. Элементы управления Web Controls
- •5.7. Проверочные элементы управления
- •5.8. Списковые элементы управления
- •5.9. Связывание данных
- •5.11. Управление состояниями в web-приложениях
- •5.12. Кэширование
- •5.13. Безопасность в web-приложениях
- •5.14. Создание пользовательских элементов управления
- •Литература
3.4. Программная настройка Remoting
Разберем настройку и использование Remoting на следующем примере. Предположим, что планируется реализовать в виде удаленного сервиса калькулятор, который производит четыре арифметических действия. На первом этапе выделим функционал сервиса и оформим его описание в виде интерфейса:
namespace BSUIR {
public interface ICalc {
double Add(double x, double y);
double Sub(double x, double y);
double Mult(double x, double y);
double Div(double x, double y);
}
}
Скомпилируем интерфейс в динамическую библиотеку ICalc.dll.
В качестве непосредственной реализации интерфейса BSUIR.ICalc рассмотрим класс BSUIR.Calculator:
using System;
namespace BSUIR {
public class Calculator: ICalc {
public Calculator() {
log("Calculator constructor");
}
public double Add(double x, double y) {
log("Add " + x + " + " + y);
return x+y;
}
public double Sub(double x, double y) {
log("Sub " + x + " - " + y);
return x-y;
}
public double Mult(double x, double y) {
log("Mult " + x + " * " + y);
return x*y;
}
public double Div(double x, double y) {
log("Div " + x + " / " + y);
return x/y;
}
public static void log(string s) {
Console.WriteLine("[{0}]: {1}",
AppDomain.CurrentDomain.FriendlyName, s);
}
}
}
Класс Calculator скомпилирован в динамическую библиотеку с именем calc.dll. Для компиляции класса необходимо установить ссылку на сборку ICalc.dll.
Итак, на данном этапе у нас имеются:
интерфейс BSUIR.ICalc, размещенный в отдельной динамической библиотеке ICalc.dll;
класс BSUIR.Calculator, который реализует интерфейс BSUIR.ICalc и размещается в динамической библиотеке calc.dll.
Что дает подобное разделение на интерфейс и реализующий его класс? Преимущества подхода заключаются в следующем: для клиентов необходим только интерфейс BSUIR.ICalc, без его реализации. Мы можем менять на серверной части нашего распределенного приложения класс BSUIR.Calculator совершенно «прозрачно» для клиентов, пока класс поддерживает интерфейс BSUIR.ICalc. Если бы разделение не выполнялось, то клиенту понадобился бы класс BSUIR.Calculator на локальной машине, хотя и предполагалось бы удаленное использование объектов данного класса.
Построим сервер для нашего распределенного приложения. Прежде всего, нам необходимо внести некоторые изменения в класс BSUIR.Calculator.
using System;
namespace BSUIR {
public class Calculator: MarshalByRefObject, ICalc {
// далее по коду изменений нет
. . .
}
}
Напомним, что наследование от MarshalByRefObject – это обязательное условие для удаленных типов.
Код настройки сервера будет размещаться в методе Main() консольного приложения (собственно, данное приложение и будет сервером1). Во-первых, необходимо создать объект, описывающий канал. Воспользуемся классом HttpChannel (пространство имен System.Runtime.Remoting.Channels.Http) для создания стандартного канала на основе протокола HTTP:
HttpChannel chan = new HttpChannel(6000);
Параметром конструктора является номер порта, с которым связан канал (канал прослушивает данный порт).
Созданный канал должен быть зарегистрирован в инфраструктуре. Для этого используется статический метод RegisterChannel() класса ChannelServices из пространства имен System.Runtime.Remoting.Channels:
ChannelServices.RegisterChannel(chan);
После создания и регистрации канала требуется зарегистрировать класс, объекты которого предполагается использовать удаленно. Для регистрации класса используются статические методы класса RemotingConfiguration. В нашем примере будут использоваться объекты с серверной активацией в режиме SingleCall:
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(Calculator),
"theEndPoint",
WellKnownObjectMode.SingleCall);
Параметры метода: тип регистрируемого класса; строка, представляющая концевую точку для типа; элемент перечисления WellKnownObjectMode, указывающий на режим использования серверных объектов (Singleton или SingleCall).
После регистрации канала и удаленного типа сервер переводится в режим ожидания. Полный текст сервера приведен ниже:
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using BSUIR;
class CalcServer {
public static void Main() {
HttpChannel chan = new HttpChannel(6000);
ChannelServices.RegisterChannel(chan);
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(Calculator),
"theEndPoint",
WellKnownObjectMode.SingleCall);
Console.WriteLine("Press [enter] to exit...");
Console.ReadLine();
}
}
При компиляции сервера необходимо установить ссылку на сборку calc.dll и сборку ICalc.dll.
Приступим к написанию клиента. Как и сервер, клиент будет консольным приложением, логика работы которого сосредоточена в методе Main().
Клиент должен зарегистрировать канал. При вызове конструктора канала на клиенте можно использовать 0 в качестве параметра или применить конструктор без параметров. В последнем случае клиент не сможет принимать вызовы сервера. Это не всегда приемлемо (например, при работе со спонсорами, асинхронных вызовов методов и т. п.).
HttpChannel chan = new HttpChannel(0);
ChannelServices.RegisterChannel(chan);
Для соединения с сервером и получения ссылки на удаленный объект можно использовать статический метод Connect() класса RemotingServices. В качестве параметров методу передается тип запрашиваемого объекта и универсальный идентификатор ресурсов, указывающий на концевую точку, связанную с серверным объектом. Типом запрашиваемого объекта в нашем случае будет интерфейс ICalc, так как работа будет вестись через этот интерфейс:
object obj = RemotingServices.Connect(typeof(ICalc),
"http://localhost:6000/theEndPoint");
Получить ссылку на удаленный объект можно при помощи метода Activator.GetObject(). Использование данного метода понятно из примера:
object obj = Activator.GetObject(typeof(ICalc),
"http://localhost:6000/theEndPoint");
После запроса полученную ссылку требуется привести к типу ICalc, а затем можно вызывать методы удаленного объекта:
ICalc calc = (ICalc)obj;
calc.Add(3, 4);
Полный листинг клиента приведен ниже:
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using BSUIR;
class CalcClient {
public static void Main() {
HttpChannel chan = new HttpChannel(0);
ChannelServices.RegisterChannel(chan);
object obj = RemotingServices.Connect(typeof(ICalc),
"http://localhost:6000/theEndPoint");
ICalc calc = (ICalc)obj;
calc.Add(3, 4);
}
}
Для программной настройки инфраструктуры Remoting применялся класс RemotingConfiguration. Подробное описание свойств и методов этого класса приведено в таблице. Все свойств и методы являются статическими.
Таблица 18
Статические элементы класса RemotingConfiguration
Имя элемента |
Описание |
ApplicationId |
Строка, содержащая GUID для приложения |
ApplicationName |
Строка с именем приложения. Является частью URI удаленного CAO-типа для клиентов |
Configure |
Метод используется в случае, когда настройки Remoting хранятся в конфигурационном файле |
GetRegisteredActivatedClientTypes GetRegisteredActivatedServiceTypes GetRegisteredWellKnownClientTypes GetRegisteredWellKnownServiceTypes |
Набор методов, позволяющих получить все зарегистрированные типы в виде массива |
IsActivationAllowed |
Метод проверяет на сервере, является ли тип, указанный в качестве параметра, типом с клиентской активацией |
IsRemotelyActivatedClientType |
Метод проверяет на клиенте, является ли тип, указанный в качестве параметра, типом с клиентской активацией |
IsWellKnownClientType |
Метод проверяет на клиенте, является ли тип, указанный в качестве параметра, типом с серверной активацией |
ProcessId |
Строка, содержащая уникальный GUID текущего процесса |
RegisterActivatedClientType RegisterActivatedServiceType RegisterWellKnownClientType RegisterWellKnownServiceType |
Набор методов для регистрации типов различных видов на клиенте и на сервере |