在Suteki.Shop中對於Filter的使用上提供了兩種方式,一種是從FilterAttribute(抽象類屬性)以及 接口 IActionFilter和 IResultFilter中繼承並實現。另一種是我們經常提到的從 ActionFilterAttribute 上繼承方式來實現自己的ActionFilter。首先看一下第一種,同時它也是該項 目中被Action廣泛使用的方式, 下面是類圖:
當然圖中最核心的 當屬FilterUsingAttribute,它同時繼承了 FilterAttribute類和 IAuthorizationFilter, IActionFilter, IResultFilter這三個接口,所以其所實現的功能與MVC中所定義的 ActionFilterAttribute如出一轍。同時,下面是其核心代碼:
public class FilterUsingAttribute : FilterAttribute, IAuthorizationFilter, IActionFilter, IResultFilter
{
private readonly Type filterType;
private object instantiatedFilter;
public FilterUsingAttribute(Type filterType)
{
if (!IsFilterType(filterType))
{
throw new InvalidOperationException("Type '{0}' is not valid within the FilterUsing
attribute as it is not a filter type.".With(filterType.Name));
}
this.filterType = filterType;
}
private bool IsFilterType(Type type)
{
return typeof (IAuthorizationFilter).IsAssignableFrom(type)
|| typeof (IActionFilter).IsAssignableFrom(type)
|| typeof(IResultFilter).IsAssignableFrom (type);
}
public Type FilterType
{
get { return filterType; }
}
private T GetFilter<T>() where T : class
{
if (instantiatedFilter == null)
{
instantiatedFilter = ServiceLocator.Current.GetInstance(filterType);
}
return instantiatedFilter as T;
}
private void ExecuteFilterWhenItIs<TFilter> (Action<TFilter> action) where TFilter :class
{
var filter = GetFilter<TFilter>();
if(filter != null)
{
action(filter);
}
}
public void OnAuthorization(AuthorizationContext filterContext)
{
ExecuteFilterWhenItIs<IAuthorizationFilter>(f => f.OnAuthorization (filterContext));
}
public void OnActionExecuting(ActionExecutingContext filterContext)
{
ExecuteFilterWhenItIs<IActionFilter>(f => f.OnActionExecuting(filterContext));
}
public void OnActionExecuted (ActionExecutedContext filterContext)
{
ExecuteFilterWhenItIs<IActionFilter>(f => f.OnActionExecuted(filterContext));
}
public void OnResultExecuting(ResultExecutingContext filterContext)
{
ExecuteFilterWhenItIs<IResultFilter>(f => f.OnResultExecuting (filterContext));
}
public void OnResultExecuted(ResultExecutedContext filterContext)
{
ExecuteFilterWhenItIs<IResultFilter>(f => f.OnResultExecuted(filterContext));
}
}
在上面的OnAction..和 OnResult..事件中,都調用了ExecuteFilterWhenItIs這個泛型方法,而該方法的作用是對泛型約束中使 用到的相應IActionFilter進行操作,而獲取相應的Filter實例的工作就交給了GetFilter<T>()方 法,因為該方法使用IOC方式將filterType以服務組件的方式進行創建,所以我們會看到在 ContainerBuilder(Suteki.Shop\ContainerBuilder.cs)中有如下代碼,注意最後一行:
container.Register(
Component.For<IUnitOfWorkManager> ().ImplementedBy<LinqToSqlUnitOfWorkManager>().LifeStyle.Transient,
Component.For<IFormsAuthentication> ().ImplementedBy<FormsAuthenticationWrapper>(),
Component.For<IServiceLocator>().Instance(new WindsorServiceLocator (container)),
看來其最終會使用Castle框架所提供的IOC功能。