6

首先,我使用的是 Ninject 1.5。我有两个项目:Web 项目和一个类库。我的 DI 配置在 Web 项目中。在我的类库中,我定义了以下内容:

    public interface ICacheService<T>
    {
            string Identifier { get; }
            T Get();
            void Set( T objectToCache, TimeSpan timeSpan );
            bool Exists();
    }

然后是一个名为CategoryCacheService的具体类。

在我的网络项目中,我绑定了两者:

Bind( typeof( ICacheService<List<Category>> ) ).To( typeof(CategoryCacheService)).Using<SingletonBehavior>();

在我的类库中,我有 HtmlHelper 类的扩展方法,例如:

public static class Category
 {
  [Inject]
  public static ICacheService<List<Category>> Categories { get; set; }

  public static string RenderCategories(this HtmlHelper htmlHelper)
  {
   var c = Categories.Get();

   return string.Join(", ", c.Select(s => s.Name).ToArray());
  }
 }

有人告诉我,您不能注入静态属性,而是应该使用Kernel.Get<>() - 但是...由于上面的代码位于类库中,因此我无权访问内核。我怎样才能从这一点上获得内核,或者有更好的方法吗?

4

2 回答 2

8

好问题要问。

使用 DI 的一半想法是从注入的代码中消除对实例化行为的关注/微调。Category因此,将类更改为不再是更有意义,static在 ctor 中声明其依赖项并让客户端代码将其拼接在一起。

关于如何访问它,如果你真的确定它是一个好主意......通常你的想法是创建一个CacheServiceResolver并注册它[在你的 Web 项目中]。然后将其Kernel作为正在构造的实例传递给它。这样,您的 DLL 仅绑定到您的CacheServiceResolver.

经常使用的另一种方法是在全球某处有一个最后的“服务定位器”设施,它公开一个“GlobalGet”。但这通常是个坏主意,只能用于临时的管道胶带用途。

要查看的另一件事是 Common Service Locator,它将允许一个库容器中立,尽管在 EL 之外,您不会发现很多用法,因为您不应该真正显示您的容器

另一种选择是要求Func<T>工厂方法和Bind解析它的 lambda,从您的代码中提取该查找。

编辑:在 Ninject 2 中,无需Kernel像我所说的那样显式传递实例 - 只需IKernel在你的 ctor 中请求一个,你就会得到它,无论解析请求是否显式传递一个。

编辑2:对我的回答真的很不满意,试图让它更通用,而不是过多地屠杀它。总结是,理想的选项通常按以下顺序排列:

  1. 没有容器工件,将拼接留给客户
  2. 提供一个容器中立的扩展点,使用您图书馆领域的通用语言中的术语代替中和的抽象容器术语,在您的图书馆的上下文中专门完成某些事情
  3. 提供与容器无关的集成方法,例如 Common Service Locator
  4. 然后才考虑让人们需要
    • 了解你的容器
    • 了解你的容器
于 2009-10-31T07:38:07.360 回答
4

在 Web 项目中,从包管理器控制台运行以下命令。

Install-Package Ninject.MVC3

您应该在 App_Start 文件夹中得到一个 NinjectWebCommon 模块。

在底部,您可以添加您的依赖项,如下所示:

private static void RegisterServices(IKernel kernel)
{   
 kernel.Bind<IPeopleRepository>().To<PeopleRepository>();
}

从您的类库项目中运行以下命令:

Install-Package Ninject

这是使用类库中的存储库注入服务的方法:

public class PeopleService : IPeopleService
{
 private readonly IPeopleRepository _peopleRepository;

 [Inject]
 public PeopleService(IPeopleRepository peopleRepository)
 {
    this._peopleRepository = peopleRepository;
 }
}
于 2013-04-24T12:03:15.407 回答