Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ninject and static classes - how to?

Tags:

c#

static

ninject

I have a static class and I need to inject some instances into it. A static class can have a static constructor but it must be parameterless. So, how am I supposed to inject something into it?

I do not wish to create a singleton. I wish to have a static class, and one of its methods operate on an instance that should be injected. Below is an example of the sort of thing I need:

public static class AuthenticationHelper
{
    // Fields.
    private static object _lock = new object();
    private static readonly UserBusiness _userBusiness; // <-- this field needs to be injected.

    // Public properties.
    public static User CurrentUser
    {
        get
        {
            if (IsAuthenticated)
            {
                User user = (User)Context.Session[SessionKeys.CURRENT_USER];

                if (user == null)
                {
                    lock (_lock)
                    {
                        if (user == null)
                        {
                            user = _userBusiness.Find(CurrentUserId);
                            Context.Session[SessionKeys.CURRENT_USER] = user;
                        }
                    }
                }

                return user;
            }

            return null;
        }
    }
    public static int CurrentUserId { get; /* implementation omitted for brevity */ }
    public static bool IsAuthenticated { get; /* implementation omitted for brevity */ }
}

Background info: this is an MVC4 application, so I'm using ninject.mvc3 plugin.

PS.: I've seen some questions concerning Ninject and static methods, but none of them seemed to address an issue like this.

like image 242
Phillippe Santana Avatar asked May 31 '13 23:05

Phillippe Santana


2 Answers

Don't do it. Don't use a static class that needs dependencies of its own. This makes testing harder and other types that depend on this AuthenticationHelper won't be able to include it in their constructor which means they hide the fact that they depend on it.

Instead just do what you would always do: make AuthenticationHelper non-static, implement an IAuthenticationHelper interface on it and inject all dependencies through its public constructor.

But if you insist into keeping that class static (which again is a really bad idea), create a static Initialize(UserBusiness userBusiness) method on it, and call this method in the start-up path of your application. You can't let your DI container call this static method. They don't allow because 1. it's a bad idea, and 2. such static method only has to be called once, so letting your container auto-wire this for you doesn't really help.

like image 93
Steven Avatar answered Oct 12 '22 05:10

Steven


As a side note, the lock is completely useless since you are locking access to a local variable "user" which will not change between the 2 "if (user == null)" lines.

Your intention is to lock access to the Context.Session[CURRENT_USER] element, so ..

            User user = (User)Context.Session[SessionKeys.CURRENT_USER];

            if (user == null)
            {
                lock (_lock)
                {
                    user = (User)Context.Session[SessionKeys.CURRENT_USER];
                    if (user == null)
                    {
                        user = _userBusiness.Find(CurrentUserId);
                        Context.Session[SessionKeys.CURRENT_USER] = user;
                    }
                }
            }
like image 38
steve Avatar answered Oct 12 '22 05:10

steve