Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET MVC3 Service Locator / Dependency Resolver Question With Ninject

I have what I'd consider a standard .NET MVC3 Repository pattern project that I've been playing/learning with. It's pretty standard structure.

  • Repository project (with the below mentioned Caching infrastructure)
  • Domain Model Project
  • Service Layer Project
  • MVC Presentation project

I've run into a scenario where I need to inject a private member of a class that only has a static constructor which leaves me out of luck for constructor injection.

The class in question is a wrapper to use an AppFabric caching implementation that I just completed. (For those so inclined, my implementation is based on https://github.com/geersch/AppFabric )

Essentially I have:

  • interface ICacheProvider
  • class DefaultCacheProvider : ICacheProvider
  • static class Cache (utilizing whatever implementation I've injected)

The static class cache is where I'd like to inject an ICacheProvider that gets resolved to DefaultCacheProvider.

    private static readonly ICacheProvider CacheProvider;

    static Cache()
    {
        //DependencyResolver.Current.GetService<ICacheProvider>();

        //CacheProvider =
        //    (ICacheProvider)ServiceLocator.Current
        //                            .GetInstance(typeof(ICacheProvider));
    }

    public static void Add(string key, object value)
    {
        CacheProvider.Add(key, value);
    }

    public static void Add(string key, object value, TimeSpan timeout)
    {
        CacheProvider.Add(key, value, timeout);
    }

    public static object Get(string key)
    {
        return CacheProvider[key];
    }

    public static bool Remove(string key)
    {
        return CacheProvider.Remove(key);
    }

Based off what I've read, this seems like a scenario for ServiceLocator but I've seen some very strong opinions on it (anti pattern, etc. etc), that and my familiarity with it is low so I'm unsure of an implementation that would work.

I've seen the recommendation on StackOverflow to design the Cache class as a standard class and inject the ICacheProvider in SingletonScope

kernel.Bind<ICacheProvider>().To<DefaultCacheProvider>().InSingletonScope();

but I personally would prefer a static wrapper for ease of use.

Is a ServiceLocator setup the way to go here or is there something else obvious that I'm unaware of? If ServiceLocator is the way to go, is there any tie-in with Ninject to utilize? I know Ninject now has service locator capabilities but was unsure how to implement.

Thanks for any info.

like image 493
Khepri Avatar asked Apr 22 '11 01:04

Khepri


1 Answers

I think your approach is missing the essence of the Inversion of Control container to provide Dependency Injection.

Based off what I've read, this seems like a scenario for ServiceLocator but I've seen some very strong opinions on it (anti pattern, etc. etc)

The very strong opinons usually include an aversion to the Singleton pattern, or, in other words, using a static class to provide services. The problem here is that the Cache class you've written is the same Singleton pattern that is the anti-pattern you referred to.

What does the code that consumes the Cache singleton look like? Let me propose a hypothetical.

public class SomeClass
{
    public string GetSomeMetaData()
    {
        return Cache.Get("magicKey");
    }
}

In this case, you've abstracted the IoC and avoided DI by using a Singleton. I would suggest

public class SomeClass
{
    private readonly ICacheProvider _cacheProvider;

    public SomeClass(ICacheProvider cacheProvider)
    {
        _cacheProvider = cacheProvider;
    }

    public string GetSomeMetaData()
    {
        return _cacheProvider.Get("magicKey");
    }
}

Now the consumption of the ICacheProvider occurs directly in the class that needs it and can more easily accomodate change to ICacheProvider implementations. It had the added benefit of simplifying testing. The Singleton pattern is nearly impossible to test against.

like image 140
Ed Chapel Avatar answered Nov 18 '22 02:11

Ed Chapel