ActionFilterAttributes是否跨线程重用? 这是如何工作的?
我一直在用下面的代码进行一些testing,试着研究ActionFilterAttributes的工作方式:
public class TestAttribute : ActionFilterAttribute { private string _privateValue; public string PublicValue { get; set; } public override void OnActionExecuting(ActionExecutingContext filterContext) { _privateValue = DateTime.Now.ToString(); base.OnActionExecuting(filterContext); } }
当我在两个并行线程上运行上述代码时,_privateValue字段变得混乱。 但是,PublicValue属性不会混淆。
它看起来像ActionFilterAttributes跨线程重用,但新实例创build取决于指定给公共属性的常量。 我对么?
我在哪里可以find这方面的信息?
这将取决于ASP.NET MVC的版本,但不应将实例状态存储在将在不同方法之间重用的操作筛选器中。 下面是一个例子,来自ASP.NET MVC 3中的一个重大变化 :
在以前版本的ASP.NET MVC中,除less数情况外,每个请求都创build操作filter。 这种行为从来不是一个保证的行为,而只是一个实现细节,而filter的合同就是把它们看作是无状态的。 在ASP.NET MVC 3中,filter被更积极地caching。 因此,任何不正确地存储实例状态的自定义操作filter都可能被破坏。
这基本上意味着动作filter的同一个实例可以重用于不同的动作,如果你已经存储了实例状态,它可能会中断。
就代码而言,这意味着你绝对不应该写这样的动作filter:
public class TestAttribute : ActionFilterAttribute { private string _privateValue; public override void OnActionExecuting(ActionExecutingContext filterContext) { _privateValue = ... some calculation } public override void OnActionExecuted(ActionExecutedContext filterContext) { // use _privateValue here } }
但你应该这样写:
public class TestAttribute : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { var privateValue = ... some calculation filterContext.HttpContext.Items["__private_value__"] = privateValue; } public override void OnActionExecuted(ActionExecutedContext filterContext) { var privateValue = filterContext.HttpContext.Items["__private_value__"]; // use privateValue safely here } }