Joshua Tompkins
Joshua Tompkins

Reputation: 1452

Dependency Injection for Long-Lived Objects in Web API?

I'm putting together a REST service using ASP.NET Web API & Ninject, though I suspect this might be a more general IoC question than anything specific to my IoC framework. I have a number of objects that need to access a simple cache of User entities:

public class UserCache
{
    private IList<User> users;
    private IUserRepositoryFactory factory;

    [Inject]
    public UserCache(IUserRepositoryFactory factory)
    {
        this.factory = factory;
        this.users = new List<User>();
    }

    public void Add(int id)
    {
        IUserRepository repo = factory.Create(new TestContext());

        this.users.Add(repo.Get(id));
    }

    public int Count { get { return this.users.Count; } }
}

In practice, the cache is read-through, and will fill itself with User entities using a UserRepository (and associated IUserRepository interface):

public class UserRepository : IUserRepository
{
    private readonly TestContext context;

    public UserRepository(TestContext context)
    {
        this.context = context;
    }

    public User Get(int id)
    {
        return new User() { Name = "Test User" };
    }
}

The cache is long-lived and shared across the entire application. My question is this: I want to use my UserRepository to pull User entities from my database. This repository needs to be injected into the cache somehow, or instantiated using a factory.

The trick is, the only way I've been able to both a) create the cache such that Ninject will inject its dependencies and b) have access to the cache throughout the same is to bind the cache in singleton scope and inject it into objects that need access to it:

kernel.Bind<TestContext>().ToSelf();
kernel.Bind<UserCache>().ToSelf().InSingletonScope();

...and then in a controller (for example):

[Inject]
public UserCache Cache { get; set; }

My question is, is this the best way to treat long-lived objects that require injection? Or is there some better way that I'm missing? I don't want to give the cache (or any other objects like it) direct access to the Ninject kernel.

Upvotes: 1

Views: 832

Answers (1)

Hadi Eskandari
Hadi Eskandari

Reputation: 26354

Isn't this supposed to be the other way around? You should use IUserRepository in your controllers and the repository under the hood should fetch the data from cache (better if done using an interceptor) if it is already cached, otherwise should hit the database.

That way you don't have to worry about lifecycle of the long living cached objects. Remember that at the end of the day the whole WebAPI (so far) runs on the web stack, this means the application can be recycled unexpectedly based on different factors.

Upvotes: 5

Related Questions