Ninject:如何注入类库? [英] Ninject: How do I inject into a class library?

查看:131
本文介绍了Ninject:如何注入类库?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

开始我正在使用Ninject 1.5。我有两个项目:Web项目和一个类库。我的DI配置在Web项目中。在我的类库中,我有以下定义:

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

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

在我的Web项目中,我绑定了两个:

 绑定(typeof (ICacheService< List< Category>))).To(typeof(CategoryCacheService))使用< SingletonBehavior>(); 

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

  public static class Category 
{
[Inject]
public static ICacheService< List< Category>>分类{get;组;

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

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

我被告知你不能注入静态属性,而应该使用 Kernel.Get<>() - 但是...由于上面的代码在类库中,我无法访问内核。如何从这一点获取内核?还是有更好的方法?

解决方案

/ p>

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



关于如何访问它,如果你真的确定它的一个好主意...一般来说,你的案例将是创建一个 CacheServiceResolver 并注册[在您的Web项目中]。然后将它作为它的构造传递给内核实例。这样你的DLL只能绑定到您的 CacheServiceResolver 的界面。



另一种经常使用的方法是在全球范围内的最后一个服务定位器设施,暴露了一个GlobalGet。但这通常是一个坏的想法,只能用于临时的Duct Taping目的。



另一件需要查看的是Common Service Locator,这将允许人们图书馆容器中立,虽然在EL之外,你不会发现很多用法,如你不应该真正显示你的容器



另一个选项是要求一个 Func< T> 工厂方法和绑定到一个解析它的lambda,从代码中提取该查找。



编辑:在Ninject 2中,没有必要明确地传入 Kernel 实例,就像我所说 - 可以简单地要求一个 IKernel 在你的ctor,你会得到它,无论解决方案请求是否通过一个。



编辑2:真的不满意我的答案,试图使它更普遍没有屠杀它太多了。总结是,期望的选项通常按照以下顺序:


  1. 没有容器工件,离开缝合到客户端

  2. 提供一个容器中立的扩展点,专门用于在图书馆的上下文中使用您的图书馆领域的无所不在的语言代替中和的抽象容器条款来实现某些内容

  3. 提供一个容器中立的集成方法一个常见的服务定位器

  4. 只有这样才能让人需要


    • 知道您的容器

    • 了解您的容器



To start I'm using Ninject 1.5. I have two projects: Web project and a Class library. My DI configuration is within the Web project. Within my class library I have the following defined:

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

And then a concrete class called CategoryCacheService.

In my web project I bind the two:

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

In my class library I have extension methods for the HtmlHelper class, for example:

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());
  }
 }

I've been told that you cannot inject into static properties, instead I should use Kernel.Get<>() - However... Since the code above is in a class library I don't have access to the Kernel. How can I get the Kernel from this point or is there a better way of doing this?

解决方案

Good question to ask.

Half the idea of using DI is to remove the concern/fine tuning of the instancing behavior from the code under injection. Therefore, it may make more sense to change the Category class to no longer be static, declare its dependencies in a ctor and let the client code stitch it together.

Regarding how to access it if you're really sure its a good idea... Generally the idea in your case would be to create a CacheServiceResolver and register it [in your Web Project]. Then pass it the Kernel instance as its being constructed. That way your DLL is only bound to the interface of your CacheServiceResolver.

The other approach often used is to have a last-resort 'Service Locator' facility somewhere global, which exposes a 'GlobalGet'. But that's generally A Bad Idea and should only be used for temporary Duct Taping purposes.

The other thing to look at is the Common Service Locator, which will allow one to make a library container-neutral, though outside of EL, you wont find a lot of usage as you shouldnt really show your container.

The other option is to demand a Func<T> factory method and Bind that to a lambda that resolves it, extracting that lookup from your code.

EDIT: In Ninject 2, there's no need to explicitly pass in Kernel instances as I've said - one can simply ask for an IKernel in your ctor and you'll get it, regardless of whether the resolution request expclicitly passes one in.

EDIT 2: Really unhappy with my answer, have tried to make it more general without butchering it too much. Summary is that the desirable options are generally in the following in order:

  1. no container artifacts, leave stitching to client
  2. provide a container neutral extension point, tailored to specifically accomplish something in the context of your library using terminology in the Ubiquitous Language of your Library's Domain in lieu of neutralised abstract container terms
  3. provide a container-neutral integration approach a la Common Service Locator
  4. only then consider having people needing to
    • know your container
    • understand your container

这篇关于Ninject:如何注入类库?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