Рассмотрим следующий фрагмент кода, заполняющий свойства удаленного объекта информацией о человеке и вызывающий некий удаленный метод для ее обработки.
processing.FirstName = "Иван "; processing.SecondName = "Иванов"; processing.ThirdName = "Иванович"; processing.City = "Москва"; result = processing.Run();Если processing – локальный объект, то в методе Run() он будет иметь доступ к установленным здесь значениям своих методов. Предположим, что processing – удаленный объект. В этом случае возможны, например, следующие варианты.
Таким образом, один и тот же код может давать разные результаты в зависимости от модели использования удаленной компоненты, причем только в одном из примеров был получен корректный результат при минимальных накладных расходах. Можно сделать заключение, что использование в программе свойств удаленного объекта приводит к зависимости ее результата от используемой промежуточной среды и ее конфигурации.
Наилучшим вариантом решения этой проблемы представляется отсутствие публичных свойств у удаленного объекта. В таком случае использование удаленного объекта может не отличаться от вызова метода локального объекта. Однако применение такого подхода "в лоб" (так называемый chunky design) может привести к плохо читаемому коду, например следующему.
result = processing.Run("Иванов", "Иван", "Иванович", "Москва");
В отличие от предыдущего фрагмента, это код не является самодокументирующимся, и увеличивает вероятность ошибки в последовательности аргументов вызываемого метода. В данном примере так же наблюдается смешивание двух сущностей: объекта, содержащего данные о человеке, и объекта, производящего с ним операции. Правильный подход заключается в создании маршализируемого по значению класса, содержащего все параметры удаленного вызова, и передача его экземпляра как параметра удаленного вызова метода.
person.FirstName = "Иван"; person.SecondName = "Иванов"; person.ThirdName = "Иванович"; person.City = "Москва"; result = processing.Run(person);
Для многих задач представляет интерес вопрос модификации поведения удаленного объекта путем добавления некоторого дополнительного кода. Рассмотрим следующий фрагмент кода, вызывающий некий математический метод для заданной функции и заданного отрезка значений аргумента. Было бы удобно отделить реализацию самого математического метода от применяемой функции.
task.Epsilon = 1e-5: task.X1 = -1; task.X2 = 1; task.MaximumSteps = 20; task.Function += X2Function; result = processing.Run(processingArguments); ... double X2Function(double x) { return x*x; }
Если processing – это удаленный объект, то данный код, вероятно, приведет к многочисленным удаленным вызовам функции X2Function. В этом случае приведенный код имеет два главных недостатка – во первых, клиент для этого должен так же поддерживать удаленные вызовы, во вторых, он неэффективен, если удаленный метод постоянно вызывает находящуюся на стороне клиента функцию.
Для решения возникшей проблемы в общем случае требуется передать тем или иным способом кода функции (и, возможно, используемых ею данных) на сервер с реализующим математический метод удаленным объектом. Такой подход неприменим в общем случае по соображениям безопасности, но при необходимости можно, например, при использовании .NET Framework передать клиенту сборку с требуемым кодом как данные при удаленном вызове. В качестве возможной альтернативы для математических задач может выступать и передача кода функции для дальнейшей компиляции встроенным компилятором языка C#.