Как эффективно использовать DTO на основе сценария в C#

Я работаю над моделью сотрудника, она содержит всю информацию о сотруднике

Например:

public class Employee
{
    public int EmployeeId { get; set; }
    public string FirstName { get; set; }
    public string MiddleName { get; set; }
    public string LastName { get; set; }
    public string EmailAddress { get; set; }
    public string HomePhone { get; set; }
    public string MobilePhone { get; set; }
}

У меня есть два метода для получения записей сотрудника

public Employee GetEmployeeName(int id)
{
    // The return should contain only FirstName, MiddleName and LastName. 
    // The rest of the properties should be non-accessable (i.e., Private)
}

public Employee GetEmployeeContacts(int id)
{
    // The return should contain only EmailAddress, HomePhone and MobilePhone. 
    // The rest of the properties should be non-accessable (i.e., Private)
}

public Employee GetEmployeeNameEmail(int id)
{
    // The return should contain only FirstName, MiddleName, LastName and EmailAddress. 
    // The rest of the properties should be non-accessable (i.e., Private)
}

public Employee GetEmployee(int id)
{
    // It should return the entire Employee object
}

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

2 ответа

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

  1. Используйте динамический объект, который имеет множество плюсов и минусов. Смотрите здесь и здесь.

  2. Используйте наследование для определения базового класса (например, EmployeeCommon) с общими свойствами знаменателя и подклассами для каждого дополнительного подмножества (EmployeeCommonAndPhoneNumbers) вы хотите вернуться от ваших различных методов.

  3. Разделите различные наборы свойств на отдельные классы "группы свойств" (например, ContactInfo) и поместите их как свойства на ваш Employee учебный класс. Индивидуальные свойства (как FirstName или же EmailAddress) то, что вы хотите "показать и скрыть", может присутствовать или отсутствовать в каждом экземпляре Employee по мере необходимости, но все различные объекты "группы свойств" все равно будут присутствовать в каждом экземпляре Employee как собственность (хотя они будут null в случаях, когда они не нужны), так что это может или не может соответствовать вашим требованиям.

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

IIUC, специализированная GetEmployee... методы будут жить в отдельном фабричном классе и будут создавать экземпляры Employeeс заполнением только обязательных свойств. Я предполагаю, что вы хотите сделать это, потому что ваш API включает в себя разные контракты сообщений с различными подмножествами свойств Employee. GetEmployeeNameEmail Реализация метода будет искать Employee с указанным идентификатором, создавать новый экземпляр Employee, заполнять только свойства name и email и возвращать этот объект.

Вы не можете сделать методы приватными для этих различных контекстов DTO; но вы можете "спрятать" их, определив отдельные интерфейсы для каждого подмножества свойств. Подкласс Employee будет реализовывать каждый из этих интерфейсов:

public interface IEmployeeWithName
{
     int EmployeeId { get; set; }
     string FirstName { get; set; }
     string MiddleName { get; set; }
     string LastName { get; set; }
}

 interface IEmployeeWithContacts
{
     int EmployeeId { get; set; }
     string EmailAddress { get; set; }
     string HomePhone { get; set; }
     string MobilePhone { get; set; }
}

 interface IEmployeeWithNameEmail
{
     int EmployeeId { get; set; }
     string FirstName { get; set; }
     string MiddleName { get; set; }
     string LastName { get; set; }
     string EmailAddress { get; set; }
}

 interface IEmployee
{
     int EmployeeId { get; set; }
     string FirstName { get; set; }
     string MiddleName { get; set; }
     string LastName { get; set; }
     string EmailAddress { get; set; }
     string HomePhone { get; set; }
     string MobilePhone { get; set; }
}

public class Employee : IEmployee, IEmployeeWithContacts, IEmployeeWithName, IEmployeeWithNameEmail
{
    public int EmployeeId { get; set; }
    public string FirstName { get; set; }
    public string MiddleName { get; set; }
    public string LastName { get; set; }
    public string EmailAddress { get; set; }
    public string HomePhone { get; set; }
    public string MobilePhone { get; set; }
}

public class EmployeeFactory
{

    private Employee GetEmployeeByID(int id)
    {
        // this would perform the lookup and populate the Employee object...
        return new Employee();
    }

    public IEmployeeWithName GetEmployeeName(int id)
    {
        // The return should contain only FirstName, MiddleName and LastName. 
        return GetEmployeeByID(id);
    }

    public IEmployeeWithContacts GetEmployeeContacts(int id)
    {
        // The return should contain only EmailAddress, HomePhone and MobilePhone. 
        return GetEmployeeByID(id);
    }

    public IEmployeeWithNameEmail GetEmployeeNameEmail(int id)
    {
        // The return should contain only FirstName, MiddleName, LastName and EmailAddress. 
        return GetEmployeeByID(id);
    }

    public IEmployee GetEmployee(int id)
    {
        // It should return the entire Employee object
        return GetEmployeeByID(id);
    }
}

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

Другие вопросы по тегам