开始我正在使用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;() - 但是......由于上面的代码是在类库中我无权访问内核。如何从这一点获取内核或者有更好的方法来实现这一点?
答案 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
,你会得到它,无论如何分辨率请求是否明确地传递了一个。
答案 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;
}
}