代码改变世界

NHibernate Step By Step(4)-事件(Event)

2009-08-02 23:23  Clingingboy  阅读(1015)  评论(0编辑  收藏  举报

    除了拦截器,NH还有事件机制,与拦截器不同,这些事件全部与操作有关进行分拆,这其实是一件相当大的工作量,因为着session的每个操作都会有对应的事件,对使用者而言,灵活度则增加了.所以在NHibernate.Event命名空间下,命名了大量的事件监听接口与session操作相对应,在NHibernate.Action命名空间下继承自IExecutable的接口则对这些接口进行调用.

ListenerType枚举,列出了全部的事件类别

/// <summary>
/// Values for listener type property.
/// </summary>
public enum ListenerType
{
    /// <summary>Not allowed in Xml. It represents the default value when an explicit type is assigned.</summary>
    NotValidType,
    /// <summary>Xml value: auto-flush</summary>
    Autoflush,
    /// <summary>Xml value: merge</summary>
    Merge,
    /// <summary>Xml value: create</summary>
    Create,
    /// <summary>Xml value: create-onflush</summary>
    CreateOnFlush,
    /// <summary>Xml value: delete</summary>
    Delete,
    /// <summary>Xml value: dirty-check</summary>
    DirtyCheck,
    /// <summary>Xml value: evict</summary>
    Evict,
    /// <summary>Xml value: flush</summary>
    Flush,
    /// <summary>Xml value: flush-entity</summary>
    FlushEntity,
    /// <summary>Xml value: load</summary>
    Load,
    /// <summary>Xml value: load-collection</summary>
    LoadCollection,
    /// <summary>Xml value: lock</summary>
    Lock,
    /// <summary>Xml value: refresh</summary>
    Refresh,
    /// <summary>Xml value: replicate</summary>
    Replicate,
    /// <summary>Xml value: save-update</summary>
    SaveUpdate,
    /// <summary>Xml value: save</summary>
    Save,
    /// <summary>Xml value: pre-update</summary>
    PreUpdate,
    /// <summary>Xml value: update</summary>
    Update,
    /// <summary>Xml value: pre-load</summary>
    PreLoad,
    /// <summary>Xml value: pre-delete</summary>
    PreDelete,
    /// <summary>Xml value: pre-insert</summary>
    PreInsert,
    /// <summary>Xml value: pre-collection-recreate </summary>
    PreCollectionRecreate,
    /// <summary>Xml value: pre-collection-remove </summary>
    PreCollectionRemove,
    /// <summary>Xml value: pre-collection-update </summary>
    PreCollectionUpdate,
    /// <summary>Xml value: post-load</summary>
    PostLoad,
    /// <summary>Xml value: post-insert</summary>
    PostInsert,
    /// <summary>Xml value: post-update</summary>
    PostUpdate,
    /// <summary>Xml value: post-delete</summary>
    PostDelete,
    /// <summary>Xml value: post-commit-update</summary>
    PostCommitUpdate,
    /// <summary>Xml value: post-commit-insert</summary>
    PostCommitInsert,
    /// <summary>Xml value: post-commit-delete</summary>
    PostCommitDelete,
    /// <summary>Xml value: post-collection-recreate </summary>
    PostCollectionRecreate,
    /// <summary>Xml value: post-collection-remove </summary>
    PostCollectionRemove,
    /// <summary>Xml value: post-collection-update </summary>
    PostCollectionUpdate,
}

 

这一设计让人感觉到NH设计工作的繁重,与内部操作仅仅相连,修改一个操作的话就要为了这些特性而修改.可能这也是必要的工作吧.

还是贴些代码来的实在

public delegate void AssertionAction(PostUpdateEvent @event);
 
public class AssertOldStatePostListener : IPostUpdateEventListener
{
    private readonly AssertionAction assertionDelegate;

    public AssertOldStatePostListener(AssertionAction assertionDelegate)
    {
        this.assertionDelegate = assertionDelegate;
    }

    public const string LogMessage = "PostUpdateEvent called.";

    private static readonly ILog log = LogManager.GetLogger(typeof(AssertOldStatePostListener));

    public void OnPostUpdate(PostUpdateEvent @event)
    {
        log.Debug(LogMessage);
        assertionDelegate(@event);
    }
}

注意这里操作完成后将赋值的事件重新赋值了

[Test]
public void ImplicitFlush()
{
    ((SessionFactoryImpl) sessions).EventListeners.PostUpdateEventListeners = new IPostUpdateEventListener[]
                                                                                  {
                                                                                      new AssertOldStatePostListener(
                                                                                          eArgs =>
                                                                                          Assert.That(eArgs.OldState, Is.Not.Null))
                                                                                  };
    FillDb();
    using (var ls = new LogSpy(typeof (AssertOldStatePostListener)))
    {
        using (ISession s = OpenSession())
        {
            using (ITransaction tx = s.BeginTransaction())
            {
                IList<SimpleEntity> l = s.CreateCriteria<SimpleEntity>().List<SimpleEntity>();
                l[0].Description = "Modified";
                tx.Commit();
            }
        }
        Assert.That(ls.GetWholeLog(), Text.Contains(AssertOldStatePostListener.LogMessage));
    }

    DbCleanup();
    ((SessionFactoryImpl) sessions).EventListeners.PostUpdateEventListeners = new IPostUpdateEventListener[0];
}