Ninject在行动过滤器 [英] Ninject in an Action Filter

查看:124
本文介绍了Ninject在行动过滤器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个自定义操作过滤器和正与Ninject的BindFilter方法​​绑定吧:

 公共类ExtendModelAttribute:FilterAttribute {}公共类ExtendModelFilter:IActionFilter
{
    私人的iKernel内核;
    公共ExtendModelFilter(Func键<&的iKernel GT;内核)
    {
        this.kernel =内核;
    }    公共无效OnActionExecuted(ActionExecutedContext filterContext)
    {
        // 去做:
    }    公共无效OnActionExecuting(ActionExecutingContext filterContext)
    {
    }
}

我结合我的过滤器,像这样:

  kernel.BindFilter< ExtendModelFilter>(FilterScope.Action,0).WhenActionMethodHas< ExtendModelAttribute>();

一切到目前为止是伟大的工作。我想做到的是以下内容:

  [ExtendModel]
公众的ActionResult指数()
{
    返回查看(新IndexModel());
}

我想什么ExtendModel过滤做的是确定正在使用什么类型的模型,然后找到正确的依赖关系:

 公共接口IModelExtender<&的TModel GT; {
    无效扩展(的TModel模型);
}公共类IndexModelExtender:IModelExtender< IndexModel> {
    公共无效扩展(IndexModel模型)
    {
        //使用任何额外所需这里扩展模型
    }
}

我不知道如何写在行动过滤器code得到IModelExtender的一个实例:

 公共无效OnActionExecuted(ActionExecutedContext filterContext)
{
    // 去做:
    //我需要看filterContext模型,以确定哪些
    //类型IModelExtender&LT的; T>创造:
    //上述对于实施例中,当施加在索引[ExtendModel]()方法
    //那么我需要它来解析IndexModelExtender
}

也许我想要做的心不是'甚至可能吗?因为我不知道在编译时什么T是做什么,有什么办法做到我想要什么?

修改结果
这是一个什么样的ModelExtender可能会做一个例子:

 公共类IndexModelExtender:IModelExtender< IndexModel>
{
    公共IndexModelExtender(IFooRepository fooRepository,IBarRepository barRepository)
     {
        // ...
     }     公共无效扩展(IndexModel模型)
     {
         model.SelectList1 =新的SelectList(fooRepository.GetFoos(),描述,ID);
         model.SelectList2 =新的SelectList(barRepository.GetBars(),描述,ID);
     }
}

我想避免code像这样在我的控制器:

 公众的ActionResult指数()
 {
     VAR模型=新IndexModel();
     //填充选择列表在这里
     返回查看(模型);
 } [HttpPost]
 公众的ActionResult指数(IndexModel模型)
 {
     如果(!ModelState.IsValid){
        //此处填写同样的东西
     }
  }


解决方案

您将不得不使用反射因为模型类型是在运行时才知道,你的扩展是通用的:

 公共类ExtendModelFilter:IActionFilter
{
    公共无效OnActionExecuted(ActionExecutedContext filterContext)
    {
        对象模型= NULL;
        如果(filterContext.Result是ViewResultBase)
        {
            模型=((ViewResultBase)filterContext.Result)。型号;
        }
        否则,如果(filterContext.Result是JsonResult)
        {
            模型=((JsonResult)filterContext.Result)。数据;
        }
        // TODO:你可以用别的继续如果在这里采取
        //考虑到有模型的概念,一些其他的操作结果
        //例如像一些你可能已经编写自定义操作结果        如果(型号== NULL)
        {
            //我们没有模式=>没有延长
            返回;
        }        变种extenderType = typeof运算(IModelExtender&所述;&GT)。MakeGenericType(model.GetType());
        VAR扩展= DependencyResolver.Current.GetService(extenderType);
        VAR延长= extenderType.GetMethod(扩展);
        extend.Invoke(扩展,新的[] {}模型);
    }    公共无效OnActionExecuting(ActionExecutingContext filterContext)
    {
    }
}

您还会注意到,我已经为了使用当前的依赖解析器并使其NInject不可知重构了自定义操作过滤器。你当然可以保留的iKernel 的依赖,如果你preFER。

I have created a custom Action Filter and am binding it with Ninject's BindFilter method:

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

I am binding my filter like so:

 kernel.BindFilter<ExtendModelFilter>(FilterScope.Action, 0).WhenActionMethodHas<ExtendModelAttribute>();

Everything so far is working great. What I want to accomplish is the following:

[ExtendModel]
public ActionResult Index()
{
    return View(new IndexModel());
}

What I want the ExtendModel filter to do is determine what type of Model is being used and then find the correct dependency:

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

I'm not sure how to write the code in the action filter to get an instance of 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
}

Maybe what I want to do isnt' even possible? Since I don't know at compile time what T is, is there any way to do what I want?

EDIT
Here is an example of what a ModelExtender might do:

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

I want to avoid code like this in my controller:

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

解决方案

You will have to use reflection because the model type is known only at runtime and your extender is generic:

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

You will also notice that I have refactored the custom action filter in order to use the current dependency resolver and make it NInject agnostic. You could of course keep the IKernel dependency if you prefer.

这篇关于Ninject在行动过滤器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