2011-09-12 80 views
1

我将越来越多的面向方面的关注点移动到我的ASP.NET MVC网站的ActionFilters上。因此,我怀疑我的一些性能瓶颈可能已经转移到ActionFilters中,而没有看到它们的性能。我想挂钩MVC的ActionFilter创建过程来包装每个ActionFilter,以便我可以记录该ActionFilter的执行需要多长时间。如何包装所有性能监控的actionfilters?

到目前为止,我已经找到了下面的网络链接,提示如何开始,但不知道如何实际包装每个ActionFilter。

+0

我把我最后的代码在我的[博客](http://wp.me/p1sjyR-Q)使用@BernieWhite的答案。 –

回答

3

您应该从ControllerActionInvoker派生和新类,并重写GetFilters方法。在这种方法中,您应该创建一个诊断包装类的新实例,实现包装真实过滤器的相同接口(IActionFilter)。 GetFilters被称为InvokeAction方法的一部分(也可以重写),但GetFilters可能是最干净的。

另外你也可以尝试重写InvokeActionMethodWithFilters这是那里的行动过滤器实际上却再次调用,这可能是混乱的,但如果你刚刚添加的东西 等可确定:

protected override ActionExecutedContext InvokeActionMethodWithFilters(ControllerContext controllerContext, IList<IActionFilter> filters, ActionDescriptor actionDescriptor, IDictionary<string, object> parameters) 
{ 
    Stopwatch diagWatch = Stopwatch.StartNew(); 

    var context = base.InvokeActionMethodWithFilters(controllerContext, filters, actionDescriptor, parameters); 

    diagWatch.Stop(); 

    return context; 
} 

要实现ControllerActionInvoker类见:

public class DiagControllerActionInvoker : ControllerActionInvoker 
{ 
    protected override FilterInfo GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor) 
    { 
     FilterInfo baseFilters = base.GetFilters(controllerContext, actionDescriptor); 

     //Add new filters 
     //e.g. baseFilters.ActionFilters.Insert(0, actionFilter); 

     return baseFilters; 
    } 
} 

要实际指定您的自定义ControllerActionInvoker是叫你需要创建一个DefaultControllerFactory实现,如:

public class SiteControllerFactory : DefaultControllerFactory 
{ 
    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) 
    { 
     if (controllerType == null) 
     { 
      return null; 
     } 

     // Create controller class. Here. 
     IController controller = (IController)Activator.CreateInstance(controllerType) 

     if (typeof(Controller).IsAssignableFrom(controllerType)) 
     { 
      Controller controllerInstance = controller as Controller; 

      if (controllerInstance != null) 
      { 
       controllerInstance.ActionInvoker = new DiagControllerActionInvoker(); 
      } 
     } 

     return controller; 
    } 
} 

而像通过设置在一个应用程序代码如下所示:

ControllerBuilder.Current.SetControllerFactory(new SiteControllerFactory()); 
1
  1. 更简单的方法可能是写集成测试,以测量每个动作过滤器或组合的表现。
  2. MVC3中有全局动作过滤器;你可能想写性能属性,它会启动和停止计时器,并给你过滤器运行的总时间操作。
  3. 如果您希望分析整个生产环境中的应用程序,可以使用很多可用的商业产品DotTrace,Dynatrace等,这些产品可以为每次调用的打破成本提供细分。