Inversion of Control – It’s broader than just injecting components

I have previously written about Inversion of Control in .NET. There I focused on making a class open for extension by being able to replace the components that it uses. I demonstrated two techniques for doing that, Dependency Injection and Service Location.

Today I attended an excellent workshop about Scala development held by Ted Neward at Øredev. During the session Ted demonstrated a different, functional, aspect of the Inversion of Control concept which he illustrated in Scala. Since it’s fully possible to do the same thing in C# I thought would borrow and modify his example to show a different type of Inversion of Control compared to what I did in my previous article.

Injecting functions

Let’s look at a very simple example. It’s rather silly, but I think it illustrates the point quite well so humor me :)

We have a class named Car with a single property, Make. The class overrides the ToString method to return its make.

class Car
{
    public Car(string make)
    {
        Make = make;
    }

    public string Make { get; private set; }

    public override string ToString()
    {
        return string.Format("I'm a {0}", Make);
    }
}

We also have a console application that creates a couple of cars and then iterates over them printing the result of their ToString methods to the console.

var cars = new List<Car>
    {
        new Car("Volvo"),
        new Car("Saab")
    };

foreach (var car in cars)
    Console.WriteLine(car);

Now, let’s say that we also wanted to add a Ferrari and that we wanted our Ferrari’s ToString method to return a different result than the others. Had we been using a dynamic language such as Ruby we could have just switched that specific objects implementation of the ToString method out for something else. But in C# we have no means of doing that. We could of course create a subclass of Car and override the method but that might not always be a good, or even an impossible, option.

However we can quite easily make it possible to change the implementation of the ToString method of all Cars by making it delegate to another function which we in turn make possible to replace utilizing the fact that we can pass functions around as values in C#.

We begin by creating a field for the function in the Car class and make its ToString method delegate to that.

private Func<string> toStringImplementation;

public override string ToString()
{
    return toStringImplementation();
}

Of course with just this change our program will crash and burn as the field will be null for our existing cars. We therefore add a default implementation in the constructor with the same functionality as the old ToString method.

public Car(string make)
{
    Make = make;
    toStringImplementation = 
        () => { return string.Format("I'm a {0}", Make); };
}

Finally we add a way to change which implementation is used.

public void SetToStringImplementation(Func<string> implementation)
{
    toStringImplementation = implementation;
}

We are now able to change the implementation of the ToString method of specific instances of the Car class at runtime, enabling us to create our Ferrari without creating a subclass of Car.

var cars = new List<Car>
    {
        new Car("Volvo"),
        new Car("Saab")
    };

var ferrari = new Car("Ferrari");
ferrari.SetToStringImplementation(() => "I'm more than a car, I'm a lifestyle");
cars.Add(ferrari);

foreach (var car in cars)
    Console.WriteLine(car);

This is as I mentioned before a rather silly example but I do think it illustrates a different, and interesting, aspect of Inversion of Control compared to my previous post. Hopefully it also illustrates that the concept of Inversion of Control is much broader than just dependency injection.

PS. For updates about new posts, sites I find useful and the occasional rant you can follow me on Twitter. You are also most welcome to subscribe to the RSS-feed.

Comments

  1. Peter Strasvensen's avatar

    Peter Strasvensen 1 years ago

    That is not Inversion of Control but Dependency Injection. You could accomplish the same thing by setting a public property to receive a Func.

  2. Joel Abrahamsson's avatar

    Joel Abrahamsson 1 years ago

    True, it's dependency injection. What I guess I meant was that it wasn't your usual database-accessing/e-mail-sending/logging component that got injected but a function and in contrast to my earlier post it wasn't done by constructor injection.

    But why would you say that it wasn't IoC?

  3. Stefan Forsberg's avatar

    Stefan Forsberg 1 years ago

    Favor composition over inheritance?

    Slightly off topic: When do you use a delegate (Func in this case) instead of creating a class to handle the ToString-formatting?

Follow me on Twitter

  1. @tim_abell The gigantic ones are for customers who specifically ask for them only :) 1 months ago
  2. Looking to buy a gigantic easter egg filled with candy for delivery in Stockholm. Any recommendations? 1 months ago
  3. @strandberg_m Du måste skriva om resultatet efteråt! 1 months ago
follow me

Latest comments

  1. Joel Abrahamsson wrote "Hi Jonas! The fluent API is really geared towards working..." on Building a search page for an EPiServer site using Truffler
  2. Jonas wrote "Thank you for one more great write up! If you're not lucky ..." on Building a search page for an EPiServer site using Truffler
  3. David Knipe wrote "The CategoriesFacet method will save me a load of headaches ..." on Cool new features in the Truffler .NET API

About this site

This blog is built with EPiServer Community, EPiServer CMS, ASP.NET MVC and a bunch of other great products. The source code is available for download at the projects page, where you also can read more about this site and my other projects.

read more