5

次のクラスがあるとします。

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;
}

...そして、サービス境界(WCF)を越えてカメラ情報を転送するためのDTO(たとえば、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; }
}

Cameraこれで、データを公開するためのメソッドを追加できます。

class Camera
{
    // blah blah

    public CameraData ToData()
    {
        var regionOfInterestData = regionOfInterest.ToData();

        return new CameraData()
        {
            Exposure = exposure,
            Brightness = brightness,
            Contrast = contrast,
            RegionOfInterest = regionOfInterestData
        };
    }
}

または、カメラがデータを公開するために特別なIReporterを渡す必要があるメソッドを作成できます。これにより、Contractsレイヤーへの依存関係が削除されます(CameraはCameraDataについて知る必要がなくなります)。

class Camera
{
    // beep beep I'm a jeep

    public void ExposeToReporter(IReporter reporter)
    {
        reporter.GetCameraInfo(exposure, brightness, contrast, regionOfInterest);
    }
}

だから私はどちらをすべきですか?私は2番目の方が好きですが、IReporterにCameraDataフィールド(によって変更されるGetCameraInfo())が必要であり、これは奇妙に感じます。また、さらに良い解決策があれば、私と共有してください!私はまだオブジェクト指向の初心者です。

4

5 に答える 5

13

DTOはサービスまたはアプリケーションに固有であるのに対し、ドメインモデルは「最も内側の」レイヤーであり、依存関係がないため、一般的にはノーと言います。DTOは、ドメインモデル以外の実装の詳細であるため、ドメインモデルがDTOについて知るための抽象化を破っています。

これについてAutoMapperを検討することを検討しましたか?そうすることで、コードの記述が大幅に減ることになります。この場合、私はあなたが簡単に逃げることができると思います:

Mapper.CreateMap<RegionOfInterest, RegionOfInterestData>();
Mapper.CreateMap<Camera, CameraData>();

そして後で:

CameraData cd = Mapper.Map<Camera, CameraData>(camera);

これにより、コードのチャーンが減少するだけでなく、マッピングコードが独自の「マッピングレイヤー」に区分されます。これらのマッピングを登録する1つまたは複数のモジュールがあり、実際にDTOを使用するアセンブリに配置できます。

そしてもちろん、実際のマッピングを簡素化するために、いつでも拡張メソッドを作成できます。

public static class CameraExtensions
{
    public static CameraData ToCameraData(this Camera camera)
    {
        return Mapper.Map<Camera, CameraData>(camera);
    }
}

これにより、全体を書くのと同じくらい簡単になりますcamera.ToCameraData()が、ドメインオブジェクト( )とDTO()の間に強い依存関係作成する必要はありません。基本的に、元のバージョンの使いやすさはすべて揃っていますが、カップリングはありません。CameraCameraData

公開されていないCameraDataプライベートデータからオブジェクトを作成しようとしているためにこれらの依存関係を作成している場合、私の即時の反応は、この設計について何かが正しくないということです。オブジェクトCameraの読み取り専用プロパティを公開してみませんか?Cameraとにかく、メソッドを介して外の世界にそれらへのアクセスを許可しているToData場合は、明らかにこの情報を隠しているのではなく、アクセスするのがより面倒になっているだけです。

3か月後に別の種類のDTOが必要だと判断した場合はどうなりますか?Camera新しいユースケースをサポートするたびに、ドメイン中心のオブジェクトを変更する必要はありません。私の意見では、マッパーが必要な属性にアクセスできるように、クラスに読み取り専用のパブリックプロパティをいくつか配置することをお勧めします。

于 2010-04-05T22:46:04.203 に答える
4

私は通常、このように取り組んでいます。ビジネスオブジェクトは、ビジネスレイヤーDLLでは「純粋」です。次に、WCFレイヤーにCamera.MapToCameraDataContract拡張メソッドを追加します。また、通常、サービスレイヤーにも逆拡張メソッド(CameraDataContract.MapToCamera)があります。

つまり、基本的には最初の方法ですが、ToDataメソッドは、WCFレイヤーだけが知っている拡張メソッドです。

于 2010-04-05T22:30:18.873 に答える
0

最初の(DTOの公開)は私よりもはるかに望ましいです。それはより単純で、より速く実行され、理解と維持がより簡単になります。DTOは実際にはデータベースオブジェクトに依存していないため、依存関係を減らすという目的を簡単に達成できます。

于 2010-04-05T22:50:12.477 に答える
0

DTO自体にto/fromメソッドを配置しました。

[DataContract]
public class CameraData
{
    ...
    public Camera ToCamera() { ... }

    public static CameraData FromCamera(Camera c) { ... }
}

そうすれば、私のドメインオブジェクトは私のDTOについて知る必要がありません。

于 2010-04-05T22:52:15.863 に答える
0

あなたのサービスはWCFからWCFですか?

その場合は、ビジネスオブジェクトをDTOとして使用することを選択できます(ビジネスオブジェクトが永続性を認識しない限り)。これを行った場合は、CameraDataクラスをICameraDataインターフェイスに変更し、CameraにICameraDataを実装させることをお勧めします。インターフェイスに属性(DataContractなど)を保持します。

次に、クライアントからサーバーにビジネスオブジェクトを渡すことができます。特にクライアント側またはサーバー側のロジックに注意してください。

ここにある私のブログ投稿の最初の画像は、ビジネスオブジェクトオブジェクトをクライアント側で再利用するのがいかに簡単かを示しています(ダイアログボックスは、「サービス参照の追加」を実行したときに表示されるものです)。ブログ投稿には、bizオブジェクトを再利用する際の落とし穴の1つに関する情報が含まれています。

ExposeToReporterで何を達成しようとしているのかわかりませんが、正しくありません。個人的には、ICameraDataパラメーターを受け取るIReporterにメソッドを配置し、その中にレポーターの詳細を設定します。

このようなもののための素晴らしい学習ソースはdnrtvです。タイトルにWCFが含まれているものすべてをご覧ください。特に、MiguelCastroによるExtremeWCFをご覧ください。

于 2010-04-05T23:03:56.923 に答える