简体   繁体   English

重构 C# 代码以实现某种工厂设计模式

[英]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.我有一个 Web API 应用程序 (.NET Core),它是我后端的一部分。 I have implemented the Unit of Work and Repository patterns into a N-Layer 1 Tier Architecture.我已经将工作单元和存储库模式实现到 N 层 1 层架构中。 The way how the Client App and the backend communicate is through sending DTO's (Data Transfer Objects).客户端应用程序和后端通信的方式是通过发送 DTO(数据传输对象)。 So, I have different DTO's obviously with a different structure and composition according to what the Repository Method is requesting.因此,根据存储库方法的请求,我显然有不同的 DTO,具有不同的结构和组成。 This is because at design time I define the type of DTO the Client is expecting, something like this:这是因为在设计时我定义了客户端期望的 DTO 类型,如下所示:

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: EmployeeDto是这样的:

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).我想要做的是删除紧密耦合的实例化代码( public EmployeeDto employee = new EmployeDto(); ),并实现某种工厂模式,我只调用 Factory 对象,传递我想要的 DTO 类型(因为我已经知道了)并且工厂将我请求的 DTO 类型和 DTO 状态(数据)返回给我。

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.请记住,我有几种具有不同结构的 DTO,因此它们的填充方式不同,并且可以在不同的方法中调用 Factory 对象并可以请求不同的 DTO。

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.只需一行即可获取整个“包”DTO 本身和数据。

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.我只需要指导哪些设计模式可能是最佳选择和一个示例,我已经阅读了有关 Creational Design 模式工厂及其不同风格的内容,但我还不明白这是如何实现的。

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.但是,我不认为这是一个正确的答案,在返回 Dto 时强制转换 Dto,我不喜欢 Factory 类中的 Object 泛型类型。 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.处理EmployeeDto类型的存储库直接了解这种类型似乎是很自然的。

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 .这意味着您不会像示例中那样使用GetEmployeeDto方法,而只是通用的GetDto甚至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.这让我想到另一个提示:遵循 DDD 相关模式,存储库应该返回一个可以使用的域对象,而不是 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.但即使使用自动映射器,所有技术细节都应该对域层隐藏。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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