获取ASP.NET MVC 4中按名称给出的方法的属性

时间:2012-10-25 08:33:39

标签: c# asp.net-mvc reflection ravendb

我正在使用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这个名字给出的方法呢?

2 个答案:

答案 0 :(得分: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();
}

答案 1 :(得分:1)

为什么不让DataAccess属性继承自ActionFilterAttribute,以便将ActionExecuting / Executed方法放在属性而不是Controller上?

Example of how to do it with NHibernate使用动作过滤器在基本控制器上设置会话。它是使用NHibernate完成的,但非常类似于你需要做的事情,它是由Ayende编写的,他是我相信的RavenDB作者之一。