Ninject:如何注入类库?

时间:2009-10-30 17:19:00

标签: dependency-injection ninject

开始我正在使用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&lt;&gt;() - 但是......由于上面的代码是在类库中我无权访问内核。如何从这一点获取内核或者有更好的方法来实现这一点?

2 个答案:

答案 0 :(得分:8)

要问的好问题。

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

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

的界面

经常使用的另一种方法是在全球某处设置最后的“服务定位器”设施,从而暴露出“GlobalGet”。但这通常是一个坏主意,只应用于临时管道编带目的。

要看的另一件事是Common Service Locator,它允许一个库容器中立,虽然在EL之外,你不会发现很多用法为you shouldnt really show your container

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

编辑:在Ninject 2中,没有必要像我所说的那样明确传递Kernel个实例 - 你可以简单地在你的ctor中要求IKernel,你会得到它,无论如何分辨率请求是否明确地传递了一个。

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

  1. 没有容器工件,留给客户端缝合
  2. 提供容器中性扩展点,专门用于在您的库的上下文中使用术语库中无所不在的语言中的术语来代替中和的抽象容器术语来专门完成某些内容。
  3. 提供与容器无关的集成方法和公共服务定位器
  4. 只考虑让人们需要
    • 了解你的容器
    • 了解你的容器

答案 1 :(得分:4)

在Web项目中,从Package Manager控制台运行以下命令。

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;
 }
}
相关问题