Отдалечени извиквания с. Net remoting



страница1/3
Дата09.06.2017
Размер499.7 Kb.
#23191
  1   2   3

Отдалечени извиквания с .NET Remoting

Автор


Виктор Живков

Необходими знания


  • Базови познания за .NET Framework

  • Базови познания за езика C#

  • Базови познания по компютърни мрежи и Интернет технологии

  • Базови познания по разпределени архитектури и системи

  • Познания за сериализацията в .NET Framework

Съдържание


  • Какво е .NET Remoting?

  • Кога се използва Remoting?

  • Remoting инфраструктурата

  • Remoting канали и форматери. Регистрация на канал

  • Активация на обекти. Активация от сървъра. Активация от клиента

  • Маршализация (Marshaling). Marshal-by-Value обекти. Marshal-by-Reference обекти

  • Живот на обектите (Lifetime). ILease

  • Remoting конфигурационни файлове

  • Практика: Създаване на Remoting сървър и клиент

  • Проблемът с общите типове

В тази тема ...


В настоящата тема ще разгледаме инфраструктурата за отдалечени извик­вания, която .NET Framework предоставя на разработчиците. Ще обясним основите на Remoting технологията и всеки един от нейните компо­ненти. Ще започнем с канали и форматери и ще продължим с отдалече­ните обекти и тяхната активация. Ще се спрем на разликата между различните типове отдалечени обекти, жизнения им цикъл и видовете маршализация. Стъпка по стъпка ще достигнем до създаването на приме­рен Remoting сървър и клиент. Ще завършим с обяснение на един гъвкав и практичен начин за конфигуриране на цялата Remoting инфраструктура.

Разпределени приложения


Поради сложния характер на днешните приложения по-голямата част от тях са разпределени. Състоят се от няколко отделни компонента, които често пъти са отдалечени един от друг, но за целта на приложението трябва да взаимодействат помежду си. Съществуват няколко утвърдени от практиката модели за разпределени приложения:

  • Клиент/сървър – двете страни комуникират помежду си чрез заявки. Клиентът изпраща заявка към сървъра, сървъра я обработва и връща резултата обратно.

  • Разпределени обекти (distributed objects) – примери за такива инфраструктури за:

    • DCOM – използва се в Microsoft Windows

    • CORBA – отворен стандарт, който за съжаление е много сложен

    • Java RMI – стандарт базиран на Java технологията

    • .NET Remoting – стандарт предлаган от .NET Framework

  • Уеб услуги (Web Services) – стандартизирана технология, при която отделни обекти на различни платформи и системи комуникират посредством стандартни SOAP съобщения.

По-нататък в настоящата тема ще разгледаме подробно само .NET Remoting технологията. Няма да правим сравнение между различните модели, такива тъй като тази тема не е обект на настоящата книга. Уеб услугите в .NET Framework са разгледани подробно в предишната глава. [TODO: Add cross-reference to Web Services chapter]

Какво е .NET Remoting?


Remoting технологията в .NET Framework предлага на разработчика проз­рачен достъп до отдалечени обекти, без излишни трудности и загуба на гъвкавост. Подходяща е за случаи, когато се налага да се достъпват обекти, които:

  • се намират в друг домейн на приложението (application domain)

  • принадлежат на друг процес

  • се намират на отдалечена машина

Независимо от местоположението на интересуващите ни обекти Remoting инфраструктурата осигурява лесен начин за използва­нето им. Комуни­кацията между обектите се извършва чрез стандар­тизиран механизъм и специалната инфра­структура, осигурени от .NET Framework.

Кога се използва Remoting?


Тъй като Remoting технологията ни позволява да осъществим достъп до и реализация на отдалечени обекти, тази технология може да бъде решение за проблеми, свързани с мрежова комуникация. Самата инфраструктура е гъвкава и разширяема. Тя дава решения на голям набор от проблеми без особено усилия от страна на програмиста. .NET Framework ни предлага и алтернативи в лицето на Web услугите и мрежовата комуникация на по-ниско ниво (виж System.Net). Повече за това, кога е удачно да използ­ваме Remoting, можете да намерите в частта "Remoting сценарии".

Microsoft Indigo


Друга зараждаща се технология с голям потенциал e Microsoft Indigo. Тя включва в себе си възможностите на ASMX (или т. нар. уеб услуги), .NET Remoting, Enterprise Services, WSE (Web Services Enchancements) и MSMQ (Microsoft Message Queue). В Indigo е доразвита концеп­цията за комуни­кация между отдалечени обекти, като се набляга на съвмести­мостта на различните среди и платформи. Архитектурата на Indigo е пример за имплементация на набиращата популярност Service Oriented Architecture (SOA). Заради развитието на тази технология в .NET Framework 2.0 ще има промени, свързани със самия Remoting. Обратната съвместимост е запазена, но Microsoft препоръчват преминаване към Indigo, след като излезе финалната му версия.

Remoting инфраструктурата


Remoting инфраструктурата се състои от:

  • канали – канали, по които се пренасят данните и съобщенията от и към отдалечените обекти

  • форматери – отговарят за форматирането, кодирането и декодира­нето на съобщенията, които се пренасят чрез каналите в някакъв формат

  • прокси обекти – предават извикванията на методи към и от отдале­чените обекти

  • механизми за активация – служат за създаване и получаване на инстанция на отдалечения обект

  • маршализация – осигурява пренос на обекти, техните свойства, полета и т.н.

Като нагледен пример за това каква е взаимовръзката межди тези компо­ненти и как работят те, нека разгледаме следната диаграма:


Как работи Remoting инфраструктурата?


При създаването на инстанция на отдалечен обект Remoting инфраструк­турата автоматично създава при клиента прокси клас, който се грижи за обмяната на съобщенията между клиентския и сървърния обект. За клиен­та съществуването му остава незабележимо, тъй като всяко извиква­не се обработва автоматично от средата. След като проксито получи кон­трола на съобщението, го предава на следващия възел в инфраструктурата – канала. Каналът работи тясно свързано с форматер, който форматира данните, обменяни между клиента и сървъра. След това съобщението се изпраща по TCP сокет до получателя, десериализира се, сървърният обект извършва извикването и връща резултата по обратния път към клиента. Всяка от описаните стъпки, с изключение на създаването на сървърно прокси, може да бъде настроена допълнително, така че да отговаря на специфични нужди.

Remoting канали


Каналите се използват за пренос на съобщения от и към отдалечени обекти. Когато клиентът извика метод на отдалечен обект, параметрите, както и всички детайли, свързани с даденото извикване, се транспортират през канал до обекта. Резултатът от извикването се връща обратно при клиента по същия начин. Всеки клиент може да избере към точно кой канал от регистрираните на сървъра да се прикачи, за да комуникира с отдалечения обект. Това дава изключителна гъвкавост на разработчика в избора на канал, така че той да отговаря на специфичните нужди.

За канали могат да се използват стандартните вградени канали, техни модификации и дори напълно нови, създадени от разработчика канали, които да комуникират по избран протокол. В .NET Framework са реализирани три типа канали:



  • TCP канал – използва се чист TCP сокет. Данните се сериализират стандартно посредством бинарен форматер и се транспортират посредством TCP протокол. При нужда форматерът може да бъде преконфигуриран като SOAP.

  • HTTP канал – използва се SOAP протокол. Съобщенията се сериали­зират чрез SOAP форматер в XML с включени SOAP хедъри. Може да се конфигурира да използва бинарен форматер вместо стандартния SOAP. Комуникацията между обектите се извършва посредством HTTP протокол и се използва модела на заявка/отговор (request / response) подобно на този в уеб приложенията.

  • Други канали – дефинирани от разработчика. Те трябва да имплементират интерфейсите: IChannel, IChannelReceiver и/или IChannelSender. Както се вижда от имената на последните два интерфейса, първият служи за канал, който може само да приема съобщения, а вторият – за такъв, който може само да изпраща. В повечето случаи каналите имплементират и двата интерфейса, за да могат да комуникират в двете посоки.

Каналите се използват както от сървърните приложения, така и от клиентските. Каналът трябва да бъде регистриран и от двете страни преди началото на комуникация между тях. За преноса на потока от съобщения се използват TCP портове, през които се подават форматира­ните данни на извикването.

Регистрация на канал


Регистрацията на канал е задължителна стъпка в подготвянето на комуни­кацията с отдалечени обекти. Този процес има следните изисква­ния и ограничения:

  • Най-малко един канал трябва да бъде регистриран преди да бъде направено обръщение към отдалечен обект. Каналите задължително се регистрират преди регистрацията на самите обекти.

  • Всеки канал се регистрира за даден application domain. В един процес е възможно да има няколко application domains. В момента, в който дадения процес приключи работата си, всички канали, които са регистрирани в него, се унищожават автоматично.

  • В рамките на даден application domain всеки канал трябва да има уникално име. Разгледайте примера за да видите начина, по който можете да зададете уникално име на канал:

    IDictionary properties = new Hashtable();

    properties["name"] = "http1";

    properties["port"] = "9001";

    ChannelServices.RegisterChannel(

    new HttpChannel(properties, null, null));


  • Не е възможно два или повече канала да бъдат регистрирани върху един и същ порт, по едно и също време, на една и съща машина. От друга страна е възможно един канал да бъде регистриран на повече от един порт.

  • В случай, че не сте сигурни кой порт да използвате за канала, можете да накарате Remoting инфраструктурата да ви предостави автоматично свободен порт като регистрирате канал за порт 0.

  • Клиентът може да комуникира с отдалечения обект, използвайки който и да е регистриран канал. Remoting инфраструктурата автома­тично осигурява свързването на отдалечения обект с правилния канал. Клиентът е задължен да регистрира канал преди да се опита да комуни­кира с отдалечения обект.

Пример за регистрация на канал


Регистрацията на канал може да се извърши по два начина:

  • Чрез класа System.Runtime.Remoting.Channels.ChannelServices:

    using System.Runtime.Remoting.Channels;

    using System.Runtime.Remoting.Channels.Tcp;


    ...
    TcpChannel channel = new TcpChannel(1234);

    ChannelServices.RegisterChannel(channel);



  • Чрез класа System.Runtime.Remoting.RemotingConfiguration и кон­фигурационен файл:

RemotingConfiguration.Configure("MyClient.exe.config");

Конфигурационните файлове, като средство за настройка на Remoting инфраструктурата, ще разгледаме малко по-късно в настоящата тема.

Форматери (formatters)


Ролята на форматерите в Remoting инфраструктурата е да сериализират съобщенията между двете страни в определен формат. На разположение на разработчиците са два вградени форматера плюс възможността да създадат свой собствен форматер, който да отговаря на специфичните им нужди.

  • SOAP форматер – сериализира поток в SOAP съвместим XML формат. Използването SOAP протокола позволява съвместимост с множество платформи и клиенти. Поради употребата на XML, обемът на предаваните данни е голям и това води до намаляване на произ­водителността.

  • Бинарен форматер – сериализира поток в двоичен формат, който е с много по-малък обем от SOAP варианта. Поради вида на сериали­зирания поток не е толкова съвместим с различни системи, колкото е SOAP потока.

  • Друг форматер – форматер, реализиран от разработчика за неговите специфични цели и нужди.

Форматери по подразбиране


Всеки от предоставените от .NET Framework канали има форматер по подразбиране. На разработчика се предоставя готово решение със сис­темата от класове за осъществяване на отдалечените извиквания и той може да се съсредоточи върху реализацията на програмната логика. Двата канала, които са вградени в Remoting инфраструктурата, имат форматери по подразбиране:

  • TCP каналът има бинарен форматер.

  • HTTP каналът има SOAP форматер.

Тези форматери могат да се преконфигурират. Ето един пример как може­те да реализирате в своето приложение TCP канал със SOAP форматер:

SoapServerFormatterSinkProvider provider =

new SoapServerFormatterSinkProvider();

IDictionary properties = new Hashtable();

properties["port"] = 12345;

TcpChannel channel = new TcpChannel(properties, null, provider);


Друг начин за промяна на стандартния форматер на вградените канали е чрез редактиране на конфигурационния файл machine.config. Този начин е разгледан подробно в частта описваща конфигурирането на Remoting инфраструктурата в края на темата.

Активация на обекти


Процесът на създаване на инстанция на отдалечен обект се нарича активация. Remoting инфраструктурата предоставя два начина за извър­шването й:

  • Сървърна активация (server-side activation) – използва се в слу­чаи, когато няма необходимост отдалечените обекти да поддър­жат своето състояние между две извиквания (SingleCall) или когато множество клиенти извикват методи на една и съща инстанция на обекта и трябва да се поддържа състоянието на обекта между извик­ва­нията (Singleton).

  • Клиентска активация (client-side activation) – инстанцията на обекта е създадена само за клиента, който я е извикал. Само той я управлява и определя времето й за живот. Жизненият цикъл на този вид отдалечени обекти се управлява чрез lease-based система на инфраструктурата.

Преди да е възможна активацията на обекти, е задължително да бъдат регистриран всеки от типовете на отдалечените обекти, които смятаме да използваме.

SingleCall режим на активация


SingleCall режимът е приложим при обекти със сървърна активация. Характерно за този режим е, че при всяко извикване на метод от страна на клиента се създава нова инстанция на обекта на сървъра, която обслужва извикването и веднага след това завършва своя жизнен цикъл.

Такива обекти са удобни в случай, че имаме метод, който трябва да свърши определена работа, за извършването, на която нямаме нужда от предишното състояние (state) на обекта. Обекти с такъв режим на работа улесняват балансирането на натоварването (load-balancing) на сървъра, тъй като не се налага да се поддържа състоянието им между отделните извиквания.


Singleton режим на активация


Singleton режимът е приложим при обекти със сървърна активация. Харак­терно при него е, че съществува единствена инстанция на отдале­чения обект и всички клиенти работят с нея. Нейните данни, методи и свойства са споделени между всички клиенти. Самият обект поддържа своето състояние (state).

Този режим на активация е подходящ, когато данните на обекта, трябва да бъдат споделени или когато инстанцирането и поддържането на състоянието на обекта създава допълнително натовар­ване. При използва­нето на Singleton обекти е възможно няколко клиента едновременно да работят с тях, поради което трябва да се осигури синхронизация при достъпа до общи данни. [TODO: cross reference to multitreading chapter]


Клиентска активация


При активация от страна на клиента, след заявката на сървъра се създа­ват инстанции на отдалечения обект. Създаденият обект обслужва един­ствено своя клиент. Обектът може да поддържа своето състояние между извикванията. Жизненият цикъл на всяка инстанция се контролира чрез lease-based системата на Remoting инфраструктурата (ще я разгледаме подробно в частта "Живот на обектите" [TODO: линк]).

При всяка заявка за създаване на нов обект се връща нова инстанция. С такъв тип обекти трябва да се работи внимателно, тъй като е възможно за един клиент на сървъра да има повече от една инстанция. При проекти­ране на такива класове трябва да се отдели време за оптимизиране на методите на класа и да се направи преглед на това колко и какви данни съдържа той, за да се облекчи натоварването на сървъра.


Регистрация на отдалечен обект


Регистрацията на отдалечените обекти следва веднага след регистрацията на Remoting канали. За да извършим това ни е необходимо да предоста­вим на Remoting инфраструктурата следните данни:

  • името на асемблито, в което се намира класа, който искаме да регистрираме

  • типа на отдалечения обект

  • URI (Unique Resource Identifier) на обекта, чрез който клиентът да може да се обръща към него

  • в случай, че обектът е със сървърна активация – неговия режим на активация (SingleCall или Singleton)

Отново имаме избор между два начина за регистриране – чрез код или чрез конфигурационен файл.

Чрез регистрацията предоставяме данни, които описват уникално на Remoting инфраструктурата всеки тип, който искаме да използваме като отдалечен. Този процес на регистрация е задължителен както за сървъра така и за клиента. Важен момент при регистрирането на типовете е регистрациите при сървъра и клиента да си съответстват. Друго изискване е, типовете, които се използват за отдалечени обекти на сървъра и тези на клиента да имат една и съща версия или поне техните интерфейси да съвпадат. Този конкретен проблем е разгледан в частта "Проблемът с общите типове". [TODO: link]


Регистрация на сървъра (Server-Side Registration)


Чрез програмен код имаме три възможности за регистриране на типа на обект, който искаме да е достъпен отдалечено. Използват се методите на класа RemotingConfiguration:

  • RegisterWellKnownServiceType() с параметър, указващ че обектът трябва да се използва в SingleCall режим – регистрира тип на отдалечен обект в режим SingleCall. Пример:

    RemotingConfiguration.RegisterWellKnownServiceType(

    typeof(CommonTypes.Library), // type of the remote object

    "Library", // assembly name

    WellKnownObjectMode.SingleCall); // activation mode



  • RegisterWellKnownServiceType() с параметър указващ че обектът трябва да се използва в Singleton режим – регистрира тип на отда­лечен обект в режим Singleton. Пример:

    RemotingConfiguration.RegisterWellKnownServiceType(

    typeof(CommonTypes.Library), // type of the remote object

    "Library", // assembly name

    WellKnownObjectMode.Singleton); // activation mode



  • RegisterActivatedServiceType() – регистрира отдалечен обект с клиентска активация. Пример:

RemotingConfiguration.RegisterActivatedServiceType(

typeof(CommonTypes.Library)); //type of the remote object


Регистрация на клиента (Client-Side Registration)


Чрез програмен код имаме два начина за регистриране на типа на обект, който искаме да ползваме отдалечено от някой Remoting сървър. Използ­ват се методите на класа RemotingConfiguration:

  • RegisterWellKnownClientType() – регистрира тип със сървърна активация. Не се указва дали обектът използва режим SingleCall или Singleton, защото това зависи от сървъра. Клиентът не може и не трябва да знае такива подробности в имплементацията и логиката на сървъра. Форматът на URI адреса, който се подава на метода, е следният:

<протокол>://<име на сървъра или IP адрес>:<порт>/<път до асембли с типа>/<тип>

Ето един пример за регистрация на отдалечен тип с активация от страна на сървъра:

RemotingConfiguration.RegisterWellKnownClientType(

typeof(CommonTypes.Library), // type of the remote object

"http://remoting_server:1234/remoting/Library"); // object URI


  • RegisterActivatedClientType() – регистрира тип с клиентска активация. Форматът на URI идентификаторът е следният:

<протокол>://<име на сървъра или IP адрес>:<порт>

Ето пример за регистрация на отдалечен обект, който ползва клиент­ска активация:

RemotingConfiguration.RegisterActivatedClientType(

typeof(CommonTypes.Library), // type of the remote object

"http://remoting_server:1234"); // URL of the server

Създаване на инстанция на отдалечен обект


За да получим инстанция на даден отдалечен обект трябва преди това да сме регистрирали неговия тип в Remoting инфраструктурата. След това можем да създадем обект от този тип по някой от следните начини:

  • Чрез статичния метод GetObject() на класа Activator – използва се за отдалечени обекти със сървърна активация. Създава прокси обект при клиента, чрез който се осъществяват всички извиквания. Комуникация със сървъра се извършва единствено при извикването на методите и връщането на резултата, а не при създаването на прокси обекта.

    Library library = Activator.GetObject(

    typeof(Library), // type of the remote object

    "http://remoting_server:1234/remoting/Library" // object URI

    ) as Library;



  • Чрез оператора new – може да се използва за създаване на обекти със сървърна и с клиентска активация. Осигурява и механизъм за предаване на параметри при инстанциране. В C# операторът new се използва както при създаването на локални обекти, така и при създаването на отдалечени обекти. За да създадем отдалечен обект с new, преди това съответният клас трябва да е бил регистриран в Remoting инфраструктурата. В противен случай се създава локален обект. Ето примерен код, който създава отдалечен обект с оператора new:

