我创建了一个自定义Action Filter并将其与Ninject的BindFilter方法绑定:
public class ExtendModelAttribute : FilterAttribute {}
public class ExtendModelFilter : IActionFilter
{
private IKernel kernel;
public ExtendModelFilter(Func<IKernel> kernel)
{
this.kernel = kernel;
}
public void OnActionExecuted(ActionExecutedContext filterContext)
{
// TODO:
}
public void OnActionExecuting(ActionExecutingContext filterContext)
{
}
}
我像这样绑定我的过滤器:
kernel.BindFilter<ExtendModelFilter>(FilterScope.Action, 0).WhenActionMethodHas<ExtendModelAttribute>();
到目前为止,一切都很好。我想要完成的是:
[ExtendModel]
public ActionResult Index()
{
return View(new IndexModel());
}
我希望ExtendModel过滤器做的是确定使用什么类型的Model,然后找到正确的依赖项:
public interface IModelExtender<TModel> {
void Extend(TModel model);
}
public class IndexModelExtender : IModelExtender<IndexModel> {
public void Extend(IndexModel model)
{
// extend the model here with anything extra that is required
}
}
我不确定如何在动作过滤器中编写代码来获取IModelExtender的实例:
public void OnActionExecuted(ActionExecutedContext filterContext)
{
// TODO:
// I Need to look at the filterContext Model to determine which
// type of IModelExtender<T> to create:
// For Example, when [ExtendModel] is applied on the Index() method above
// then I need it to resolve to IndexModelExtender
}
也许我想要做的甚至不可能?由于我在编译时不知道T是什么,有什么办法可以做我想要的吗?
修改
以下是ModelExtender可能执行的操作的示例:
public class IndexModelExtender : IModelExtender<IndexModel>
{
public IndexModelExtender(IFooRepository fooRepository, IBarRepository barRepository)
{
// ...
}
public void Extend(IndexModel model)
{
model.SelectList1 = new SelectList(fooRepository.GetFoos(), "Description", "Id");
model.SelectList2 = new SelectList(barRepository.GetBars(), "Description", "Id");
}
}
我想在我的控制器中避免这样的代码:
public ActionResult Index()
{
var model = new IndexModel();
// populate select lists here
return View(model);
}
[HttpPost]
public ActionResult Index(IndexModel model)
{
if(!ModelState.IsValid ) {
// populate the same stuff here
}
}
答案 0 :(得分:4)
您必须使用反射,因为模型类型仅在运行时已知并且您的扩展器是通用的:
public class ExtendModelFilter : IActionFilter
{
public void OnActionExecuted(ActionExecutedContext filterContext)
{
object model = null;
if (filterContext.Result is ViewResultBase)
{
model = ((ViewResultBase)filterContext.Result).Model;
}
else if (filterContext.Result is JsonResult)
{
model = ((JsonResult)filterContext.Result).Data;
}
// TODO: you could continue with the else if here to take
// into account some other action results that have the notion of model
// like for example some custom action results that you might have written
if (model == null)
{
// we have no model => nothing to extend
return;
}
var extenderType = typeof(IModelExtender<>).MakeGenericType(model.GetType());
var extender = DependencyResolver.Current.GetService(extenderType);
var extend = extenderType.GetMethod("Extend");
extend.Invoke(extender, new[] { model });
}
public void OnActionExecuting(ActionExecutingContext filterContext)
{
}
}
您还会注意到我已经重构了自定义操作过滤器,以便使用当前依赖项解析程序并使其与NInject无关。如果您愿意,您当然可以保留IKernel
依赖关系。