MVC3,Ninject,MvcSiteMapProvider - 如何将依赖注入到重写方法

时间:2011-10-28 19:36:56

标签: asp.net-mvc dependency-injection inversion-of-control ninject service-locator

我有一个使用NinjectMvcSiteMapProvider的MVC3应用程序。

我创建了这个类,MvcSiteMapProvider使用它来动态地将节点添加到我的站点地图:

public class PageNodeProvider : DynamicNodeProviderBase
{
    public override IEnumerable<DynamicNode> GetDynamicNodeCollection()
    {            
         // need to get repository instance
         var repository = // how do I get this???

         foreach (var item in repository.GetItems())
         {
              yield return MakeDynamicNode(item);
         }
    }
}

MvcSiteMapProvider本身实例化了这个类型,所以我不确定如何将我的存储库注入其中。

我想通过获取内核句柄并在方法中调用Get<Repository>()来考虑使用服务位置。但是,在查看NinjectHttpApplication的定义时,我看到了这个属性:

    // Summary:
    //     Gets the kernel.
    [Obsolete("Do not use Ninject as Service Locator")]
    public IKernel Kernel { get; }

Do not use Ninject as Service Locator?!我还应该怎么做呢? 然后我找到this question here on stackoverflow并且所有答案都说不要使用服务位置。

我应该做什么?

2 个答案:

答案 0 :(得分:4)

这似乎是“供应商为什么设计不好?”一书中的另一章。您遇到与任何类型的ASP.NET提供程序相同的问题。对他们来说,没有真正好的和令人满意的解决方案。只是黑客攻击。

我认为您最好的选择是分叉项目并更改DefaultSiteMapProvider以使用DepencencyResolver而不是Activator,并将实现提供给社区。然后,您可以在PageNodeProvider实现中使用构造函数注入。这将解决所有类型和所有人的问题。

当然,您也可以在实现中使用DependencyResolver。但到目前为止,这不是最好的解决方案,因为你应该让实例尽可能接近根,它会使测试变得更加复杂,并且只为你解决问题。

答案 1 :(得分:1)

即使我看到你决定完全放弃提供者,我还是想详细说明使用DependencyResolver。基本上,您可以使用

通过Ninject手动获取正确的存储库实例
var repository = DependencyResolver.Current.GetService<IRepository>();

这不太健壮,因为如果内容发生变化,你必须维护它和NinjectMVC3.cs类,并且测试起来要复杂一些。