33

標準のドメイン層エンティティがあります。

public class Product
{
    public int Id { get; set; }

    public string Name { get; set; }

    public decimal Price { get; set;}
}

ある種の検証属性が適用されています。

public class Product
{
    public int Id { get; set; }

    [NotEmpty, NotShorterThan10Characters, NotLongerThan100Characters]
    public string Name { get; set; }

    [NotLessThan0]
    public decimal Price { get; set;}
}

ご覧のとおり、これらの属性は完全に構成されています。ここで使用されている検証フレームワーク (NHibernate Validator、DataAnnotations、ValidationApplicationBlock、Castle Validator など) は重要ではありません。

クライアント レイヤーには、ドメイン エンティティ自体を使用せずに、ビュー レイヤーが使用する ViewModel (別名 DTO) にマップする標準的なセットアップもあります。

public class ProductViewModel
{
    public int Id { get; set; }

    public string Name { get; set; }

    public decimal Price { get; set;}
}

次に、クライアント/ビューでいくつかの基本的なプロパティ レベルの検証を実行できるようにしたいとしましょう。

これを行う唯一の方法は、ViewModel オブジェクトで検証定義を繰り返すことです。

public class ProductViewModel
{
    public int Id { get; set; }

    // validation attributes copied from Domain entity
    [NotEmpty, NotShorterThan10Characters, NotLongerThan100Characters]
    public string Name { get; set; }

    // validation attributes copied from Domain entity
    [NotLessThan0]
    public decimal Price { get; set;}
}

ViewModel (DTO) レイヤーでビジネス ロジック (プロパティ レベルの検証) を繰り返したので、これは明らかに満足のいくものではありません。

では、何ができるでしょうか?

AutoMapper のような自動化ツールを使用して Domain エンティティを ViewModel DTO にマップすると仮定すると、マップされたプロパティの検証ロジックを ViewModel に転送するのもクールではないでしょうか?

質問は次のとおりです。

1) これは良い考えですか?

2) もしそうなら、それはできますか? そうでない場合、代替手段は何ですか?

ご意見をお寄せいただきありがとうございます。

4

8 に答える 8

11

DataAnnotations をサポートするものを使用している場合は、メタデータ クラスを使用して検証属性を含めることができるはずです。

public class ProductMetadata 
{
    [NotEmpty, NotShorterThan10Characters, NotLongerThan100Characters]
    public string Name { get; set; }

    [NotLessThan0]
    public decimal Price { get; set;}
}

ドメイン エンティティと DTO の両方の MetadataTypeAttribute に追加します。

[MetadataType(typeof(ProductMetadata))]
public class Product

[MetadataType(typeof(ProductMetadata))]
public class ProductViewModel

これは、すべてのバリデーターですぐに使用できるわけではありません。同様のアプローチを実装するには、選択した検証フレームワークを拡張する必要がある場合があります。

于 2010-02-11T08:31:34.047 に答える
9

検証の目的は、アプリケーションに入力されるデータが特定の基準を満たしていることを確認することです。つまり、ここで特定したようなプロパティの制約を検証する唯一の場所は、アプリケーションからデータを受け入れる時点です。信頼できないソース (つまり、ユーザー)。

「お金のパターン」のようなものを使用して、検証をドメイン タイプ システムに昇格させ、意味のあるビュー モデルでこれらのドメイン タイプを使用できます。より複雑な検証がある場合 (つまり、単一のプロパティで表現されるよりも多くの知識を必要とするビジネス ルールを表現している場合)、これらは変更を適用するドメイン モデルのメソッドに属します。

つまり、データ検証属性をビュー モデルに配置し、ドメイン モデルには含めません。

于 2010-02-10T00:43:47.493 に答える
4

インターフェースを使って意図を表現してみませんか?例えば:

public interface IProductValidationAttributes {
    [NotEmpty, NotShorterThan10Characters, NotLongerThan100Characters]
    string Name { get; set; }

    [NotLessThan0]
    decimal Price { get; set;}
}
于 2010-01-16T01:52:17.293 に答える
4

AutoMapper はこれを自動的に実行できる可能性があることがわかりました。これが最良のシナリオです。

AutoMapper-users: 検証属性をビューモデルに転送しますか?
http://groups.google.com/group/automapper-users/browse_thread/thread/efa1d551e498311c/db4e7f6c93a77302?lnk=gst&q=validation#db4e7f6c93a77302

そこで提案された解決策を試すことはできませんでしたが、すぐに試すつもりです。

于 2010-02-20T11:06:23.087 に答える
1

私もしばらくこれを検討してきました。私はブラッドの返事を完全に理解しています。ただし、ドメインエンティティとビューモデルの両方に注釈を付けるのに適した別の検証フレームワークを使用したいとします。

私が紙の上で思いつくことができる唯一の解決策は、まだ属性で機能しますが、ビューモデルでミラーリングしているドメインエンティティのプロパティを「指す」別の属性を作成することです。次に例を示します。

// In UI as a view model.
public class UserRegistration {
  [ValidationDependency<Person>(x => x.FirstName)]
  public string FirstName { get; set; }

  [ValidationDependency<Person>(x => x.LastName)]
  public string LastName { get; set; }

  [ValidationDependency<Membership>(x => x.Username)]
  public string Username { get; set; }

  [ValidationDependency<Membership>(x => x.Password)]
  public string Password { get; set; }
}

xValのようなフレームワークは、この新しい属性を処理し、依存関係クラスのプロパティで検証属性を実行するように拡張できますが、ビューモデルのプロパティ値を使用します。これをもっと具体化する時間がなかっただけです。

何かご意見は?

于 2010-02-17T23:45:01.923 に答える
1

手書きのドメイン エンティティを使用する場合は、ドメイン エンティティを独自のアセンブリに配置し、クライアントとサーバーの両方で同じアセンブリを使用しないでください。同じ検証を再利用できます。

于 2010-02-16T15:55:42.120 に答える
0

まず第一に、「標準」ドメイン エンティティの概念はありません。私にとって、標準ドメインエンティティにはそもそもセッターがありません。そのアプローチをとれば、実際にドメインについて何かを伝える、より意味のある API を持つことができます。したがって、DTO を処理し、SetContactInfo、ChangePrice などのドメイン オブジェクトに対して直接実行できるコマンドを作成するアプリケーション サービスを使用できます。これらのそれぞれが ValidationException を発生させる可能性があり、これをサービスで収集して、ユーザー。単純な属性/プロパティ レベルの検証のために、dto のプロパティに属性を残すことができます。それ以外については、ドメインを参照してください。これが CRUD アプリケーションであっても、ドメイン エンティティをプレゼンテーション レイヤーに公開することは避けます。

于 2010-01-25T13:57:27.027 に答える