c# - 使用 Ninject 在 MVC 3 中注入(inject)属性

标签 c# asp.net-mvc-3 ninject

我正在尝试将一个属性注入(inject)到我的名为 UnitOfWorkAttribute 的 ActionFilter 中。我有这段代码:

[Inject]
public IUnitOfWork UnitOfWork { get; set; }

在执行之前,我告诉 Ninject 用以下方法解决这个问题:

Bind<IUnitOfWork>().To<NHibernateUnitOfWork>().InThreadScope();

我的问题是,在我的 UnitOfWorkAttribute 类中,每当我尝试使用我的 UnitOfWork 属性时,它都会以 Null 形式出现。这是我的界面:

public interface IUnitOfWork : IDisposable
{
    void Begin();
    void Commit();
    void Rollback();
}

这是我的具体内容:

public interface INHibernateUnitOfWork : IUnitOfWork
{
    ISession Session { get; }
}

public class NHibernateUnitOfWork : INHibernateUnitOfWork
{
    private readonly ISessionSource sessionSource;
    private ITransaction transaction;
    private ISession session;

    private bool disposed;
    private bool begun;

    public NHibernateUnitOfWork(ISessionSource sessionSource)
    {
        this.sessionSource = sessionSource;
        Begin();
    }

    //.......
}

我正在实现//......下的接口(interface)

我在这里做错了什么?

最佳答案

问题是 Ninject 从来没有机会在 ActionFilter 上“做这件事”,这是由 FilterAttributeFilterProvider 在 MVC 内部处理的。您需要做的是告诉 MVC 使用自定义 FilterAttributeFilterProvider,您可以在过滤器执行之前拦截过滤器。请允许我演示:

假设我有这个接口(interface)和实现:

public interface IFoo
{

}

public class Foo : IFoo
{

}

然后我有一个 ActionFilter:

public class MyActionFilterAttribute : ActionFilterAttribute
{
    public MyActionFilterAttribute()
    {
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        //do something with Foo
        base.OnActionExecuting(filterContext);
    }

    [Inject]
    public IFoo Foo { get; set; }
}

然后我们有一个 Controller :

public class HomeController : Controller
{
    [MyActionFilter]
    public ActionResult Index()
    {
        return View();
    }
}

如果您现在按原样运行它,显然 Foo 在 MyActionFilter 中仍为 null,所以让我们继续......

让我们设置 Ninject DependencyResolver:

public class NinjectDependencyResolver : IDependencyResolver
{
    private readonly IKernel _kernel;

    public NinjectDependencyResolver(IKernel kernel)
    {
        _kernel = kernel;
    }

    public object GetService(Type serviceType)
    {
        return _kernel.TryGet(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        return _kernel.GetAll(serviceType);
    }
}

现在让我们在 Global.asax 中使用它:

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);

        DependencyResolver.SetResolver(new NinjectDependencyResolver(GetKernel()));
    }

    private IKernel GetKernel()
    {
        var kernel = new StandardKernel();
        kernel.Bind<IFoo>().To<Foo>();
        return kernel;
    }

越来越近了,但是 MVC 在创建 Action 过滤器时仍然没有办法使用 Ninject 内核。我们将在这里实现这一目标。

首先:

public class NinjectFilterProvider : FilterAttributeFilterProvider
{
    private readonly IKernel _kernel;

    public NinjectFilterProvider(IKernel kernel)
    {
        _kernel = kernel;
    }

    public override IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    {
        var filters = base.GetFilters(controllerContext, actionDescriptor);

        foreach (var filter in filters)
        {

            _kernel.Inject(filter.Instance);
        }

        return filters;
    }
}

这里发生的是我们正在创建一个自定义的 FilterAttributeFilterProvider 类。在 OnActionExecuting 方法中,在我们通过基本实现获得所有过滤器之后,我们可以立即调用 Ninjects Inject 方法,该方法将检查实例并查看它是否可以向其中注入(inject)任何东西(使用 Inject 属性)。

最后一 block 拼图是为我们的自定义 FilterAttributeFilterProvider 设置绑定(bind):

全局.asax:

    private IKernel GetKernel()
    {
        var kernel = new StandardKernel();
        kernel.Bind<IFoo>().To<Foo>();
        //use our custom NinjectFilterProvider
        kernel.Bind<IFilterProvider>().To<NinjectFilterProvider>();
        return kernel;
    }

现在,当 MVC 获取 IFilterProvider 时(它通过 DependencyResolver 自动执行),它不会获取默认的 FilterAttributeFilterProvider,而是获取我们的自定义NinjectFilterProvider 和我们的 Foo 实例将因此填充在自定义 Action Filter 中。

关于c# - 使用 Ninject 在 MVC 3 中注入(inject)属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11781653/

相关文章:

c# - Fluentvalidation 的性能

c# - 如何在现有 MVC 3 项目中添加/集成 SqlMembershipProvider?

asp.net-mvc - 如何从 ASP.Net MVC 3 的下拉列表中读取数据

javascript - 提交表单之前调用 Ajax

c# - 如何使用约束绑定(bind)泛型类型

c# - 使用 Ninject,我可以在不公开具体类的情况下从接口(interface)创建实例吗?

c# - 如何避免桂锁

c# - C# 中这个语法是什么

asp.net-mvc-3 - Ninject - 找不到资源

c# - 对象的成员是否应该在类中自动设置?