Возможна ли моя цель с помощью WCF (и правильно ли это делать?) - PullRequest
1 голос
/ 06 апреля 2010

Я пишу некоторое программное обеспечение, которое изменяет конфигурацию Windows Server (такие вещи, как MS-DNS, IIS, части файловой системы).Мой проект имеет серверный процесс, который строит граф объектов в памяти о состоянии конфигурации сервера, и клиент, который запрашивает этот граф объектов.Затем сервер будет сериализовать график, отправить его клиенту (предположительно с использованием WCF), затем сервер внесет изменения в этот график и отправит его обратно на сервер.Сервер получает график и продолжает вносить изменения в сервер.

Однако я узнал, что сериализация объектного графа в WCF не так проста, как я сначала подумал.Мои объекты имеют иерархию, и у многих есть параметризованные конструкторы и неизменные свойства / поля.Существует также множество коллекций, массивов и словарей.

Насколько я понимаю, сериализация WCF заключается в том, что она требует использования XmlSerializer или DataContractSerializer, но DCS накладывает ограничения на разработку моего объектного графа (кажется, что неизменные данныеправильно, это также требует конструкторов без параметров).Я понимаю, что XmlSerializer позволяет мне использовать мои собственные классы при условии, что они реализуют ISerializable и имеют конструктор десериализатора.Это нормально для меня.

Я говорил об этом с моим другом, и он выступает за использование маршрута только для объектов передачи данных, где мне придется поддерживать отдельный объект-граф DataContract длятранспортировка данных и повторная реализация объектов моего сервера на клиенте.

Другой мой друг сказал, что, поскольку моя служба имеет только две операции ("GetServerConfiguration" и "PutServerConfiguration"), возможно, стоит просто пропустить WCF полностьюи реализации моего собственного сервера, который использует сокеты.

Итак, мои вопросы:

  • Кто-нибудь сталкивался с подобной проблемой раньше, и если да, есть ли лучшие подходы?Разумно ли отправлять целый граф объектов клиенту для обработки?Должен ли я вместо этого разбить его так, чтобы клиент запрашивал часть графа объекта так, как ему это нужно, и отправлял только биты, которые были изменены (таким образом уменьшая риски, связанные с параллелизмом?)?
  • При отправке графа объектаэто правильный путь, является ли WCF правильным инструментом?
  • И если WCF прав, каков наилучший способ заставить WCF сериализовать мой граф объектов?

Ответы [ 2 ]

3 голосов
/ 06 апреля 2010

Графы объектов могут использоваться с сериализацией DataContract.

Примечание: Убедитесь, что вы сохраняете ссылки на объекты, чтобы у вас не было нескольких копий одного и того же объекта на графике, когда все они должны быть одной и той же ссылкой, поведение по умолчанию не сохраняет идентичность как это.

Это можно сделать, указав параметр preserveObjectReferences при создании DataContractSerializer или указав true для свойства IsReference в DataContractAttribute (для этого последнего атрибута требуется. NET 3.5SP1 ).

Однако при отправке графов объектов по WCF вы рискуете столкнуться с нарушением квот WCF (а их много), если вы не позаботитесь о том, чтобы график соответствовал разумному размеру.

Например, для транспорта net.tcp необходимо установить следующие значения: maxReceivedMessageSize, maxStringContentLength и maxArrayLength. Не говоря уже о скрытой квоте из 65335 различных объектов, разрешенных на графике (maxObjectsInGraph), которую можно с трудом переопределить.

Вы также можете использовать классы, которые предоставляют доступ только для чтения с DataContractSerializer и не имеют конструкторов без параметров:

using System;
using System.IO;
using System.Runtime.Serialization;

class DataContractTest
{
    static void Main(string[] args)
    {
      var serializer = new DataContractSerializer(typeof(NoParameterLessConstructor));

      var obj1 = new NoParameterLessConstructor("Name", 1);

      var ms = new MemoryStream();
      serializer.WriteObject(ms, obj1);

      ms.Seek(0, SeekOrigin.Begin);

      var obj2 = (NoParameterLessConstructor)serializer.ReadObject(ms);

      Console.WriteLine("obj2.Name: {0}", obj2.Name);
      Console.WriteLine("obj2.Version: {0}", obj2.Version);
    }

    [DataContract]
    class NoParameterLessConstructor
    {
        public NoParameterLessConstructor(string name, int version)
        {
          Name = name;
          Version = version;
        }

        [DataMember]
        public string Name { get; private set; }
        [DataMember]
        public int Version { get; private set; }
    }
}

Это работает, потому что DataContractSerializer может создавать экземпляры типов без вызова конструктора.

0 голосов
/ 06 апреля 2010

Вы перепутали с сериализаторами:

  • для XmlSerializer требуется конструктор без параметров, поскольку при десериализации среда выполнения .NET будет создавать новый объект этого типа, а затем устанавливать его свойства

  • DataContractSerializer не имеет такого требования

Ознакомьтесь с постом в блоге Дэна Ригсби , в котором объясняются сериализаторы во всей их красе и сравниваются оба.

Теперь для вашего дизайна - мой главный вопрос: имеет ли смысл иметь одну функцию, которая возвращает все настройки, клиент манипулирует ими, а затем другую функцию, которая возвращает всю информацию?

Не могли бы вы разбить эти вещи на более мелкие куски, меньшие вызовы методов? Например. есть отдельные методы обслуживания для установки каждого отдельного элемента вашей конфигурации? Таким образом, вы могли бы

  • уменьшить объем данных, передаваемых по проводам - ​​граф объекта, который будет сериализован и десериализован, будет намного проще
  • сделать вашу конфигурационную услугу более детальной - например, если кому-то нужно установить одно маленькое свойство, этому клиенту не нужно читать всю конфигурацию большого сервера, устанавливать одно свойство и отправлять обратно огромный большой кусок - просто вызовите соответствующий метод, чтобы установить это одно свойство
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...