我有Ninject,Ninject.Extensions.Interception和Ninject.Extensions.Interception.DynamicProxy通过NuGet安装,我有以下模块
public class InterceptAllModule : InterceptionModule { public override void Load() { Kernel.Intercept(p => p.Request.Service.Name.EndsWith("Controller")).With(new TimingInterceptor()); } }
TimingInterceptor在哪里
public class TimingInterceptor : SimpleInterceptor { readonly Stopwatch _stopwatch = new Stopwatch(); protected override void BeforeInvoke(IInvocation invocation) { _stopwatch.Start(); } protected override void AfterInvoke(IInvocation invocation) { _stopwatch.Stop(); string message = string.Format("[Execution of {0} took {1}.]",invocation.Request.Method,_stopwatch.Elapsed); Log.Info(message + "\n"); _stopwatch.Reset(); } }
现在,当我尝试用ninject内核挂接模块,并运行我的网站
var kernel = new StandardKernel(new InterceptAllModule());
Cannot instantiate proxy of class: MyApiController.
有经验的人可以指出我在做错什么吗?谢谢。
解决方法
所以使用你的代码和Remo的优点,需要动作方法是虚拟的,并放置一个空的默认构造函数(只是安抚动态代理,保持你的其他构造函数仍然)我已经有动作过滤器和拦截方法工作。
我会说,因为它的代码将拦截ApiController上的潜在的不必要的方法,所以你可能还需要放置一些代码来过滤这些例子。执行同步和处理。
我唯一的其他观点就是表演。巨大的免责声明这些只是非常基本的测试(每次使用动作过滤器方法来记录统计信息),我邀请你做自己的(!)…但是使用DynamicProxy拦截器,我得到的时间约为4毫秒获得请求
[Execution of Get took 00:00:00.0046615.] [Execution of Get took 00:00:00.0041988.] [Execution of Get took 00:00:00.0039383.]
评论拦截代码并使用Action过滤器,我获得了毫秒级的性能:
[Execution of Get took 00:00:00.0001146.] [Execution of Get took 00:00:00.0001116.] [Execution of Get took 00:00:00.0001364.]
这取决于你是否真的是一个问题或疑虑,但我以为我会指出这一点。
以前的回应
你使用ActionFilters吗?这是AOP对MVC动作的自然延伸点。
如果您对控制器上的实际操作以外的方法感兴趣,那么我会明白,但我以为我会发布一个建议。
灵感来自Are ActionFilterAttributes reused across threads? How does that work?和Measure Time Invoking MVC 4 Controller Actions。
更新以显示方法标记时计时器的排除。来自核心WebApi框架的灵感来自AllowAnonymousAttribute和AuthorizeAttribute
在全局注册,以便所有操作由此进行监视:
GlobalConfiguration.Configuration.Filters.Add(new TimingActionFilter());
然后:
public class TimingActionFilter : ActionFilterAttribute { private const string Key = "__action_duration__"; public override void OnActionExecuting(HttpActionContext actionContext) { if (SkipLogging(actionContext)) { return; } var stopWatch = new Stopwatch(); actionContext.Request.Properties[Key] = stopWatch; stopWatch.Start(); } public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) { if (!actionExecutedContext.Request.Properties.ContainsKey(Key)) { return; } var stopWatch = actionExecutedContext.Request.Properties[Key] as Stopwatch; if(stopWatch != null) { stopWatch.Stop(); var actionName = actionExecutedContext.ActionContext.ActionDescriptor.ActionName; Debug.Print(string.Format("[Execution of {0} took {1}.]",actionName,stopWatch.Elapsed)); } } private static bool SkipLogging(HttpActionContext actionContext) { return actionContext.ActionDescriptor.GetCustomAttributes<NoLogAttribute>().Any() || actionContext.ControllerContext.ControllerDescriptor.GetCustomAttributes<NoLogAttribute>().Any(); } }
和
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class,Inherited = true)] public class NoLogAttribute : Attribute { }
现在可以使用以下方式排除全局过滤器:
public class ExampleController : ApiController { // GET api/example [NoLog] public Example Get() { // } }