public interface ICacheService<T> { string Identifier { get; } T Get(); void Set( T objectToCache,TimeSpan timeSpan ); bool Exists(); }
然后是一个名为CategoryCacheService的具体类.
在我的web项目中,我绑定了两个:
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<>() – 但是……由于上面的代码在类库中,我无法访问内核.如何从这一点获取内核,或者有更好的方法吗?
使用DI的一半想法是从注入代码中删除对实例化行为的关注/微调.因此,将Category类更改为不再是静态更有意义,在ctor中声明其依赖关系并让客户端代码将它们拼接在一起.
关于如何访问它,如果你真的确定它是一个好主意…通常你的情况下的想法是创建一个CacheServiceResolver并在[你的Web项目]中注册它.然后在构造时传递内核实例.这样你的DLL只绑定到CacheServiceResolver的接口.
通常使用的另一种方法是在全球某处设置最后的“服务定位器”设施,从而暴露出“GlobalGet”.但这通常是一个坏主意,应该只用于临时管道编带目的.
另一件要看的是Common Service Locator,它允许一个库容器中立,虽然在EL之外,你不会发现很多用法为you shouldnt really show your container.
另一种选择是要求Func< T>. factory方法并将其绑定到解析它的lambda,从代码中提取该查找.
编辑:在Ninject 2中,没有必要像我所说的那样明确地传入内核实例 – 你可以简单地在你的ctor中请求一个内核,你将得到它,无论分辨率请求是否明确地通过了一个.
编辑2:对我的回答真的不满意,试图让它更普遍,而不是过多地屠杀它.总结是,理想的选项通常按顺序排列如下:
>没有容器工件,留给客户端缝合
>提供容器中立的扩展点,专门用于在库的上下文中使用术语库中的无处不在的语言中的术语来代替中和的抽象容器术语
>提供与容器无关的集成方法和公共服务定位器
>只有这样才能考虑让人们需要
>了解你的容器>了解你的容器