考虑下面的代码(已经简化)。我有一个服务类,它返回一个特定DTO对象的列表,每个对象都实现自己的特定接口。在实际代码中,当我使用遗留代码时,通过迭代数据集来填充这些代码。
问题:
我们如何在不新建或使用服务定位器反模式的情况下创建/使用DTO?在Composition Root中组合一个空的DTO对象并通过构造函数将它注入Service类没有多大意义,因为我实际上在填充列表时使用DTO作为排序的临时变量。
在代码中,您可以看到我新推DTO的示例。但这感觉并不多 比我首先让DTO不实现接口更好。那么他们不应该实现接口,因此不要将DI与DTO一起使用吗?
public class Services : IServices
{
public IList<IDTO> GetDTOs()
{
...
List<IDTO> dtos = new List<IDTO>();
foreach (c in d)
{
DTO dto = new DTO();
dto.x = c.x;
dto.y = c.y;
dto.z = c.z;
dtos.Add(dto);
}
return dtos;
}
}
答案 0 :(得分:12)
DTO不需要由容器管理的生命周期;我只会new
他们。不要过度工程。
答案 1 :(得分:8)
我认为DTO不应该实现接口,因为它们不太可能实现会改变的行为。
他们也不应该注射。并非所有对象都应该是。我认为这是对new的适当调用:创建对象,使用它,让它超出范围并进行GC。
答案 2 :(得分:1)
看看AutoMapper。我同意@duffymo,我不会使用与DTO的接口。 AutoMapper是一个基于约定的对象对象映射器,它将为您创建和填充DTO。如果没有别的东西,它会为你节省很多打字。我一直在练习与DTO编写转换例程以及相关的拼写错误。我希望我能早点找到AutoMapper。在你的例子的情况下(我在名义上使用Order类型的“from”对象):
public class Services : IServices
{
public IList<DTO> GetDTOs()
{
...
Mapper.CreateMap<Order, DTO>(); // move map creation to startup routine
var dtos = new List<DTO>();
foreach (c in d)
{
dtos.Add( Mapper.Map<Order, DTO>(c));
}
return dtos;
}
}
或使用LINQ
public class Services : IServices
{
public IList<DTO> GetDTOs()
{
...
Mapper.CreateMap<Order, DTO>(); // move map creation to startup routine
return d.Select(c => Mapper.Map<Order, DTO>(c)).ToList();
}
}