views:

213

answers:

1

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> 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?

Thanks!

+1  A: 

Good question to ask.

You've got it set up with SingletonBehavior. What are you going to achieve with the static ? Save some bytes? Half the idea of using DI is to remove the fine tuning of the instancing behavior from the code under injection.

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.

Ruben Bartelink
Ruben, the CacheServiceResolver seems like the right idea for me since I can re-use that pattern in the future. Do you have any examples on setting up a resolver?
DennyDotNet
Sadly I havent got one to hand. The general idea would be that wherever you're creating your new StandardKernel, you stash a reference to it. Then you have something as simple as `void RegisterCacheServiceResolver(Kernel kernel) {Bind<ICacheServiceResolver>().ToConstant( new CacheServiceResolver( kernel));}` on one of the modules, to which you pass the kernel. Or you could create the Kernel, and then pass it to the constructor of any Module that needs it, after which you add the Module [as opposed to passing them all into the constructor of Kernel as one typically does].
Ruben Bartelink