Интернет-журнал 'Домашняя лаборатория', 2007 №6 - Усманов
0/0

Интернет-журнал 'Домашняя лаборатория', 2007 №6 - Усманов

Уважаемые читатели!
Тут можно читать бесплатно Интернет-журнал 'Домашняя лаборатория', 2007 №6 - Усманов. Жанр: Газеты и журналы / Сделай сам / Хобби и ремесла. Так же Вы можете читать полную версию (весь текст) онлайн книги без регистрации и SMS на сайте Knigi-online.info (книги онлайн) или прочесть краткое содержание, описание, предисловие (аннотацию) от автора и ознакомиться с отзывами (комментариями) о произведении.
Описание онлайн-книги Интернет-журнал 'Домашняя лаборатория', 2007 №6 - Усманов:
Большой и увлекательный, научно-прикладной и образовательный, но некоммерческий интернет-журнал, созданный группой энтузиастов. Интернет-журнал содержит материалы, найденные в Интернет или написанные для Интернет. Основная тематика статей — то, что можно сделать самому, от садовых поделок до сверхпроводников, но есть и просто полезные материалы.
Читем онлайн Интернет-журнал 'Домашняя лаборатория', 2007 №6 - Усманов

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 247 248 249 250 251 252 253 254 255 ... 361
(производный от System.Object). Если предполагается передача контекста вызова через границу контекста, домена приложения, процесса, машины, значение каждого передаваемого свойства должно быть экземпляром класса, определенного с атрибутом Serializable и производного от ILogicaiThreadAffinative. Определение интерфейса ILogicalThreadAffinative не содержит никаких методов и данный интерфейс используется просто как маркер классов, допускаемых для передачи в контексте вызова за пределы контекста, домена приложения и т. п.

Реально контекст вызова передается через ранее упомянутые границы в форме сообщения типа IMessage. В связи с этим и требуется сериализуемость всех передаваемых объектов (т. е. возможность их передачи по значению).

Ниже представлен пример, демонстрирующий применение контекста вызова, пересекающего границу между процессами. За основу взят многократно рассмотренный пример, связанный с перечислением 5 условных единиц со стороны клиента на счет, поддерживаемый сервером.

Рассмотрим прежде всего код сервера.

Сервер

using System;

using System.Runtime.Remoting;

using System.Runtime.Remoting.Channels;

using System.Runtime.Remoting.Channels.Http;

using System.Threading;

using System.Runtime.Remoting.Contexts;

using System.Runtime.Remoting.Messaging;

using System.Reflection;

namespace MyServer {

[Serializable]

public class MyCallContextUserName:

      ILogicalThreadAffinative {

      private String _userName;

      public MyCallContextUserName() {

           _userName = Environment.UserName;

       }

        public String UserName {

            get { return _userName; }

        }

}

[Serializable]

public class MyCallContextServerName:

        ILogicalThreadAffinative {

         private Assembly _assembly;

         private String _serverName;

         public MyCallContextServerName() {

                _assembly = Assembly.GetExecutingAssembly();

                _serverName = _assembly.FullName;

         }

         public String ServerName {

               get { return _serverName; }

         }

}

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) {

             this.sum += sum;

             MyCallContextUserName userName =

                   (MyCallContextUserName)CallContext.GetData("UserName");

             Console.WriteLine("UserName = " +

                   userName.UserName);

              CallContext.SetData("ServerName",

                    new MyCallContextServerName());

             }

             public int Total() {

                  return this.sum;

            }

}

public class AccountApp {

public static void Main() {

            HttpChannel myChannel = new HttpChannel(8080);

            ChannelServices.RegisterChannel(myChannel);

            RemotingConfiguration.RegisterWellKnownServiceType {

                  typeof(Account), "Account",

                  WellKnownObjectMode.Singleton);

             Console.WriteLine("Server is listening");

             Console.ReadLine();

             Console.WriteLine("Bye");

        }

    }

}

Относительно этого кода можно сделать следующие комментарии.

В методе Add наш сервер будет не только получать очередной вклад и зачислять его на счет, но и работать с контекстом вызова.

