IOC - Should util classes with static helper methods be wired up with IOC?

Just trying to still get my head around IOC principles.

Q1: Static Methods - Should util classes with static helper methods be wired up with IOC?

For example if I have a HttpUtils class with a number of static methods, should I be trying to pass it to other business logic classes via IOC?

Follow on questions for this might be:

Q2: Singletons - What about things like logging where you may typically get access to it via a Logger.getInstance() type call. Would you normally leave this as is, and NOT use IOC for injecting the logger into business classes that need it?

Q3: Static Classes - I haven't really used this concept, but are there any guidelines for how you'd typically handle this if you were moving to an IOC based approach.

Thanks in advance.

Answers


The funny thing about IoC is that objects written in the style are generally decoupled from those details.

Let's use the utility class as an example:

public class HttpUtils
{
    public static void DoStuff(int someValue)
    {
        // ...
    }
}

In a non-IoC-focused application, you might use that method directly:

public class Foo
{
    public int Value { get; set; }

    public void DoStuff()
    {
        HttpUtils.DoStuff(Value);
    }
}

However, that couples the definition of DoStuff directly to its implementation. IoC strives to divorce those kinds of details, so instead we define the operation on its own:

public interface IDoesStuff
{
    void DoStuff(int someValue);
}

Then, we leave room in Foo for the implementation to change:

public class Foo
{
    private readonly IDoesStuff _doesStuff;

    public Foo(IDoesStuff doesStuff)
    {
        _doesStuff = doesStuff;
    }

    public int Value { get; set; }

    public void DoStuff()
    {
        _doesStuff.DoStuff(Value);
    }
}

This decouples Foo from HttpUtils. The implementer of the concept of DoStuff is now a configuration detail, and not an inherent dependency (as it is with the static method).

Notice that Foo has no idea if its IDoesStuff is a singleton or not. That lifetime is also a configuration detail, and not an inherent detail of Foo.

To sum up, IoC and static are generally at odds, since IoC promotes change and static, by definition, prevents it. Declare your dependencies in your constructors, and you'll find you almost never have you use static functionality.


An IoC container is typically useful to inject object that have state; or classes or interfaces that have more than one one implementation, even if the second implementation is a mock for testing purposes. If neither of these is true, you gain nothing by injecting it. the most common idiom these days is to have your class fronted by an interface that the real and mock implementation can both implement.

1) Static methods on helper classes - No, these do not often get injected by IoC. Typically they are stateless utilities.

To use a very simple example, you don't need two versions of a utility method called StringUtils.Reverse(). You only need one, and you can easily write tests around it because it has no state or dependencies, so there's absolutely no benefit to mocking it out. Example test:

string reversedString = StringUtils.Reverse("input");
Assert.AreEqual("tupni", reversedString)

If the utility isn't really stateless (e.g. depends on HttpContext.Current), then you should make the dependency explicit by injecting it, and not making the utility static.

2) Singletons: Often yes, singletons are injected. But a good thing about IoC is that you worry less about whether there's only one of something or not. You gain flexibility in instancing by using IoC. The decision to have a particular type as singleton or new instance each time becomes part of the IoC container's config and nothing else in the code needs to change.

So singleton-hood stops being a separate concern that has to be coded into the class (and classes having multiple concerns when they don't have to is bad), and it becomes the concern of the IoC container. You don't code the class "as a singleton" with anything special like a private constructor and a public static GetInstance() method any more, you just code it for the main concern, while the IoC container's config specifies if it's a singleton or not, or somewhere in between, like one instance per thread.

3) Static classes - are the natural home for static methods. Consider making the static methods extension methods where appropriate. You can't inject these classes, since you can't create them. Using static classes makes for procedural not object-oriented code. This isn't a bad thing for small helper methods, but if the majority of the code is like that, then you're not using the powerful OO features of the .Net platform.


Static methods by definition do not need an instance. DI/IOC aims to satisfy interfaces with concrete classes and given that your static class along with its static methods by definition cant implement an interface or extend a class the question makes no sense. Theres no point in passing the helper class because one does not need the instance to use the static methods. You code will always execute the same static helperr methods even without an instance.

In an IOC/DI powered application one would define interfaces and have at least one implementation. Its all about managing instances and their dependencies.


The dilemma arises when the utility classes, say , need access database. While db accessor need Ioc, thus utility class has to use Ioc as, so it cannot be static.

But I really want utility class to be static so easy to be consumed. I don't want to populate constructor of each consume classes who need utility classes.

Consume classes itself might not even need db access themselves. So I don't want to inject db accessor and pass it into utilities classes as well.

Guess there is no perfect solution for now. One day I hope we go one step further, in addition to constructor/property injection, there is "global context injection/configuration", or "static injection", apply Ioc beyond object creation.

Think about, why not?


Need Your Help

Avoiding all DI antipatterns for types requiring asynchronous initialization

dependency-injection initialization async-await simple-injector abstract-factory

I have a type Connections that requires asynchronous initialization. An instance of this type is consumed by several other types (e.g., Storage), each of which also require asynchronous initializat...

All Ruby tests raising: undefined method `authenticate' for nil:NilClass

ruby-on-rails ruby testing rspec devise

Most of my tests are raising the following and I don't understand why. All methods call raise the 'authenticate' error. I've checked the code if there was a method called "authenticate" but there i...