简体   繁体   中英

Refactor over C# code to implement some kind of Factory Design Pattern

I have a Web API App (.NET Core) that is part of my backend. I have implemented the Unit of Work and Repository patterns into a N-Layer 1 Tier Architecture. The way how the Client App and the backend communicate is through sending DTO's (Data Transfer Objects). So, I have different DTO's obviously with a different structure and composition according to what the Repository Method is requesting. This is because at design time I define the type of DTO the Client is expecting, something like this:

public EmployeeDto GetEMployeeDto()
{
    public EmployeeDto employee = new EmployeeDto();
    
    .
    .
    .
    // Code to get data from data base and full fill the fields of the DTO.
    .
    .
    .

    return EmployeeDto;

}

Where EmployeeDto is something like this:

public cladd EmployeeDto()
{
     public int Employee Id {get;set;}
     public string EmployeeName {get;set;}
}

What I would like to do is remove the instantiating code ( public EmployeeDto employee = new EmployeDto(); ) which is tight coupling, and implement some kind of factory pattern where I just call the Factory object, pass the type of DTO I want (because I already know it) and that the Factory returns me the type of DTO I requested and with the DTO state (data).

Just keep on mind that I have several types of DTO's with different structure, so the way how they are fill is different and that the Factory object could be called in different methods and could be requested different DTO's.

Something like:

var employee = FactoryDto.GetDto(EmployeDto);
var employeeHistory = FactoryDto.GetDto(EmployeeHistoryDto);

With just one line get the whole "package" the DTO itself and the data.

I just need a guidance to which Design Pattern could be the best option and an example, I have read about the Creational Design pattern Factory and the different flavors it has but I have not understood yet how could this achieve.

This is one of the approaches I have:

public EmployeeDto GetEmployeeDto(string dtoType)
{
    var factoryDto = new FactoryDto();
    var empDto = factoryDto.GetDto(dtoType);

    return (EmployeeDto)empDto;
}


public class FactoryDto
{
    public object GetDto(string dtoType)
    {
        switch(dtoType)
        {
            case "EmployeeDto":
                {
                    return new EmployeeDto();
                }
            case "EmployeeHistoryDto":
                {
                    return new EmployeeHistoryDto();
                }
            default:
                {
                    return new EmployeeHistoryDto();
                }
        }
            
    }

}

But, I do not think this is a correct answer, casting the Dto when returning the Dto and I do not like that Object generic type in the Factory class. Is there a better way to improve this approach using any of the Creational Design Patterns? Regards!

There is no way (at least not one that makes sense to me) to decouple an implementation meant to deal with a specific type, from this type. It seems perfectly natural for a repository dealing with EmployeeDto type to know directly about this type.

Not sure how does your design look at a broader view, but perhaps what you are missing is a generic interface, so your client side is not much coupled? For example, something like this:

public interface IRepository<T>
{
    IEnumerable<T> GetAll<T>();
    T Get<T>(int id);
}

An implication is that you would not have GetEmployeeDto method as in your example, but just a general GetDto or even Get . Which leads me to another hint: following DDD-related patterns, a repository should return a domain object that is ready to use, not a DTO.

This way your domain layer can just use the repository and focus on domain logic, instead of being forced to deal with conversions. As mentioned in the comments it's good to configure an automapping library to do this for you anyway. But even with an automapper, all technicalities should be hidden from the domain layer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM