假设我有以下课程:
class Camera
{
public Camera(
double exposure,
double brightness,
double contrast,
RegionOfInterest regionOfInterest)
{
this.exposure = exposure;
this.brightness = brightness;
this.contrast = contrast;
this.regionOfInterest = regionOfInterest;
}
public void ConfigureAcquisitionFifo(IAcquisitionFifo acquisitionFifo)
{
// do stuff to the acquisition FIFO
}
readonly double exposure;
readonly double brightness;
readonly double contrast;
readonly RegionOfInterest regionOfInterest;
}
Run Code Online (Sandbox Code Playgroud)
...和DTO在服务边界(WCF)上传输摄像头信息,比如在WinForms/WPF/Web应用程序中查看:
using System.Runtime.Serialization;
[DataContract]
public class CameraData
{
[DataMember]
public double Exposure { get; set; }
[DataMember]
public double Brightness { get; set; }
[DataMember]
public double Contrast { get; set; }
[DataMember]
public RegionOfInterestData RegionOfInterest { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
现在我可以添加一个方法Camera
来公开它的数据:
class Camera
{
// blah blah
public CameraData ToData()
{
var regionOfInterestData = regionOfInterest.ToData();
return new CameraData()
{
Exposure = exposure,
Brightness = brightness,
Contrast = contrast,
RegionOfInterest = regionOfInterestData
};
}
}
Run Code Online (Sandbox Code Playgroud)
或者,我可以创建一个方法,要求传入一个特殊的IReporter,让Camera公开其数据.这消除了对Contracts图层的依赖性(Camera不再需要了解CameraData):
class Camera
{
// beep beep I'm a jeep
public void ExposeToReporter(IReporter reporter)
{
reporter.GetCameraInfo(exposure, brightness, contrast, regionOfInterest);
}
}
Run Code Online (Sandbox Code Playgroud)
那我该怎么办?我更喜欢第二种,但它需要IReporter有一个CameraData字段(由其改变GetCameraInfo()
),这感觉很奇怪.此外,如果有更好的解决方案,请与我分享!我仍然是一个面向对象的新手.
Aar*_*ght 13
我一般会说没有,他们不应该,因为DTO的是特定的服务或应用程序,而该领域模型是你的"最里面的"层,应该没有依赖性.DTO的是什么实现细节等比域模型,因此,它打破了抽象为您的域模型,以了解他们.
你考虑过为AutoMapper看过吗?你最终会以这种方式编写更少的代码.在这种情况下,我认为你可以简单地逃脱:
Mapper.CreateMap<RegionOfInterest, RegionOfInterestData>();
Mapper.CreateMap<Camera, CameraData>();
Run Code Online (Sandbox Code Playgroud)
后来:
CameraData cd = Mapper.Map<Camera, CameraData>(camera);
Run Code Online (Sandbox Code Playgroud)
这不仅减少了代码流失,而且将映射代码划分到自己的"映射层"中 - 您有一个或多个模块可以注册这些映射,您可以将它们放在真正使用DTO的任何程序集中.
当然,您始终可以创建扩展方法来简化实际映射:
public static class CameraExtensions
{
public static CameraData ToCameraData(this Camera camera)
{
return Mapper.Map<Camera, CameraData>(camera);
}
}
Run Code Online (Sandbox Code Playgroud)
这使整个事情像写作一样简单camera.ToCameraData()
,但没有在域对象(Camera
)和DTO(CameraData
)之间创建硬依赖.您基本上拥有原始版本的所有易用性,但没有耦合.
如果您正在创建这些依赖项,因为您尝试从未公开公开的CameraData
私有Camera
数据创建对象,那么我的立即反应将是,这个设计并不完全正确.为什么不在Camera
对象上公开只读属性?无论如何,如果你通过这种ToData
方法让外界访问它们,那么你显然没有隐藏这些信息,你只是让它变得更加麻烦.
如果您决定在未来3个月内需要不同类型的DTO,该怎么办?Camera
每次要支持新用例时,都不必修改以域为中心的对象.在我看来,更好的是在类中放置一些只读的公共属性,以便映射器可以访问他们需要的属性.