Лучший способ использовать DTO на стороне клиента WCF - PullRequest
0 голосов
/ 20 апреля 2019

Мне хотелось бы получить несколько советов о том, как правильно реализовать следующую ситуацию.

У меня есть три решения: служба WCF, которая использует Entity Framework для взаимодействия с базой данных SQL, - сервер WPF, на котором размещается служба.и клиент WPF, который использует сервис.Я думаю о том, как правильно внедрить DTO.

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

На стороне клиента я должен добавить некоторые расширения к этим DTO, например, мне нужно добавить несколько автоматически рассчитанных свойств и методов.

В итоге у меня возникли две идеи

Первая идея - создать частичный класс для каждого DTO, мне нужно добавить логику.

Преимущество я вижу в этом: мне не нужно переписывать весь DTO, только добавить дополнительные свойства и методы.нужно, и мне нужно сопоставить только один раз EFEntity => ServiceDTO и ServiceDTO => EFEntity

Недостаток: я хотел бы установить для приватности некоторые свойства, чтобы другие были доступны только для чтения.Но независимо от уровня доступа или настроек, которые я пишу в Service DTO, он всегда генерируется на клиенте как public .... { get; set; }.

Вот пример такого подхода

//AT THE WCF SERVICE: DTO
[DataContract]
public class BajaRoturaDTO
{
    [DataMember] public int Id { get; set; }
    [DataMember] public int NoVale { get; set; }
    [DataMember] public DateTime Fecha { get; set; }
    [DataMember] public UsuarioDTO Usuario { get; set; }
    [DataMember] public string Comentario { get; set; }
    [DataMember] public DepartamentoDTO Departamento { get; set; }
    [DataMember] private List<Instance> _instances { get; set; } //I would like to make this private but it's autogenerated public on the Client

    [DataContract]
    public class Instance
    {
        [DataMember] public int ValidationState { get; set; }
        [DataMember] public int Cantidad { get; set; }
        [DataMember] public ProductoInstanceDTO TargetInstance { get; set; }
    }
}

//AT THE WPF CLIENT: DTO PARTIAL CLASS
public partial class BajaRoturaDTO
{
    public BajaRoturaDTO()
    {
        _instances = new List<Instance>();
    }

    public BajaRoturaDTO(DateTime defaultDate)
    {
        Fecha = defaultDate;
        _instances = new List<Instance>();

    }
    [Magic] public List<Instance> Instances { get => new List<Instance>(_instances); }

    [Magic] public decimal ImporteCosto { get => _instances.Sum(x => x.ImporteVenta); }

    [Magic] public decimal ImporteVenta { get => _instances.Sum(x => x.ImporteCosto); }

    [Magic] public string TotalProductos { get => _instances.Count() + " producto(s)"; }

    public partial class Instance
    {
        [Magic] public decimal ImporteCosto { get => Cantidad * TargetInstance.Producto.PrecioCosto; }

        [Magic] public decimal ImporteVenta { get => Cantidad * TargetInstance.Producto.PrecioVenta; }

        public async Task Validate(DateTime targetDate)
        {
            ValidationState = await TargetInstance.Validate(targetDate, Cantidad);
        }
    }

    //METHODS
    public async Task AddInstance(Instance target)
    {
        var matchInList = _instances.FirstOrDefault(x =>
            x.TargetInstance.Producto.Id == target.TargetInstance.Producto.Id
            && x.TargetInstance.Departamento.Id == target.TargetInstance.Departamento.Id);

        if (matchInList is null)
        {
            _instances.Add(target);
            await target.Validate(Fecha);
        }
        else
        {
            matchInList.Cantidad += target.Cantidad;
            await matchInList.Validate(Fecha);
        }

        RaisePropertyChanged("Instances");
        RaisePropertyChanged("ImporteCosto");
        RaisePropertyChanged("ImporteVenta");
        RaisePropertyChanged("TotalProductos");
    }
//More methods

PD:Декоратор [Magic] - это расширение, которое я установил для автоматизации INotifyPropertyChange.

Другая идея - создать новый класс для каждого DTO на клиенте WPF и снова использовать AutoMapper для сопоставления ServiceDTO с ClientClass

Преимущество, которое я вижу: я могу определять автоматически вычисляемые свойства, закрытое поле, методы и все, что я хочу

Недостаток, который я вижу: мне приходится заново создавать каждый DTO и выполнять большее отображение (EFEntity => ServiceDTO => CientClassи ClientClass => ServiceDTO => EFEntity)

Мне нужно ваше мнение о том, что вы думаете об этом двух подходах или есть ли лучший способ.

Спасибо за ваше время и извините за мой английскийесли у меня есть орфографические ошибки

...