Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ninject: How do I inject into a class library?

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?

like image 890
Denny Ferrassoli Avatar asked Oct 30 '09 17:10

Denny Ferrassoli


People also ask

What is ninject dependency injection?

Ninject is a lightweight dependency injection framework for . NET applications. It helps you split your application into a collection of loosely-coupled, highly-cohesive pieces, and then glue them back together in a flexible manner.

How do you inject dependency?

Types of Dependency Injection The injector class injects dependencies broadly in three ways: through a constructor, through a property, or through a method. Constructor Injection: In the constructor injection, the injector supplies the service (dependency) through the client class constructor.

Which library is used for dependency injection?

Use Hilt in your Android app Hilt is Jetpack's recommended library for dependency injection in Android. Hilt defines a standard way to do DI in your application by providing containers for every Android class in your project and managing their lifecycles automatically for you.

What is a ninject module?

The Ninject modules are the tools used to register the various types with the IoC container. The advantage is that these modules are then kept in their own classes. This allows you to put different tiers/services in their own modules.


2 Answers

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
like image 173
Ruben Bartelink Avatar answered Oct 11 '22 08:10

Ruben Bartelink


In the web project run the following command from the Package Manager Console.

Install-Package Ninject.MVC3

You should end up with a NinjectWebCommon module in the App_Start folder.

Towards the bottom you can add your dependencies like below:

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

From your class library project run the following command:

Install-Package Ninject

This is how to inject a service with a repository from the class library:

public class PeopleService : IPeopleService
{
 private readonly IPeopleRepository _peopleRepository;

 [Inject]
 public PeopleService(IPeopleRepository peopleRepository)
 {
    this._peopleRepository = peopleRepository;
 }
}
like image 44
hutchonoid Avatar answered Oct 11 '22 10:10

hutchonoid