MVC3、Ninject、MvcSiteMapProvider - 如何将依赖注入到覆盖的方法中

7
我有一个使用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; }

不要使用Ninject作为服务定位器,那我该怎么办呢?我在stackoverflow上找到了这个问题,所有答案都说不要使用服务定位。我应该怎么办?

MvcSiteMapProvider在v4中放弃了Microsoft提供的模型。现在完全使用DI和组合根模式进行连接。根本不使用依赖项解析器。是的,使用依赖项解析器是一个不好的实践。 - NightOwl888
2个回答

4
这似乎是来自书籍“为什么提供者是糟糕的设计?”的另一章节。您与任何类型的ASP.NET提供程序都存在相同的问题,它们没有真正好且令人满意的解决方案,只有hack。我认为您最好的选择是fork该项目并将DefaultSiteMapProvider更改为使用DepencencyResolver而不是Activator,并将实现提供回社区。然后,您可以在PageNodeProvider实现中使用构造函数注入。这将一劳永逸地解决所有类型和每个人的问题。
当然,您也可以仅在您的实现中使用DependencyResolver。但这绝不是最好的解决方案,因为您应该尽可能接近根获取实例,这会使测试更加复杂,并且只能为您解决问题。

我在看到你的回答之前就已经放弃了这个供应商,但还是谢谢。对于这个项目和未来的项目,我也已经放弃了其他的供应商。 - Ronnie Overby

1

尽管我看到你已经决定完全放弃提供者,但我想详细说明如何使用DependencyResolver。基本上,您可以通过Ninject手动获取正确的存储库实例

var repository = DependencyResolver.Current.GetService<IRepository>();

这种方法不够健壮,因为您需要维护这个东西以及 NinjectMVC3.cs 类,如果有变化的话,并且测试也更加复杂。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接