2

ravendb用作存储后端。由于它使用unit of work模式,我需要打开会话、执行操作、保存结果和关闭会话。我想保持我的代码干净,并且不要在每个操作中显式调用会话打开和关闭,所以我将此代码放入OnActionExecutingOnActionExecuted方法中,如下所示:

    #region RavenDB's specifics

    public IDocumentSession DocumentSession { get; set; }

    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext.IsChildAction)
        {
            return;
        }

        this.DocumentSession = Storage.Instance.OpenSession();
        base.OnActionExecuting(filterContext);
    }

    protected override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (filterContext.IsChildAction)
        {
            return;
        }

        if (this.DocumentSession != null && filterContext.Exception == null)
        {
            this.DocumentSession.SaveChanges();
        }

        this.DocumentSession.Dispose();
        base.OnActionExecuted(filterContext);
    }

    #endregion

但是有些动作需要连接ravendb而不需要。所以我决定创建自定义属性并标记方法需要用它打开 DocumentSession。这是一个例子:

    //
    // GET: /Create

    [DataAccess]
    public ActionResult Create()
    {
        return View();
    }

我卡住了。我的计划是在OnActionExecuted方法中检索操作的属性,如果[DataAccess]存在,则打开DocumentSession.

在我可以通过语句OnActionExecuted检索操作名称(方法名称) 。filterContext.ActionDescriptor.ActionName但是如何使用反射检索给定类的方法属性?

我发现它可能是Attribute.GetCustomAttributes调用的,但我得到的最接近 - 我需要MemberInfo该方法的对象。但是我怎样才能得到这个MemberInfo名称给出的方法呢?

4

2 回答 2

4

如果您从 FilterAttribute 继承自定义属性,它将具有 OnActionExecuted 和 OnActionExecuting 方法。并且会在一般的 OnActionExecuted 和 OnActionExecuting 之前执行。

例子:

public class DataAccessAttribute: FilterAttribute, IActionFilter
{       

    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext.IsChildAction)
        {
            return;
        }
        var controller = (YourControllerType)filterContext.Controller;
        controller.DocumentSession = Storage.Instance.OpenSession();
    }

    public void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (filterContext.IsChildAction)
        {
            return;
        }
        var controller = (YourControllerType)filterContext.Controller;
        documentSession = controller.DocumentSession; 
        if (documentSession != null && filterContext.Exception == null)
        {
            documentSession.SaveChanges();
        }

        documentSession.Dispose();
}
于 2012-10-25T08:41:17.863 回答
1

为什么不让您的属性从ActionFilterAttributeDataAccess继承,这样您就可以将 ActionExecuting/Executed 方法放在属性上而不是控制器上?

如何通过使用操作过滤器在基本控制器上设置会话来使用 NHibernate 执行此操作的示例。它是使用 NHibernate 完成的,但与您需要做的非常相似,它是由我相信的 RavenDB 作者之一 Ayende 编写的。

于 2012-10-25T08:40:55.163 回答