在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功能。