public class CarProvider: MarshalByRefObject {
private List‹JamesBondCar› theJBCars = new List‹JamesBondCar›();
public CarProvider (JamesBondCar[] theCars){
Console.WriteLine("Создание поставщика Car");
Console.WriteLine("с помощью пользовательского конструктора');
theJBCars.AddRange(theCars);
}
…
}
Чтобы позволить вызывающей стороне активизировать CarProvider с помощью нового конструктора, нужно построить приложение сервера, которое зарегистрирует CarProvider, как САО-тип, а не как WKO-тип. Это можно сделать программно с помощью метода, аналогичного RemotingConfiguration.RegisterActivatedServiceType(), или с помощью файла *.config на стороне сервера. Чтобы "жестко" задать имя CAO-объекта в программном коде сервера, передайте информацию типа или типов (после создания и регистрации канала), как предлагается ниже.
// "Жёсткое" указание того, что CarProvider является САО-типом.
RemotingConfiguration.RegisterActivatedServiceType(typeof(CAOCarGeneralAsm.CarProvider));
Если вы предпочтете использовать файл *.config, вместо элемента ‹wellknown› используйте элемент ‹activated›, как показано ниже.
‹configuration›
‹system.runtime.remoting›
‹application›
‹service›
‹activated type = "CAOCarGeneralAsm.CarProvider, CAOCarGeneralAsm"/›
‹/service›
‹channels›
‹channel ref="tcp" port="32496" /›
‹ /channels›
‹/ application›
‹/system.runtime.remoting›
‹/configuration›
Наконец, нужно обновить приложение клиента, и не только с целью учета соответствующего файла *.config (или программных изменений в базовом коде) для запроса доступа к удаленному САО-объекту, но и с тем, чтобы вызвать созданный пользовательский конструктор типа CarProvider. Вот как должен выглядеть модифицированный метод Main() на стороне клиента.
static void Main(string[] args) {
// Чтение обновленного файла *.config.
RemotingConfiguration.Configure("CAOCarProviderClient.exe.config");
// Создание массива типов для передачи поставщику.
JamesBondCar[] cars = {
new JamesBondCar ("Viper", 100, true, false),
new JamesBondCar("Shaken", 100, false, true),
new JamesВоndCar("Stirred", 100, true, true)
};
// Теперь вызов пользовательского конструктора.
CarProvider ср = new CarProvider(cars);
…
}
Обновленный файл *.сonfig клиента также должен использовать элемент ‹activated›, а не элемент ‹wellknown›. Кроме того, свойство url элемента ‹client› теперь должно указывать адрес зарегистрированного САО-объекта. Напомним, что при регистрации типа CarProvider сервером в виде WKO-объекта, клиент указывал соответствующую информацию в рамках элемента ‹wellknown›.
‹configuration›
‹system.runtime.remoting›
‹application›
‹client displayName = "CarClient" url = "tcp://localhost:32469"›
‹activated type="CAOCarGeneralAsm.CarProvider, CAOCarGeneralAsm"/›
‹/client›
‹channels›
‹channel ref="tcp"/›
‹/channels›
‹/application›
‹/system.runtime.remoting›
‹/configuration›
Чтобы "жестко" запрограммировать запрос САО-типа клиентом, можете использовать метод RegistrationServices.RegisterActivatedClientType(), как показано ниже.
static void Main(string[] args) {
// Использование "жестких" значений.
RemotingConfiguration.RegisterActivatedClientType(typeof(CAOCarGeneralAsm.CarProvider), "tcp://localhost:32469");
}
Запустив на выполнение обновленные компоновочные блоки сервера и клиента, вы с удовлетворением обнаружите, что можете передать свой пользовательский массив типов JamesBondCar удаленному объекту CarProvider через перегруженный конструктор.
Исходный код.Проекты CAOCarGeneralAsm, CAOCarProviderServer и CAOCarProviderCIient размещены в подкаталоге, соответствующем главе 18.
Схема лизингового управления циклом существования САО-типов и WKO-синглетов
Вы уже видели, что WKO-типы, сконфигурированные для активизации одиночного вызова, существуют только в процессе текущего вызова метода. Поэтому WKO-типы одиночного вызова являются объектами, не меняющими своего состояния в процессе выполнения. Как только текущий вызов завершается, WKO-тип одиночного вызова становится объектом, предназначенным для участия в очередной процедуре сборки мусора.
С другой стороны, САО-типы, а также WKO-типы, сконфигурированные для активизации в виде синглета, являются по своей природе объектами, кумулятивно изменяющими параметры своего состояния в процессе выполнения вызовов клиентов. Учитывая эти две доступные опции установки конфигурации, возникает следующий вопрос: как процесс сервера "узнает" о том, что пора уничтожить такой MBR-объект? Если сборщик мусора на сервере уничтожит MBR-объекты, находящиеся в использовании удаленным клиентом, это создаст проблемы, А если серверу придется ожидать освобождения MBR-типов слишком долго, это отрицательно повлияет на работу системы, особенно если соответствующие MBR-объекты удерживают важные ресурсы (связь с базой данных, неуправляемые типы или какие-то другие ресурсы).
Читать дальше