首先,感谢链接到帖子“让你的控制器节食:GETs and queries”。我的代码示例使用其中的类型。
我的解决方案还涉及使用动作过滤器作为注入通用行为的点。
控制器很简单,看起来像@Kambiz Shahim 的:
[QueryFilter]
public class ConferenceController : Controller
{
public ActionResult Index(IndexQuery query)
{
return View();
}
public ViewResult Show(ShowQuery query)
{
return View();
}
public ActionResult Edit(EditQuery query)
{
return View();
}
}
工作时QueryFilterAttribute
我意识到,IMediator
它的实现可以省略。知道查询类型就足以解析IQueryHandler<,>
via IoC 的实例。
在我的示例中,使用了Castle Windsor和“服务定位器”模式的实现。
public class QueryFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
object query = filterContext.ActionParameters["query"];
Type queryType = query.GetType();
Type modelType = queryType.GetInterfaces()[0].GetGenericArguments()[0];
var handlerType = typeof(IQueryHandler<,>).MakeGenericType(queryType, modelType);
// Here you should resolve your IQueryHandler<,> using IoC
// 'Service Locator' pattern is used as quick-and-dirty solution to show that code works.
var handler = ComponentLocator.GetComponent(handlerType) as IQueryHandler;
var model = handler.Handle(query);
filterContext.Controller.ViewData.Model = model;
}
}
IQueryHandler
添加接口以避免使用反射
/// <summary>
/// All derived handlers can be refactored using generics. But in the real world handling logic can be completely different.
/// </summary>
/// <typeparam name="TQuery">The type of the query.</typeparam>
/// <typeparam name="TResponse">The type of the response.</typeparam>
public interface IQueryHandler<in TQuery, out TResponse> : IQueryHandler
where TQuery : IQuery<TResponse>
{
TResponse Handle(TQuery query);
}
/// <summary>
/// This interface is used in order to invoke 'Handle' for any query type.
/// </summary>
public interface IQueryHandler
{
object Handle(object query);
}
/// <summary>
/// Implements 'Handle' of 'IQueryHandler' interface explicitly to restrict its invocation.
/// </summary>
/// <typeparam name="TQuery">The type of the query.</typeparam>
/// <typeparam name="TResponse">The type of the response.</typeparam>
public abstract class QueryHandlerBase<TQuery, TResponse> : IQueryHandler<TQuery, TResponse>
where TQuery : IQuery<TResponse>
{
public abstract TResponse Handle(TQuery query);
object IQueryHandler.Handle(object query)
{
return Handle((TQuery)query);
}
}
类型应该被注册in Global.asax.cs
container.Register(Component.For<ISession>().ImplementedBy<FakeSession>());
container.Register(
Classes.FromThisAssembly()
.BasedOn(typeof(IQueryHandler<,>))
.WithService.Base()
.LifestylePerWebRequest());
在 github 上有一个gist 链接,其中包含所有代码。