// This class is located and registered on the server

class Library

{

private string mName;


// Default constructor

public Library()

{

mName = "Library";



}
// Parametrized constructor

public Library(string aName)

{

mName = aName;



}

}
...


// This code runs on the client-side
// Register the Library class as remote type

RemotingConfiguration.RegisterWellKnownClientType(

typeof(CommonTypes.Library), "http://remoting_server:1234/remoting/Library");
// Get object from the server using the default constructor

Library library1 = new Library();


//Get object from the server using the parameterized constructor

Library library2 = new Library("My library");



Кодът за инстанциране на отдалечен обект с ключовата дума new не се отличава от създаването на обикновени обекти. Изобщо работата с отда­лечени обекти изглежда в повечето случаи, като че ли се изпълнява вър­ху обикновени инстанции. След регистрация Remoting инфраструкту­рата се грижи всяко извикване да се прехвърля от локалния прокси клас към отдалечения обект прозрачно, без допълнителна намеса на програ­миста.

Маршализация (Marshaling)


Маршализацията (marshaling) е процес на пренос на обекти и данни между Remoting клиента и сървъра. Този процес се извършва при всяко:

  • подаване на параметри на метод

  • връщане на резултат от метод

  • достъп до поле или свойство на обект или тип

Според начина, по който се пренасят има три типа обекти:

  • Marshal-By-Value обекти – пренасят се по стойност посредством сериализация. [TODO: add reference to Serialization chapter]

  • Marshal-By-Reference обекти – пренасят се по референция. По специалното при тях е, че се използва отдалечена референция.

  • Non-Marshaled обекти – не се пренасят. Причина за това може да бъде, че обектите стават невалидни извън своя application domain или контекст, поради съображения за сигурност и др.

Marshal-By-Value обекти


Marshal-By-Value са всички обекти, които са маркирани с атрибута [Serializable] и/или имплементират интерфейса ISerializable. Тези обекти се предават по стойност, т.е. тяхно копие се пренася до отдале­чената машина. Копират се всички сериализируеми полета и свойства в обекта. Като поведение те са подобни на стойностните типове в .NET Framework. При промяна на данните се променя само локалното копие на обекта. Целият обект се пренася до отдалечената машина наведнъж (само с едно извикваме) и това осигурява добро бързодействие в случай, че обемът на данните не е голям.

Ето един пример, в който са дефинирани два класа, които се марша­лизират по стойност:



[Serializable]

public class Book

{

private string mAuthor;



private string mTitle;
// Default constructor

public Book()

{

}

...



}
public class Author : ISerializable

{

private string mName;



private string[] mBooks;
// Default constructor

public Author()

{

}
// Constructor for serialization only



private Author(SerializationInfo info,

StreamingContext context)

{

// Deserialize data to class fields



}
// ISerializable.GetObjectData method

public void GetObjectData(SerializationInfo info,

StreamingContext context)

{

// Serialize class fields



}

...


}

Marshal-By-Reference обекти


Marshal-By-Reference са всички обекти, които са наследници на класа MarshalByRefObj без значение дали типът е сериализируем. Пренасят се до отдалечената машина посредством отдалечена референция, от която се създава динамично прокси клас. Всяко извикване или операция върху обекта се извършва върху прокси класа, който от своя страна прехвърля нужните данни към отдалечената инстанция, където се изпълнява реално извикването. Този процес се повтаря за всяко четене или писане в поле или извикване на метод, което значително понижава производителността.

[Serializable]

public class Book : MarshalByRefObject

{

private string mAuthor;



private string mTitle;
// Default constructor

public Book()

{

}

...



}

Живот на обектите (Lifetime)


В .NET Framework жизненият цикъл на обектите се управлява от системата за събиране на боклука (Garbage Collector). Тя следи дали даден обект се достъпва от клиентите в даден application domain (AppDomain). Когато обектът спре да бъде използван той подлежи на събиране от системата за боклук. Ако обектите и клиентите им са в един и същ application domain, системата работи без проблеми. Дори в случай, че клиентът и обектите са в отделни домейни, но в рамките на един и същ процес, отново няма никакви проблеми, тъй като те всичките споделят общ управляван хийп (managed heap).

Случаят, в който клиентите и обектите са в различен процес и/или машина, е по-особен. Ако системата за събиране на боклука работи по същия начин, то тя веднага след инициали­зирането ще открие, че към обекта няма референции и веднага ще го обяви за боклук. За да реши този проблем Remoting инфраструк­турата предлага "система за отпускане на „живот назаем” за обектите – lease-based lifetime management.


Живот назаем


При създаването си всеки отдалечен обект на сървъра се асоциира с Lease обект, който има задачата да контролира жизнения му цикъл. Той определя времето, за което отдалечения обект е активен и не подлежи на събиране от системата за системата за почистване на паметта.

Специален обект наречен Lease Manager следи сървърните обекти и техните асоциирани Lease обекти. Всеки Lease обект има начално време, което да дава назаем (initial lease time). Lease времето започва да тече след като първата референция към сървърния обект се маршализира през границата на домейна. Докато то е по-голямо от нула, се счита че обектът, асоцииран с него, все още е активен и CLR смята, че сървърния обект все още се използва от клиента. Lease мениджърът пази референ­ция към обекта, за да предотврати неговото събиране от “системата за почистване на паметта”.

Когато Lease времето свърши, CLR решава че обектът не е вече в употреба и че той ресурсите му подлежат на освобождаване. При свър­шване на времето е възможно да има клиенти, които все още да се нуж­даят от обекта. В този момент се отправя заявка към всеки от тях дали все още се нуждаят от обекта.

Спонсори на обектите


Всеки клиент, който иска да бъде "попитан" дали иска да се удължи живота на обекта, който той ползва, трябва да предоставя специален обект-спонсор. Спонсорът от своя страна решава дали да удължи живота на сървърния обект или не. Ако реши да удължи времето за живот, то Lease мениджърът изпълнява желанието му. В противен случай системата за събиране на боклук може да прибере обекта. Следващата схема обяс­нява нагледно процеса:

Функцията на всеки един от показаните обекти е обяснена по-долу. Тази схема за определяне на продължителността на живота е приложима само за Marshal-By-Reference обекти с клиентска активация и Singleton обекти със сървърна активация. Двата случая има специфични особености, които са разгледани по-долу. Сега ще насочим вниманието си към Lease обекта, спонсора и Lease мениджъра.

Lease обектът имплементира интерфейса ILease, който предоставя функции за определяне живота на асоциираните с него обекти. Конкретна имплементация на този интерфейс е класът Lease в System.Runtime.Remoting.Lifetime.