Во-первых, предполагается, что клиент перед вызовом метода Add добавил в контекст вызова свойство с именем UserName. Соответствующее значение содержит учетные данные пользователя, от имени которого было запущено клиентское приложение. Значение свойства UserName задается ссылкой на экземпляр класса

[Serializable]

public class MyCallContextUserName:

        ILogicalThreadAffinative {…}

Из определения этого класса видно, что его экземпляры могут передаваться в контексте вызова за пределы текущего контекста, т. к. этот класс определяется с атрибутом сериализации и наследует интерфейс ILogicalThreadAffinative.

Конструктор данного класса

public MyCallContextUserName() {

       _userName = Environment.UserName;

}

сохраняет в строковом поле _userName значение соответствующей переменной среды, получаемой как статическое свойство UserName класса Environment.

Используя свойство userName контекста вызова сервер в методе Add выясняет имя пользователя и выводит его на консоль:

MyCallContextUserName userName =

       (MyCallContextUserName)CallContext.GetData("UserName");

Console.WriteLine("UserName = " +

         userName.UserName);

Для доступа к нужному свойству используется статический метод GetData класса CallContext, которому в качестве параметра передается имя свойства. Полученное значение приводится к типу MyCallContextUserName.

Во-вторых, получив и выведя на консоль имя пользователя, сервер заканчивает выполнение метода Add, включая в контекст вызова свою информацию. Эту новую информацию сможет получить клиент, дождавшийся возврата из метода Add.

Итак, сервер добавляет в контекст вызова новое свойство с именем ServerName:

CallContext.SetData("ServerName",

        new MyCallContextServerName()};

Класс MyCallContextS erverName определяется аналогично классу MyCallContextUserName.

Основная функциональность этого класса определяется его конструктором:

public MyCallContextServerName() {

        _assembly = Assembly.GetExecutingAssembly();

        _serverName = _assembly.FullName;

}

Здесь мы получаем ссылку на исполняемую сборку (т. е. на сборку сервера) и сохраняем в _serverName ее полное имя.

Остальная часть кода сервера не претерпела каких-либо изменений.

Клиент

using System; using MyServer;

using System. Runtime.Remoting;

using System.Runtime.Remoting.Channels;

using System.Runtime.Remoting.Channels.Http;

using System.Net;

using System.Runtime.Remoting.Messaging;

public class MyApp {

       public static void Main() {

           HttpChannel с = new HttpChannel();

           ChannelServices.RegisterChannel(c);

           try {

                Account a = (Account)Activator.GetObject(typeof(Account),

                "http://localhost:8080/Account",

                 WellKnownObjectMode.Singleton);

           CallContext.SetData("UserName",

                 new MyCallContextUserName());

           a. Add(5);

           Console.WriteLine("5 is sent to " +

                ((MyCallContextServerName)CallContext.GetData(

                       "ServerName")).ServerName);

           Console.WriteLine("Total = " +a.Total());

       }

       catch(WebException e) {

            Console.WriteLine(e.Message);

       }

       catch(Exception e) {

             Console.WriteLine(e.Message);

       }

       finally!

             Console.WriteLine("Bye");

       }

   }

}

Все отличие данного кода клиента от рассмотренных ранее примеров представлено в следующих строках

CallContext.SetData("UserName",

         new MyCallContextUserName());

a. Add(5);

Console.WriteLine("5 is sent to " +

          ((MyCallContextServerName)CallContext.GetData (

                   "ServerName")).ServerName);

Перед вызовом метода Add клиент добавляет в контекст вызова уже рассмотренное свойство userName. В результате, при выполнении вызова Add, сервер получает доступ к учетным данным пользователя, от имени которого было запущено клиентское приложение, и может принимать решение о выполнении данного вызова.

По завершении вызова метода Add клиент получает из свойства контекста значение свойства serverName, добавленное в контекст вызова сервером при выполнении Add. В результате клиент получает информацию о сборке, содержащей код сервера, выполнившего

1 ... 247 248 249 250 251 252 253 254 255 ... 361
На этой странице вы можете бесплатно читать книгу Интернет-журнал 'Домашняя лаборатория', 2007 №6 - Усманов бесплатно.

Оставить комментарий

Рейтинговые книги