我有一个使用Ninject和MvcSiteMapProvider的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并且所有答案都说不要使用服务位置。
我应该做什么?
答案 0 :(得分:4)
这似乎是“供应商为什么设计不好?”一书中的另一章。您遇到与任何类型的ASP.NET提供程序相同的问题。对他们来说,没有真正好的和令人满意的解决方案。只是黑客攻击。
我认为您最好的选择是分叉项目并更改DefaultSiteMapProvider以使用DepencencyResolver而不是Activator,并将实现提供给社区。然后,您可以在PageNodeProvider实现中使用构造函数注入。这将解决所有类型和所有人的问题。
当然,您也可以在实现中使用DependencyResolver。但到目前为止,这不是最好的解决方案,因为你应该让实例尽可能接近根,它会使测试变得更加复杂,并且只为你解决问题。
答案 1 :(得分:1)
即使我看到你决定完全放弃提供者,我还是想详细说明使用DependencyResolver。基本上,您可以使用
通过Ninject手动获取正确的存储库实例var repository = DependencyResolver.Current.GetService<IRepository>();
这不太健壮,因为如果内容发生变化,你必须维护它和NinjectMVC3.cs类,并且测试起来要复杂一些。