Интерфейсът ILease


Интерфейсът ILease се намира в пространството от имена System. Runtime.Remoting.Lifetime. Както показва схемата, обекти от този тип дават назаем живот на асоциирания си отдалечен сървърен обект. Remoting инфраструктурата автоматично задава стойнос­ти по подраз­биране за свойствата на всяка инстанция от този тип, но е възможно и програмистът да зададе свои собствени. Свойствата, които интерфейсът предоставя са:

  • InitialLeaseTime – задава времето на живот на обекта. В случай че искаме да зададем друга стойност от тази по подразбиране, трябва да го направим задължително преди да сме активирали обекта. По подразбиране времето за живот е 5 минути.

  • RenewOnCallTime – задава времето, с което е възможно да се увеличи живота на обекта при всяко извикване. По подразбиране стойността му е 2 минути. Важно е да се отбележи, че не е възможно да се получи натрупване на време при интензивно ползване на обекта, тъй като формулата, по която се изчислява новото време за живот, е следната:

currentLeaseTime = MAX(InitialLeaseTime - expiredTime, RenewOnCallTime)

С други думи RenewOnCallTime стойността ще има ефект ако е по-голяма от оставащото време за живот, като в такъв случай тя определя оставащо време за живот. Отново сме задължени да зададем тази стойност преди активацията на обекта.

  • SponsorshipTimeout – задава времето, в което всеки спонсор трябва да отговори на изпратената му заявка за отпускане на още време. В случай, че не бъде получен отговор, се счита, че спонсорът е отказал. Ако нито един от спонсорите не даде допълнително време то обектът подлежи на унищожение. По подразбиране стойността е 2 минути.

  • CurentLeaseTime – връща колко време още остава от живота на обекта.

  • CurrentState – връща състоянието на живота на обекта, като стойност от изброения тип LeaseState. Стойностите, които връща са: Initial в процеса на активация; Active, когато оставащото времето за живот е по-голямо от 0; Renewing в процеса на добавяне на време при извикване; Expired в случай че времето за живот е изтекло; Null – при проблем с изчисляването на състоянието. Ето дефини­цията на типа LeaseState:

[Serializable]

public enum LeaseState

{

Null = 0,



Initial = 1, // while initializing

Active = 2, // lease time greater than 0

Renewing = 3, // while renewing

Expired = 4 // lease time equal to 0

}

Използване на ILease


В случай, че подразбиращите се стойности не са удобни, можем да променим глобално за цялото приложение стойностите чрез свойствата LeaseTime, RenewOnCallTime и SponsorshipTimeout на класа LifetimeServices (в пространството от имена System.Runtime.Remoting. Lifetime). Тъй като това са глобални настройки за поведението на отдалечените обекти, те трябва да бъдат направени преди регистрирането на отдалечените типове, които ще използваме. Например:

static void Main()

{

LifetimeServices.LeaseTime = TimeSpan.FromMinutes(10);



LifetimeServices.RenewOnCallTime = TimeSpan.FromMinutes(5);

LifetimeServices.SponsorshipTimeout = TimeSpan.FromMinutes(1);


// Register remotable types or load config file

}


Можем да променим стойностите на Lease обекта, асоцииран с конкретен отдалечен обект по следния начин:

// Type definition

public class ClientActivatedType : MarshalByRefObject

{

}
...


// Create and activate the first instance

ClientActivatedType caLongLiving = new ClientActivatedType();


// Get the Lease object associated with it

ILease longLiving = (ILease) RemotingServices.GetLifetimeService(caLongLiving);


// Adjust the lifetime parameters

longLiving.RenewOnCallTime = TimeSpan.FromMinutes(10);

longLiving.SponsorshipTimeout = TimeSpan.FromMinutes(1);
// Create and activate the second instance

ClientActivatedType caShortLiving = new ClientActivatedType();


// Get the Lease object associated with it

ILease shortLiving = (ILease) RemotingServices.GetLifetimeService(caShortLiving);


// Adjust the lifetime parameters

shortLiving.RenewOnCallTime = TimeSpan.FromMinutes(1);

shortLiving.SponsorshipTimeout = TimeSpan.FromSeconds(15);


Същите настройки могат да бъдат направени и посредством конфигура­ционен файл. Структурата и съдържанието на конфигурационния файл ще бъде разгледан в частта "Remoting конфигурационни файлове".

Интерфейсът ISponsor


Интерфейсът ISponsor се намира в пространството от имена System. Runtime.Remoting.Lifetime. Както споменахме по-рано спонсорът е обект, който има властта да удължава времето на живот на отдалечени обекти. За да може да изпълнява тази роля обектът трябва да имплемен­тира интерфейса ISponsor. Единственият метод на този интерфейс е Renewal(ILease lease), който е дефиниран по следния начин:

public interface ISponsor

{

TimeSpan Renewal(ILease lease);



}

Lease мениджърът извиква този метод, когато животът на даден обект е изтекъл, за да поиска допълнително време.

За да добавим спонсор към даден отдалечен обект можем да използваме метода на ILease обекта Register(). (За да получим обект от такъв тип трябва да извикаме метода GetLifetimeService() на желания отдалечен обект, на който ще добавяме спонсор.) Аналогично можем да премахнем даден спонсор от отдалечен обект чрез метода Unregister() на ILease.



// Activation of the object

Library library = new Library();


// Getting lease object associated with current object

ILease lease = RemotingServices.GetLifetimeService(library)

as ILease;
// Creating new sponsor

MySponsor sponsor = new MySponsor();


// Attaching sponsor to our lease object

lease.Register(sponsor);


// Detaching sponsor from our lease object

lease.Unregister(sponsor);



Премахването на спонсора, посредством метода Unregister(), от спи­съка със спонсори на отдалечения обект не е задължително, но на прак­тика, ако не се използва, води до голяма загуба на производи­телност, тъй като Remoting системата отправя заявки и чака отговор от всеки реги­стриран спонсор. Така че препоръчително е след като даден спонсор стане нену­жен, да бъде изваден от списъка на валидните спонсори.

Важна особеност на класовете, които играят ролята на спонсори е, че те реално се извикват през границите на домейна на приложението. Поради това спонсорът трябва да бъде отдалечен обект, който се маршализира по стойност или по референция.


Спонсор, маршализиран по стойност


При спонсори, които са маркирани единствено като сериализируеми (с атрибута [Serializable]), при регистриране на спонсор той се маршали­зира по стойност до сървърната страна. От там нататък сървърът използва своето копие на спонсора. Това осигурява по-добро бързодействие тъй като спестява маршализирането на спонсора за всяко извикване. Този начин ни дава възможност да контролираме живота на обектите от гледна точка на натоварването на сървъра (което не винаги е показателно за това, дали обектът все още е нужен на клиента!). За съжаление при решаването дали да удължи живота на даден обект спонсорът може да използва само информацията, която има на сървъра, тъй като е отделен от клиентската част.

Спонсор, маршализиран по референция


В случай, че спонсорът наследява MarshalByRefObject, той се намира при клиента. Тъй като има достъп до клиентската част, той може да базира своите решения на информацията, която получава от клиента, като следи определени негови събития или свойства.

В този случай възниква следният въпрос: ако Lease обектът пази "жив" отдалечения сървърен обект, и ако спонсорът пази Lease обекта "жив", какво пази спонсора "жив"? Отговорът е, че при клиента трябва да се държи референция към спонсора и обикновено това се реализира чрез член-променлива на някой подходящ клас. По този начин клиентът има възможност да дерегистрира своите спонсори когато завършва изпълне­нието си. Това може да се осъществи и в метода Dispose() ако класът имплементира интерфейса IDisposable. Както вече споменахме дереги­стрирането на спонсора подобрява значително производителността, тъй като Lease мениджърът не губи време да достъпва невалиден спонсор.

Друга характерна особеност на този тип спонсори е, че те са callback обекти от гледна точка на сървъра. Поради това и поради изисквания към сигурността в .NET за да работят този вид спонсори трябва да укажем при конфигурирането на каналите следните свойства:


  • Клиентът трябва да регистрира порт за всеки канал. Това е нужно за да може Lease мениджърът да може да извиква спонсора. По принцип няма значение точно кой порт ще бъде подаден. Добра практика е да се подава порт 0, тъй като в този случай Remoting системата сама избира някой порт. Каналът, номерът на порта и местонахождението на спонсора се изчисляват когато се маршали­зира референцията на спонсора до сървъра.

Живот на Singleton отдалечени обекти


Семантиката на Singleton обектите изисква те да имат неограничен живот. Посредством стандартните процедури за определяне на про­дъл­жи­тел­­ността на живота в Remoting системата, това е невъзможно или най-малкото неудобно и неефективно. За да се реши този проблем при проектирането на Singleton обекта трябва да се предефинира метода InitializeLifetileService() на базовия клас MarshalByRefObject по следния начин:

public class MySingleton : MarshalByRefObject

{

public override object InitializeLifetimeService()



{

// Returning null as Lease object

// indicates that lease never expires

return null;

}

}


Връщайки null като резултат от метода ние указваме, че искаме този обект да има безкраен живот. По този начин също решаваме проблема със спонсорите и Lease свойствата определящи продължителността на живота на обекта.

Remoting конфигурационни файлове


В настоящата секция ще разгледаме конфигурационните файлове на Remoting инфраструктурата и ще дадем описание на таговете, които се използват в тях. Тъй като сървърът и клиентът имат свои специфични елементи ще ги разгледаме последователно.

Remoting конфигурационните файлове представляват XML файлове със специална структура. Работата с тях е лесна и най-важното – те предос­тавят гъвкав начин за конфигуриране на приложения без да се налага прекомпилиране (за разлика от варианта, в който настройките са зада­дени в програмния код). В практиката е силно препоръчително да конфи­гурацията да се държи в XML а не в програмния код.

За да накараме Remoting системата да използва този файл трябва да извикаме статичния метод RemotingConfiguration.Configure() с един­ствен параметър – пътят и името на конфигурационния файл:

RemotingConfiguration.Configure("remoting.config");

Пътят до файла, името и разширението му нямат значение, освен в случай на хостинг на асемблитата със споделените класове в IIS. Remoting кон­фигурационните файлове са допълни­телни и са отделни от конфигураци­онните файлове на приложението.

След като сме извикали този метод можем да пристъпим към активиране и използване на отдалечените обекти без никакви по-нататъшни грижи за канали и форматери.


Структура и елементи на конфигурационния файл


В тази част от главата ще разгледаме подробно повечето от елементите, които могат да се съдържат в конфигурационния файл на приложение, използващо Remoting. Освен наличието на предефинираните XML тагове, в определени случаи е важно и тяхното разположение спрямо останалите тагове в конфигурацията. Ще започнем разглеждането от корена на XML документа – това е тагът .


Този таг е коренът на всички елементи във файла. Трябва да се среща точно веднъж.


Намира се задължително като под-елемент на . В този таг трябва да се намират всички елементи свързани с конфигурирането на Remoting инфраструктурата. Може да се среща само веднъж.


Представлява задължително под-елемент на . Съдържа всички специфични за приложението данни. Може да се среща само веднъж.

Има незадължителен атрибут name, който указва името на приложението:



...




Намира се винаги под елемента . Служи за конфигуриране на времето на живот на обектите. Важи за всички обекти на това прило­жение. Тези настройки се отнасят за обектите с клиентска активация и за Singleton обектите. Те имат ефект само в конфигурационния файл на сървъра, т.е. ако в конфигурационния файл на клиента има такъв таг, той бива игнориран. Конфигурирането на времената, свързани с жизнения цикъл, става чрез атрибутите на тага:

  • leaseTime – времето "на заем" на всеки обект, свързан с даденото приложение. По подразбиране има стойност 5 минути.

  • sponsorshipTimeout – времето, което Lease мениджърът изчаква отговора на спонсора след като го уведоми че даден Lease е изтекъл. Ако спонсорът не отговори в този период обектът подлежи на освобождаване от системата за събиране на боклука. По подразби­ране времето е 2 минути.

  • renewOnCallTime – времето, с което се увеличава продължителност­та на живота на обект, при всяко негово извикване. За повече подробности относно начина на изчисляване на допълнителното време вижте частта "Интерфейсът ILease". Подразбиращата се стой­ност е 2 минути.

  • leaseManagerPollTime – времето, което Lease мениджърът изчаква, след като е проверил системата за Lease обекти с изтекло време, преди да започне нова проверка. По подразбиране периодът е 10 секунди.

Единиците за измерване на времето се записва веднага след стойността за всеки атрибут. Символите за мерните единици не са зависими от главни и малки букви. Валидните стойности са:

  • D – дни

  • H - часове

  • M - минути

  • S - секунди

  • MS – милисекунди

Ето как изглежда секцията в един примерен конфигурационен файл:



leaseTime="3m"

sponsorshipTimeout="30s"

renewOnCallTime="1m"

leaseManagerPollTime="750ms" />

...




Представлява под-елемент на . Не е задължителен елемент и може да се среща повече от веднъж в рамките на един конфигура­ционен файл. Използва се като контейнер, в който са изброени и описани всички отдалечени типове, които сървърът предоставя за използване. Поради това има смисъл само в приложения, които играят ролята на сървър. Тъй като дадено приложение може да бъде едновременно както клиент така и сървър, този таг е съвместим с тага . В този таг се съдържат таговете и , които са разгледани по-долу.


Представлява под-елемент на . Не е задължителен елемент и може да се среща повече от веднъж. Служи за контейнер, в който са изброени и описани типовете на отдалечените обекти, които приложе­нието може да използва. Може да съдържа таговете и . Има следните атрибути:

  • url – определя URL адреса, който се използва за активиране на клиентски обекти. Ако приложението използва такъв тип обекти, този атрибут е задължителен.

  • displayName – използва се само от приложението Admin Tool, за да може потребителите му да отличават визуално различните такива тагове, когато са използвани повече от един. Този атрибут е неза­дължителен.


Може да се използва като под-елемент само на таговете и . И в двата случая този таг е незадължителен и може да се среща повече от веднъж. Тъй като между начините, по които се използва в двата случая, има различия, ще ги разгледаме поотделно.

В конфигурационния файл на сървъра този таг се намира под тага . Той описва отдалечените типове със сървърна активация, предлагани от сървъра. Чрез него се описват SingleCall и Singleton обектите. Има следните задължителни атрибути:



  • mode – типа на активирания на сървъра обект. Валидните стойности са SingleCall и Singleton.

  • type – означава пълния тип на обекта. Има следния формат:

<пълен тип на обекта>, <асембли, в което се намира типът>, Version=<версия>, PublicKeyToken=<публичен ключ на силно име­нуваното асембли>, Culture=<култура>

Version, PublicKeyToken и Culture се използват само при силно имену­вани асемблита.

  • objectUri – URI адрес на отдалечения обект, към който клиентът се обръща. Трябва да бъде уникално за всеки тип в приложението. Зависим е от малки и главни букви. Особеност при този атрибут е, че когато обектът се достъпва през IIS (Internet Information Services), e нужно той да завърша с разширение .soap. Повече за използването на Remoting чрез IIS можете да намерите в частта "Remoting сценарии".

В конфигурационния файл на клиента описва типовете със сървърна активация, които клиентът използва. Атрибутите, които се използват в този случай са:

  • type – означава пълния тип на обекта. Има същия формат като случая със сървърната конфигурация.

  • url – адресът, който трябва да се използва, за да може клиентът да се свърже със сървъра и неговите типове. Съдържанието на този адрес зависи и от това дали в тага е въведено име на приложението.

За да представим нагледно конфигурационните възможности нека разгле­даме следващите два примера. Конфигурация на Remoting сървър:

server.config



type="CommonTypes.Query, CommonTypes"

objectUri="Query" />

type="CommonTypes.Library, CommonTypes"

objectUri="Library" />



Конфигурация на Remoting клиент:

client.config



url="http://remoting_server:1234/Query" />



url="http://remoting_server:1234/Library" />





Представлява под-елемент на таговете и съответно в сървърния и в клиентския конфигурационен файл. Описва типовете с клиентска активация, които приложението предлага или използва. Не е задължителен елемент и може да се среща многократно в тези две секции. Има един задължителен атрибут type, който се използва и в двата случая за описване на пълния тип на отдалечения обект. Ето пример за конфи­гуриране на клиентска активация от страна на сървъра:

server.config







Ето как изглежда съответната конфигурация от страна на клиента:

client.config







Представлява под-елемент на тага или .

Когато се намира под , с този таг се дефи­нират нови канали, създадени от разработчика.

В случая, когато той се намира под , конфигурираме вече съществуващи или вече описани канали в секцията под .

Стандартните канали като TCP и HTTP каналите са описани във файла machine.config. Ако искаме да променим тяхното поведение глобално, за цялата машина, можем да редактираме този файл, но това не е препо­ръчителна практика, тъй като може да отворим дупка в сигурността на машината. Друг проблем е, че ако нашето приложение изисква такива промени, то трудно би могло да се разпространява, тъй като трябва да се налага административна намеса в процеса на инсталиране, а също така е възможно да се получат несъвместимости с други приложения, които разчитат на стандартните настройки. Затова е по-добре да се използват локално дефинирани канали.



Може да се използва като под-елемент на без значение къде се намира родителската секция. С този таг се конфигурират параметрите на всеки един от каналите, които приложението използва. Може да се съдържа в една секция повече от веднъж. Поради това, че в зависимост от разположението на родителския таг, тази секция има различно значение, ще разгледаме двата случая по отделно.

Когато се намира под можем да разглеждаме тази секция като шаблон на канала. Тагът описва канала и някои от неговите свойства като например:



  • id – уникално име на канала, което се използва за рефериране на канала в други части на конфигурационния файл. Не трябва да се допускат канали с еднакви id атрибути, тъй като парсерът не преду­преждава за грешка, а използва навсякъде последно декларирания канал с това id. Този атрибут е задължителен.

  • type – пълно име на класа, който имплементира канала. Описва се в същия формат, който се използва при атрибута type на тага . Задължителен атрибут.

  • name – име на канала. Използва се, когато се налага да се регист­рира един и същ канал, който да "слуша" на повече от един порт.

  • priority – приоритет на канала спрямо другите регистрирани от приложението канали. При заявка към сървъра Remoting системата използва тази информация, за да намери подходящ канал за връзка. По-голям приоритет имат каналите с по-голяма стойност на този атрибут. Стандартните канали, които са част от .NET Framework, имат приоритет равен на 1. Отрицателните числа са също валидни стойности.

  • displayName – използва се само от приложението Admin Tool, за да може потребителите му да отличават визуално различните такива тагове, когато са използвани повече от един. Този атрибут е неза­дължителен.

  • Специфични за канала свойства. Тъй като свойствата на каналите не се контролират от Remoting инфраструктурата и всеки канал може да има специфични изисквания, чрез тази специална група от атрибути може да се подават специфичните стойности. За тях няма предефинирани атрибути. Форматът, в който се подават стойностите, е ключ-стойност. За по-нагледно представяне нека разгледаме един пример:

type="CommonTypes.Channels.CustomChannel, CommonTypes"

myProperty="myValue"

author="Viktor Zhivkov" />



Когато използваме в рамките на тага ние се обръщаме към вече дефиниран канал в друга секция или в machine.config файла. В този случай трябва да укажем следните задъл­жителни атрибути:

  • ref – означава името (id атрибута) на шаблона, който реферираме.

  • port – номера на порта, на който каналът трябва да "слуша". В клиентските конфигурационни файлове можем да зададем стойност 0, при което Remoting системата автоматично избира вместо нас подходящия порт за връзка.

