C# 重构C代码以实现某种工厂设计模式
我有一个Web API应用程序(.NET Core),它是我后端的一部分。我已经将工作单元和存储库模式实现到一个N层1层体系结构中。客户端应用程序和后端通信的方式是通过发送DTO(数据传输对象)。因此,根据存储库方法的请求,我有不同的DTO,显然有不同的结构和组成。这是因为在设计时,我定义了客户端期望的数据类型,如下所示:C# 重构C代码以实现某种工厂设计模式,c#,.net,design-patterns,C#,.net,Design Patterns,我有一个Web API应用程序(.NET Core),它是我后端的一部分。我已经将工作单元和存储库模式实现到一个N层1层体系结构中。客户端应用程序和后端通信的方式是通过发送DTO(数据传输对象)。因此,根据存储库方法的请求,我有不同的DTO,显然有不同的结构和组成。这是因为在设计时,我定义了客户端期望的数据类型,如下所示: public EmployeeDto GetEMployeeDto() { public EmployeeDto employee = new EmployeeDto
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;
}
public cladd EmployeeDto()
{
public int Employee Id {get;set;}
public string EmployeeName {get;set;}
}
public interface IRepository<T>
{
IEnumerable<T> GetAll<T>();
T Get<T>(int id);
}
其中EmployeeDto
是这样的:
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;
}
public cladd EmployeeDto()
{
public int Employee Id {get;set;}
public string EmployeeName {get;set;}
}
public interface IRepository<T>
{
IEnumerable<T> GetAll<T>();
T Get<T>(int id);
}
我想做的是删除紧耦合的实例化代码(public EmployeeDto employee=new EmployeeDto();
),并实现某种工厂模式,在这里我只调用工厂对象,将数据类型传递给我想要的(因为我已经知道它)工厂返回我请求的DTO类型和DTO状态(数据)
请记住,我有几种不同结构的DTO,因此它们的填充方式不同,工厂对象可以用不同的方法调用,可以请求不同的DTO
比如:
var employee = FactoryDto.GetDto(EmployeDto);
var employeeHistory = FactoryDto.GetDto(EmployeeHistoryDto);
只需一行就可以将整个“包”数据传输到数据本身和数据
我只需要一个关于哪种设计模式是最好的选择的指南和一个例子,我已经读过关于Creational Design Pattern Factory及其不同风格的文章,但我还不明白这是如何实现的
这是我的方法之一:
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();
}
}
}
}
但是,我认为这不是一个正确的答案,在返回Dto时强制转换Dto,我不喜欢Factory类中的对象泛型类型。有没有更好的方法来改进这种方法使用任何创造性的设计模式?问候 没有办法(至少对我来说没有办法)将用于处理特定类型的实现与该类型解耦。对于处理EmployeeDto
类型的存储库来说,直接了解该类型似乎很自然
不确定您的设计从更广泛的角度来看如何,但可能您缺少的是一个通用接口,因此您的客户端没有太多耦合?例如,类似这样的内容:
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;
}
public cladd EmployeeDto()
{
public int Employee Id {get;set;}
public string EmployeeName {get;set;}
}
public interface IRepository<T>
{
IEnumerable<T> GetAll<T>();
T Get<T>(int id);
}
公共接口IRepository
{
IEnumerable GetAll();
T Get(int-id);
}
这意味着,您不会像示例中那样使用GetEmployeeDto
方法,而是使用常规的GetDto
方法,甚至Get
。这让我想到了另一个提示:遵循DDD相关模式,存储库应该返回一个准备好使用的域对象,而不是DTO
这样,您的域层就可以使用存储库并专注于域逻辑,而不是被迫处理转换。正如在评论中提到的,无论如何,配置一个自动映射库来为您实现这一点是很好的。但是,即使使用automapper,所有技术细节都应该隐藏在域层之外。没有办法(至少对我来说没有办法)将用于处理特定类型的实现与该类型解耦。对于处理EmployeeDto
类型的存储库来说,直接了解该类型似乎很自然
不确定您的设计从更广泛的角度来看如何,但可能您缺少的是一个通用接口,因此您的客户端没有太多耦合?例如,类似这样的内容:
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;
}
public cladd EmployeeDto()
{
public int Employee Id {get;set;}
public string EmployeeName {get;set;}
}
public interface IRepository<T>
{
IEnumerable<T> GetAll<T>();
T Get<T>(int id);
}
公共接口IRepository
{
IEnumerable GetAll();
T Get(int-id);
}
这意味着,您不会像示例中那样使用GetEmployeeDto
方法,而是使用常规的GetDto
方法,甚至Get
。这让我想到了另一个提示:遵循DDD相关模式,存储库应该返回一个准备好使用的域对象,而不是DTO
这样,您的域层就可以使用存储库并专注于域逻辑,而不是被迫处理转换。正如在评论中提到的,无论如何,配置一个自动映射库来为您实现这一点是很好的。但是,即使使用automapper,所有的技术细节都应该隐藏在域层。新员工待办事项()有什么问题吗??我个人不会费心,只会使用automapper或类似工具,然后得到一个键入的结果<代码>地图(dto)。您使用单个方法和1或0个泛型参数提出的任何此类解决方案都需要强制转换,并且需要使用if语句或类似语句在内部检查类型。工厂如何知道要为哪个员工获取DTO?Hello@MarkSeemann!根据工厂模式,客户机(实例化类的方法)不应该创建对象,该责任应该委托给其他人(在本例中是工厂),这样创建逻辑就不会向客户机公开(这不重要)工厂将返回请求的对象。您好@TheGeneral!在返回时强制转换Dto可能是一种解决方案,类似于首先将结果分配到通用对象类型,然后将对象强制转换为所请求类型的Dto:return(EmployeeDto)Object;理解这一点,谢谢你的贡献。
new EmployeeDto()
有什么问题吗?我个人不想麻烦,只要使用auto mapper或类似工具,就可以得到一个键入的结果<代码>地图(dto)。您使用单个方法和1或0个泛型参数提出的任何此类解决方案都需要强制转换,并且需要使用if语句或类似语句在内部检查类型。工厂如何知道要为哪个员工获取DTO?Hello@MarkSeemann!根据工厂模式,客户机(实例化类的方法)不应该创建对象,该责任应该委托给其他人(在本例中是工厂),这样创建