Сериализация WCF и шаблон объекта Value в доменном дизайне - PullRequest
3 голосов
/ 23 августа 2010

В книге Эрика Эванса «Домен, управляемый дизайном» описывается шаблон, называемый объектом значения.Одной из важных характеристик объекта стоимости является то, что он является неизменным.

В качестве примера у меня есть объект значения "Clinic", который должен иметь имя и идентификатор.Чтобы сделать его объектом значения, я не предоставляю сеттеры для имени и идентификатора.Также, чтобы убедиться, что нет недопустимого экземпляра, я беру имя и идентификатор в конструкторе и не предоставляю его в конструкторе без параметров.

открытый класс Clinic {

public Clinic(string name, string id)
{
    Name = name;
    Id = id;  
}

public string Name{get; private set;}
public string Id{get; private set;}

}

Проблема в том, что когда я пытаюсь вернуть этот объект из службы WCF, я получаю исключение, что у объекта нет конструктора без параметров, а у свойств нет открытых установщиков.Я хочу избежать добавления параметров без конструкторов и общедоступных сеттеров, потому что тогда моя модель доменной модели идет навстречу.Как я могу обойти эту проблему?

С уважением, Unmesh

Ответы [ 2 ]

3 голосов
/ 23 августа 2010

Раньше у меня была похожая проблема с сериализацией неизменяемых типов, в конце я решил реализовать интерфейс ISerializable и использовать SerializationInfo для хранения и извлечения приватных переменных на обоих концах процесса сериализации / десериализации:

http://theburningmonk.com/2010/04/net-tips-making-a-serializable-immutable-struct/

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

[Serializable]
public class Clinic : ISerializable
{
public Clinic(string name, string id)
{
    Name = name;
    Id = id;  
}

public Clinic(SerializationInfo info, StreamingContext context)
{
    Name= info.GetString("Name");
    Id= info.GetString("Id");
}

public string Name{get; private set;}
public string Id{get; private set;}

[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
    info.AddValue("Name", Name);
    info.AddValue("Id", Id);
}
}

Это решит проблему с передачей данных из WCF. Но с точки зрения дизайна я согласен с тем, что говорит Ладислав, и, как правило, вы захотите отделить свои доменные объекты от объектов, предназначенных исключительно для передачи сообщений (DataTransferObjects), и в этом случае вот пример того, как вы МОЖЕТЕ подойти к этому:

// the domain object (NOT EXPOSED through the WCF service)
public class Clinic
{
public Clinic(string name, string id)
{
    Name = name;
    Id = id;  
}

public string Name{ get; private set;}
public string Id{ get; private set;}

// other methods encapsulating some business logic, etc.
...
}
// the corresponding DTO object for the domain object Clinic
// this is the type exposed through the WCF layer, that the client knows about
[DataContract]
public class ClinicDTO
{
    [DataMember]
    public string Name { get; set; }
    [DataMember]
    public string Id { get; set; }
}
// WCF service contract, NOTE it returns ClinicDTO instead of Clinic
[ServiceContract]
public interface IClinicService
{
   [OperationContract]
   ClinicDTO GetClinicById(string id);
}

Чтобы облегчить процесс перехода из Clinic в ClinicDTO, вы можете либо добавить метод в Clinic для этого, либо реализовать неявный / явный преобразователь. У меня есть пример, как это сделать здесь: http://theburningmonk.com/2010/02/controlling-type-conversion-in-c/

Надеюсь, это поможет!

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

Проблема в том, что ваш объект значения не сериализуем. Как вы планируете использовать сервис? Планируете ли вы делиться объектами домена / объектами стоимости со своими клиентами? Если да, то IMO нарушает дизайн вашего домена - только бизнес-уровень должен иметь возможность работать с объектами домена и вызывать их методы. Если вы не хотите делиться объектами, вы, вероятно, создадите прокси-сервер, добавив ссылку на службу, которая будет генерировать данные для клиента. Эти контрасты будут иметь открытый конструктор без параметров и все свойства, которые можно установить (и не использовать методы домена).

Если вы хотите иметь реальный доменный дизайн, вы не должны выставлять свои доменные объекты в WCF. Вместо этого вы должны создать набор DTO и выставить эти DTO. Сервисный уровень будет отвечать за преобразование этих DTO в объекты Domain / значения и наоборот.

...