【问题标题】:MVC3, Ninject, MvcSiteMapProvider - How to inject dependency to overridden methodMVC3、Ninject、MvcSiteMapProvider - 如何将依赖项注入被覆盖的方法
【发布时间】:2011-12-17 13:16:22
【问题描述】:

我有一个使用 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&lt;Repository&gt;() 来使用服务位置。但是,我在查看 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 *,所有答案都说不要使用服务位置。

我该怎么办?

【问题讨论】:

  • MvcSiteMapProvider 在 v4 中放弃了 Microsoft 提供程序模型。它现在完全通过使用 DI 和组合根模式连接起来。根本没有使用依赖解析器。是的,使用依赖解析器是一种不好的做法。

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


【解决方案1】:

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

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

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

【讨论】:

  • 在看到您的回答之前,我已经放弃了提供商,但谢谢。我还为这个项目和未来的项目放弃了其他供应商。
【解决方案2】:

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

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

这不太健壮,因为如果内容发生变化,您必须维护它以及 NinjectMVC3.cs 类,而且测试起来有点复杂。

【讨论】: