У кого-нибудь есть умный способ относиться к DTO как к классу OO? - PullRequest
2 голосов
/ 11 августа 2010

У меня есть набор DataContracts, которые сериализуются через WCF.

Обратите внимание, что это очень упрощенный пример.

[DataContract]
public class MyData
{
    [DataMember]
    public List<int> MyList
    {
        get;
        set;
    }
}

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

В идеале, я бы хотел, чтобы класс выглядел так, если бы это не был DTO.

public class MyData
{
    private List<int> _list = new List<int>();

    public IEnumerable<int> MyList
    {
        get
        {
            return _list;
        }
    }

    public void AddItem( int value )
    {
        _list.Add( value );
    }
}

Я использую одну и ту же сборку C # как для службы, так и для клиента. Поэтому я могу добавить не DataMember методы, но я не уверен, что это хороший подход. Это не пахнет совсем правильно для меня.

Есть ли у кого-нибудь умный способ рассматривать классы DTO больше как объекты вместо простых сериализуемых структур?

Ответы [ 3 ]

2 голосов
/ 11 августа 2010

Как насчет DTO-версий вашего логического класса, которые используются исключительно для передачи сообщений?Таким образом, вы можете поместить все методы и свойства в свой класс логики по мере необходимости, не беспокоясь о том, к чему у пользователя есть доступ, когда он передается по проводам.Есть много способов сделать это, например:

вы можете реализовать некоторый метод в своем логическом классе для возврата DTO

public class Player
{
   // methods that do interesting things here
   ...

   public string Name { get; set; }

   public PlayerDTO ToTransport()
   {
      return new PlayerDTO { Name = Name, ... };
   }
}

[DataContract]
public class PlayerDTO
{
   [DataMember]
   public string Name { get; set; }

   ...
}

Или вы можете реализовать явное / неявное преобразование

public class Player
{
   // methods that do interesting things here
   ...

   public string Name { get; set; }
}

[DataContract]
public class PlayerDTO
{
   [DataMember]
   public string Name { get; set; }

   ...

   public static explicit operator PlayerDTO(Player player)
   {
      return new PlayerDTO { Name = player.Name, ... };
   }
}

это позволяет вам преобразовать объект Player в PlayerDTO:

var player = new Player { Name = .... };
var dto = (PlayerDTO) player;
1 голос
/ 13 августа 2010

Лично я думаю, что наличие DataContract для объектов, предназначенных не только для служебных операций, является чем-то вроде запаха, как это было бы для отображений столбцов ORM. Один несколько ограниченный способ сделать эти DTO более похожими на настоящие OO - это чтобы ваши методы были методами расширения DTO. Возможно, вам придется сделать что-то креативное, если у версии OO есть состояние, которое нужно фиксировать между вызовами, хотя это не присуще самому объекту DTO.

0 голосов
/ 11 августа 2010

Я не думаю, что наличие методов, не украшенных атрибутами в классе вашего DataContract, обязательно пахнет. С одной стороны, у вас есть проблемы, связанные с обслуживанием (контракты на операции и данные), а с другой - ваши проблемы, связанные с объектами. То, что клиент делает с предоставленными данными, не имеет значения для службы. Описанная вами объектно-ориентированная проблема действительно существует только для клиента.

Если клиент получил данные Ball от вашего сервиса и хочет вывести их на экран, независимо от того, имеет ли класс Ball метод Draw (), он не имеет ничего общего с контрактом между сервисом и клиентом. Это контракт между API, предоставляемым вашей сборкой, и теми, кто его использует. Итак, я говорю, почему бы не иметь метод в сборке, который не является контрактом операции / данных?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...