Читать «ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание» онлайн - страница 433
Эндрю Троелсен
• Общий компоновочный блок CarGeneralAsm.dll
• Компоновочный блок клиента CarProviderClient.exe
• Компоновочный блок сервера CarProviderServer.exe
Как вы можете догадаться, программный код приложений клиента и сервера более или менее подобен программному коду соответствующих приложений предыдущего примера, особенно в том, как эти приложения используют файлы *.config, Тем не менее, давайте разберем соответствующий процесс построения каждого из указанных компоновочных блоков по очереди.
Создание общего компоновочного блока
В ходе нашего обсуждения процесса сериализации объектов в главе 17 мы создали тип JamesBondCar (в дополнение к связанным классам Radio и Car). Библиотека программного кода CarGeneralAsm.dll будет использовать эти типы, поэтому сначала выберите Projects→Add Existing Item из меню и добавьте в свой новый проект библиотеки классов соответствующие файлы *.cs (автоматически созданный файл Class1.cs можете удалить), Поскольку каждый из добавленных типов уже обозначен атрибутом [Serializable], они готовы для маршалинга по значению в отношении удаленного клиента.
Теперь нам нужен MBR-тип, который обеспечит доступ к типу JamesBondCar. Чтобы сделать ситуацию немного более интересной, ваш MBR-объект (CarProvider) будет поддерживать обобщенный список List‹› типов JamesBondCar. Тип CarProvider определит два члена, которые позволят вызывающей стороне получить заданный тип JamesBondCar, а также полный перечень List‹› соответствующих типов. Вот весь программный код для нового типа класса.
namespace CarGeneralAsm {
// Этот тип является MBR-объектом, обеспечивающим доступ
// к соответствующим MBV-типам.
public class CarProvider: MarshalByRefObject {
private List‹JamesBondCar› theJBCars = new List‹JamesBondCar›();
// Добавление в список нескольких машин.
public CarProvider() {
Console.WriteLine("Создание поставщика машин");
theJBCars.Add(new JamesBondCar("QMobile", 140, true, true"));
theJBCars.Add(new JamesBondCar("Flyer", 140, true, false));
theJBCars.Add(new JamesBondCar("Swimmer", 140, false, true));
theJBCars.Add(new JamesBondCar("BasicJBC", 140, false, false));
}
// Получение всех JamesBondCar.
public List‹JamesBondCar› GetAllAutos() { return theJBCars; }
// Получение одного JamesBondCar,
public JamesBondCar GetJBCByIndex(int i) { return (JamesBondCar)theJBCars[i]; }
}
}
Обратите внимание на то, что метод GetAllAutos() возвращает внутренний тип List‹›. Очевидный вопрос: как данный член пространства имен System. Collections.Generic представляется вызывающей стороне? Если посмотреть описание этого типа в документации .NET Framework 2.0 SDK, вы обнаружите, что list‹› сопровождается атрибутом [Serializable].
[SerializableAttribute()]
public class List‹T›: IList, ICollection, IEnumerable
Таким образом, для всего содержимого типа List‹› будет использован маршалинг по значению (если содержащиеся в нем типы также допускают сериализацию). Это очень удобная особенность удаленного взаимодействия .NET и членов библиотек базовых классов. Вдобавок к пользовательским MBV- и MBR-типам, которые вы можете создать сами, любой тип из библиотек базовых классов, сопровождающийся атрибутом [Serializable], также способен выступать в качестве MBV-типа в архитектуре удаленного взаимодействия .NET. Аналогично, любой тип, получающийся (непосредственно или косвенно) из MarshalByRefObject, может функционировать, как MBR-тип.