1

我有以下全局過濾器,ISiteValidation和ICacheService通過Windsor容器注入,並設置爲Transient,因此容器不會自動處理依賴關係。這將在網站投入生產時導致資源問題。那麼,人們如何正確地處理注入到過濾器中的資源呢?兩個接口都是IDisposable,但Dispose在Action Filter超出範圍時不會被調用,並且容器將繼續保留實現。動作過濾器如何處置?

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); 
    } 
} 

回答

5

屬性由CLR按要求創建:

如果你想構建一個屬性對象,必須調用要麼 GetCustomAttributes或GetCustomAttribute。每次調用其中一個方法時,它將構造指定的 屬性類型的新實例,並根據代碼中指定的值設置實例的每個字段和屬性 。

這意味着它們不在任何IoC容器的控制範圍內。系統中唯一可以處理它們的部分是調用GetCustomAttributeGetCustomAttributes的系統。但沒有任何明確的做法。因此,屬性不應該是一次性的。

幸運的是,還有另外一種方法。不要將屬性用於過濾器,而是實施IActionFilter並註冊IFilterProvider,在需要時返回過濾器的新實例(由您的IoC容器創建)。

看看它是如何使用Ninject完成的;同樣的方法應該可以移植到溫莎。

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