1

我有以下全局过滤器,ISiteValidation 和 ICacheService 通过 Windsor 容器注入并设置为 Transient,因此容器不会自动处理依赖项。当站点投入生产时,这将导致资源问题。那么人们如何正确处理注入过滤器的资源呢?这两个接口都是 IDisposable 但当操作过滤器超出范围时永远不会调用 Dispose 并且容器将继续保留实现。

public class SiteValidationAttribute : ActionFilterAttribute
{
    public ISiteValidation SiteValidation { get; set; }
    public ICacheService CacheService { get; set; }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (filterContext.RequestContext.HttpContext.Request.Url != null)
        {
            string host = filterContext.RequestContext.HttpContext.Request.Url.Host;
            try
            {
                string siteId = CacheService.Get("SiteId",
                                                 () =>
                                                 SiteValidation.GetSiteId(
                                                     host));
                var siteIdCookie = new HttpCookie("_site") {Value = siteId};
                filterContext.RequestContext.HttpContext.Response.Cookies.Add(siteIdCookie);
            }
            catch (Exception)
            {
                throw new HttpException(404, String.Format("This site'{0}' was not found", host));
            }
        }

        base.OnActionExecuted(filterContext);
    }
}
4

1 回答 1

6

属性由 CLR 根据请求创建:

如果要构造属性对象,则必须调用 GetCustomAttributes 或 GetCustomAttribute。每次调用其中一个方法时,它都会构造指定属性类型的新实例,并根据代码中指定的值设置每个实例的字段和属性。

这意味着它们不受任何 IoC 容器的控制。系统中唯一可以处理它们的部分是调用GetCustomAttribute或的部分GetCustomAttributes。但是没有什么是明确地这样做的。因此,属性不应该是一次性的。

幸运的是,还有另一种方法。不要为过滤器使用属性,而是在需要时实现一个IActionFilter并注册一个IFilterProvider返回过滤器的新实例(由您的 IoC 容器创建)的实例。

看看它是如何使用 Ninject 完成的;同样的方法应该可以移植到温莎。

https://github.com/ninject/ninject.web.mvc/tree/master/mvc3/src/Ninject.Web.Mvc/Filter

于 2012-08-07T13:27:41.283 回答