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?
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.
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.
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.
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.
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:
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;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With