Каналите имат и други атрибути освен изброените задължителни. Ще разгледаме поотделно списъка с атрибути на стандартните вградени HTTP и TCP канали.

Атрибути на HTTP канал:



  • clientConnectionLimit – определя максималния брой на едновре­менните връзки за даден канал. По подразбиране има стойност 2.

  • proxyName – име на прокси сървър. По този начин се конфигурира Remoting инфраструктурата да използва прокси сървър.

  • proxyPort – порт на прокси сървъра, който да се използва за комуникация. Употребява се заедно с proxyName атрибута.

  • useIpAddress – булева стойност за това дали в URL адресите на предоставяните типове се използва IP адрес (true) или име на машина (false). Приложим е само в конфигурацията на сървъра. По подразбиране има стойност true.

  • machineName – име на машината, което да се използва при комуни­кация вместо истинското й име. Ако е подадена стойност автома­тично атрибутът useIpAddress приема стойност false.

Атрибути на TCP канал:

  • useIpAddress – булева стойност за това дали в URL адресите на предоставяните типове се използва IP адрес (true) или име на машина (false). Приложим е само в конфигурацията на сървъра. По подразбиране има стойност true.

  • rejectRemoteRequests – булева стойност, която задава дали да се отхвърлят връзки от други машини. Когато има стойност true са разрешени само извиквания между процесите на една машина.


Намира се под тага и служи за контейнер на таговете, описващи тръбите на канала (channel sink). Тази секция от конфигурационния файл не е задължителна и може да се среща най-много веднъж във файл. Валидните под-елементи на този таг са и


Този елемент може да бъде използван както под тага , така и под . Той служи за дефиниране и конфигуриране на доставчиците (providers) от страна на сървъра.

По аналогия с каналите първата употреба дефинира нов sink provider, а втората конфигурира вече съществуващ. Стандартните доставчици са дефинирани във файла machine.config. Този таг може да се употребява само веднъж.

Стандартните доставчици и форматери на канала се преконфигурират, ако използваме този таг за рефериране или деклариране в секцията. В този случай трябва да изброим всички доставчици и форма­тери, които ще бъдат използвани от канала. Например, ако добавим в конфигурационния файл на клиента доставчик, а след това форматер, ще получим изключение (exception), ако доставчикът не имплементира нужен на форматера интерфейс.

В тази секция могат да се използват таговете и


.


Тагът е аналогичен на , с тази разлика, че дефинира и конфигурира доставчиците от страна на клиента.



Използва се в секциите и . Описва sink provider на канала, за който се отнася. Може да се среща нула или повече пъти в една секция. За конфигуриране се използват следните задължителни атрибути:

  • id – уникално име на доставчика, което ще се използва за рефериране.

  • type – пълен тип на класа, чиято инстанция ще бъде доставчика. Форматът на този атрибут е същият, както на досега разглежданите атрибути .

  • ref – посочва id на доставчика, който се реферира. Не може да се използва в секции, които дефинират такива.

Освен тези атрибути можем да подадем на конструктора на доставчика параметри чрез съдържанието на
тага. От гледна точка на Remoting системата, няма значение какво е името на тага вътре, тъй като той се подава като DOM структура. Всички XML атрибути и XML структури в този таг се подават на конструктора на доставчика, описан в конфигу­рацията. Всеки един от доставчиците трябва да има конструктори, които приемат IDictionary или ICollection като входни параметри. Речни­ковата колекция се използва за контейнер на подадените атрибути, а колекцията – за DOM структурата на елемента и неговите под-елементи.

Ето така изглежда част от един примерен конфигурационен файл. Тагът , както и атрибутите mode, mask, ip ще бъдат използвани като параметри за инстанцирането на доставчика от тип IpFilter (този тип е измислен за примера, не го търсете в .NET Framework!).



...













...











Използва се като под-елемент на и . Конфигурира какъв форматер ще използва даденият канал. Ако бъде пропуснат, се използва подразбиращият се форматер. Може да се изброят няколко форматера, които да обработват последо­вателно данните, преминаващи през канала. В този случай другата страна в комуникацията трябва да бъде конфигурирана със същата последова­телност от форматери. За конфигуриране на форматера се използват следните атрибути:

  • id – уникално име на форматера, което ще се използва при рефериране.

  • type – пълен тип на класа, чиято инстанция ще бъде форматер. Форматът на този атрибут е същия, както в досега разглежданите атрибути .

  • ref – посочва id на форматера, който се реферира. Не може да се използва в секции, които дефинират такива.

  • typeFilterLevel – определя нивото на позволените извиквания. Има две стойности: Low и Full. Подразбиращата се стойност Low не позволява обръщения от тип callback. В случай, че ни се налага да използваме такива, трябва да променим тази стойност на Full. Най-честата причина за промяна на тази настройка на форматера е използването на спонсори с маршализация по референция (те имат нужда от callback извиквания).

Подобно на доставчиците, и форматерите могат да бъдат фино конфи­гурирани с потребителски атрибути и тагове в секцията. Процесът е аналогичен на разгледания по-горе.

Два реални конфигурационни файла – пример


За да обобщим и придадем форма на натрупаните до тук факти за конфи­гурационните файлове, нека разгледаме два цялостни реални примера:

Пример за цялостен конфигурационен файл за Remoting инфраструкту­рата от страна на сървъра:



server.config









type="CommonTypes.Query, CommonTypes"

objectUri="Query" />

type="CommonTypes.Library, CommonTypes"

objectUri="Library" />















































Пример за цялостен конфигурационен файл за Remoting инфраструкту­рата от страна на клиента:

client.config







leaseTime="3m"

sponsorshipTimeout="30s"

renewOnCallTime="1m"

leaseManagerPollTime="750ms" />



url="http://remoting_server/RemotingApp/Query" />



url="http://remoting_server/RemotingApp/Library"/>

































В тези два файла са показани най-важните и често срещани елементи. В случай, че използвате само вградените канали, доставчици и форматери, ще са ви достатъчни само такива конфигурационни файлове.

Каталог: dotnetcourse -> Beta1
Beta1 -> Изграждане на графичен потребителски интерфейс с Windows Forms
Beta1 -> Асемблита и разпространение
Beta1 -> Управление на паметта и ресурсите
Beta1 -> Уеб услуги с asp. Net
dotnetcourse -> Кратко ръководство и полезни съвети за това как да разработим своя практически проект
dotnetcourse -> Въпрос: Кога е нужно да слагам в класовете си свойства, и кога мога да слагам публични полета? Не е ли вторият вариант по-удобен, особено когато едно поле не се валидира по никакъв начин? Отговор
Beta1 -> Сериализация на данни


Сподели с приятели:
  1   2   3




©obuch.info 2024
отнасят до администрацията

    Начална страница