循環参照は、サービスレイヤがコントローラのModelStateとServiceレイヤに依存するコントローラに依存しているという事実と関係があります。
有効にするには、検証レイヤーを書き直す必要がありました。ここに私がしたことがあります。
以下のような一般的なバリインタフェース定義します。私たちは、明らかに、検証の状態を定義し、ValidationStateのインスタンスを返すことができるようにしたい
public interface IValidator<TEntity>
{
ValidationState Validate(TEntity entity);
}
を。
public class ValidationState
{
private readonly ValidationErrorCollection _errors;
public ValidationErrorCollection Errors
{
get
{
return _errors;
}
}
public bool IsValid
{
get
{
return Errors.Count == 0;
}
}
public ValidationState()
{
_errors = new ValidationErrorCollection();
}
}
私たちには厳密に型指定されたエラーコレクションがありますが、これもまた定義する必要があることに注意してください。コレクションは、検証するエンティティのプロパティ名とそれに関連付けられたエラーメッセージを含むValidationErrorオブジェクトで構成されます。これは、標準のModelStateインターフェイスにちょうど従います。
public class ValidationError
{
private string _property;
private string _message;
public string Property
{
get
{
return _property;
}
private set
{
_property = value;
}
}
public string Message
{
get
{
return _message;
}
private set
{
_message = value;
}
}
public ValidationError(string property, string message)
{
Property = property;
Message = message;
}
}
これの残りはのStructureMap魔法である:ここ
public class ValidationErrorCollection : Collection<ValidationError>
{
public void Add(string property, string message)
{
Add(new ValidationError(property, message));
}
}
とValidationErrorをどのように見えるかです。検証オブジェクトを探し、エンティティを検証する検証サービスレイヤーを作成する必要があります。バリデーションサービスを使用している誰かがStructureMapの存在を完全に意識しないようにしたいので、私はこのためのインターフェースを定義したいと思います。また、私はObjectFactory.GetInstance()をブートストラップロジック以外の場所に振りかけるのは悪い考えだと思います。それを集中管理することは、メンテナンス性を保証する良い方法です。とにかく、私はここでDecoratorパターンを使用します。
public interface IValidationService
{
ValidationState Validate<TEntity>(TEntity entity);
}
をそして、我々は最終的にそれを実装しています
public class ValidationService : IValidationService
{
#region IValidationService Members
public IValidator<TEntity> GetValidatorFor<TEntity>(TEntity entity)
{
return ObjectFactory.GetInstance<IValidator<TEntity>>();
}
public ValidationState Validate<TEntity>(TEntity entity)
{
IValidator<TEntity> validator = GetValidatorFor(entity);
if (validator == null)
{
throw new Exception("Cannot locate validator");
}
return validator.Validate(entity);
}
#endregion
}
私は私のコントローラで検証サービスを使用しているつもりです。それをサービスレイヤーに移動し、StructureMapでプロパティーインジェクションを使用してコントローラーのModelStateのインスタンスをサービスレイヤーに挿入することができますが、サービスレイヤーをModelStateと結合したくない場合があります。別の検証手法を使用する場合はどうなりますか?これが私がむしろコントローラーに入れている理由です。私のコントローラは以下のようになります:
public class PostController : Controller
{
private IEntityService<Post> _service = null;
private IValidationService _validationService = null;
public PostController(IEntityService<Post> service, IValidationService validationService)
{
_service = service;
_validationService = validationService;
}
}
ここで私は私のサービス層とバリデーションサービスインスタンスをStructureMapを使って注入しています。したがって、両方をStructureMapレジストリに登録する必要があります。
ForRequestedType<IValidationService>()
.TheDefaultIsConcreteType<ValidationService>();
ForRequestedType<IValidator<Post>>()
.TheDefaultIsConcreteType<PostValidator>();
これはそれです。 PostValidatorの実装方法は示していませんが、単にIValidatorインターフェイスを実装し、Validate()メソッドで検証ロジックを定義するだけです。これで済むのは、バリデーションサービスインスタンスを呼び出してバリデータを取得し、エンティティでvalidateメソッドを呼び出し、ModelStateにエラーを書き込むことです。
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create([Bind(Exclude = "PostId")] Post post)
{
ValidationState vst = _validationService.Validate<Post>(post);
if (!vst.IsValid)
{
foreach (ValidationError error in vst.Errors)
{
this.ModelState.AddModelError(error.Property, error.Message);
}
return View(post);
}
...
}
希望私はこれでこの:)
のようなものであることは一般的なタイプですクラスオブジェクトではありません。 Visual Studioでは単純に黒です。私はTEntityを使用して、単に検証したいオブジェクトの型を渡します。 私はコントローラの検証についてあなたに同意します。それを検証するためのより良い方法が見つからず、柔軟性が増しました。このようにして、私は自分のエンティティバリデーター内で望むバリデーションフレームワークを使うことができます。 –
今、私はそれほど心配していませんが、アダプタパターンを使用してModelState用のアダプタを作成することができます。したがって、本質的にあなたのエンティティを検証し、ValidationStateオブジェクトを取得し、アダプタを使用してModelStateに変換します。それを十分に抽象化したら、StructureMapを使用して選択したアダプタを注入することができます。あなたのコントローラーでどれくらいうまくつながっているかは分かりませんが、かなりうまくデカップルできると確信しています。このようにして、あなたの検証サービスは、あなたのビジネスモデル/エンティティまたはサービス層内でおそらく使用される可能性があります。私はこれで何かできるかどうかを見ていきます。 –
私はこれに続いて、http://www.asp.net/Learn/mvc/tutorial-38-cs.aspxを見ていました。もともと、私はサービスレイヤーをMVCにあまりにも強く結びつけると考えていたので、このオプションを割り引いたのですが、分かりましたが、私のプロジェクトを進めるために、悪い束のように見えます。私は非常にゆるい代替案を見つけたいと思っています。あなたが何かを思い付くなら、私はロイドフィリップスで電子メールをドロップしてください。xtra dot co dot nz。 よろしくお願いいたします。 ロイド –