2

ドメインイベントについて詳しく調べていますが、履歴上の理由から、エンティティの更新を永続化するためのアドバイスが必要です。私の例では、ユーザーエンティティとサインインを扱います。

    public class UserService
    {
        private UserRepository _repository;

        public UserService()
        {
            _repository = new UserRepository();
        }

        public User SignIn(string username, string password)
        {
            var user = _repository.FindByUsernameAndPassword(username, password);
            //As long as the found object is valid and an exception has not been thrown we can raise the event.
            user.LastLoginDate = DateTime.Now;
            user.SignIn();
            return user;
        }
    }

    public class User
    {
        public User(IEntityContract entityContract)
        {
            if (!entityContract.IsValid)
            {
                throw new EntityContractException;
            }
        }

        public Guid Id { get; set; }
        public string Username { get; set; }
        public string Password { get; set; }
        public DateTime LastLoginDate { get; set; }

        public void SignIn()
        {
            DomainEvent.Raise(new UserSignInEvent() {User = this});
        }
    }

    public class UserSignInEvent : IDomainEvent
    {
        public User User { get; set; }
    }


    public class UserSignInHandler : Handles<UserSignInEvent>
    {
        public void Handle(UserSignInEvent arguments)
        {
            //do the stuff
        }
    }

ですから、私がやっていることがあるところでは、UserオブジェクトLastLoginDateを更新し、歴史的な理由でユーザーがログインした日時をログに記録したいと思います。私の質問は、リポジトリとコンテキストの新しいインスタンスを作成して、ハンドラーに変更を保存するか、イベントに何かを渡すかです。これが私が今苦労していることです。

4

1 に答える 1

2

したがって、私が作業を行う場合は、UserオブジェクトLastLoginDateを更新し、履歴上の理由でユーザーがログインした日時をログに記録したいと思います。

最終ログイン日を覚えておくことは、ユーザー自身の関心事であるはずです。
あなたはすでに素晴らしい拡張ポイントを持っています-ユーザーはsignInメソッドを持っています。

私の質問は、リポジトリとコンテキストの新しいインスタンスを作成して、ハンドラーに変更を保存するか、イベントに何かを渡すかです。

ユーザーはエンティティフレームワークについて何も知らないはずです。
したがって、-User.Eventsも何も知らないはずです。
ドメインイベントハンドラーも知らないはずです。

「外部」(アプリケーション層など)に存在するハンドラーは、許可されています。
ただし、必要に応じてユーザーやイベントからではなく、他の場所からエンティティフレームワークのコンテキストを把握します。


私が見ているように、ここでのイベントはロギング機能にのみ必要です。

私はこのようなものを書くでしょう:

public class LoginService{
   private Users _users;
   public LoginService(Users users){
     _users = users;
   }         
   public User SignIn(string username, string password){
     var user = _users.ByUsernameAndPassword(username, password);
     user.SignIn();
     return user;
   }
 }

public class User{
   public DateTime LastLoginDate { get; set; }      
   public void SignIn(){
     LastLoginDate = DateTime.Now;
     Raise(new SignedIn(this));
   }
   public class SignedIn:DomainEvent<User>{
     public SignedIn(User user):base(user){}
   }
}

//outside of domain model
public class OnUserSignedIn:IEventHandler<User.SignedIn>{
  public void Handle(User.SignedIn e){
    var u=e.Source;
    var message="User {0} {1} logged in on {1}"
      .With(u.Name,u.LastName,u.LastLoginDate);
    Console.WriteLine(message);
  }
}

このコードの悪い点は、サービスメソッドがコマンドとクエリを同時に実行することです
(状態を変更して結果を返します)。

ユーザーがサインインしたことが通知される UserContextを導入することで、これを解決します。

これにより、サインインしたユーザーを返す必要がなくなり、
現在のユーザーにサービスを提供する責任がUserContextに移ります。

リポジトリとユーザーの更新について-エンティティフレームワークは、エンティティの状態の変化を追跡する方法を知っているほど賢いと確信しています。少なくともNHibernateでは-私がしているのはhttprequestが終了したときに変更をフラッシュすることだけです。

于 2011-05-11T21:39:47.617 に答える