IoC - Inversion of Control.

32542  63345_wl_91994v00_diwheel_fig4_wl

IoC (see Inversion of Control on Wikipedia) is a pattern of best practice which is used to decouple a component that relies on other functionality to perform its task.

An example being an application which needs to access data storage be it a file, database, webservice or other mechanism. It requires this to do its job but doesn't need to know about the implementation details.

IoC allows you to decouple your program into separate parts. This is good because:

  • Components can be easily tested independently.
  • Program complexity can be reduced.
  • You can switch components to another implementation.
  • However in some cases, IoC can make code harder to understand.

If you want to see good example of real-world usage of IoC, have a look at Mircosoft Composite UI Application Block and CompositeWPF

Two types of IoC are Depedency Injection and Service Locator


Simple Example


To explain how IoC works I've created this simple class that either adds two numbers together or takes two numbers away. They look like this.

public interface ICalculator

{

string Calculate(decimal number, decimal number2);

}

public abstract class Calculator : ICalculator

{

public abstract string Calculate(decimal number, decimal number2);

}

public class Add : Calculator

{

public override string Calculate(decimal number, decimal number2)

{

return (number + number2).ToString(CultureInfo.InvariantCulture);

}

}

public class Subtract : Calculator

{

public override string Calculate(decimal number, decimal number2)

{

return (number - number2).ToString(CultureInfo.InvariantCulture);

}

}

 


Why IoC


In the usual way we would create any dependants we need in the constructor. Taking this code as an example, we create a calculator object. We could be creating a validator to validate the input on a fictional control. Or we need to access the database so we create a Repository to do so.

public CalculatorController()

{

var ICalculator _calculator = new Add();

}

you might rewrite it like the following code to use IoC. We say that whatever class is given to the constructor as long as it implements the same set of commands our code will work.

public class AddressEditController : Controller

{

private readonly ICalculator _calculator;

private IRepository _repository;

public AddressEditController(ICalculator calculator, IRepository repository)

{

_calculator = calculator;

}

}

The biggest thing in my opinion to watch out for is were polymorphism is being broken. This usually happens without the coders knowledge, were swapping one class for another doesn't result in the same out come. For more information I recommend reading "Agile Principles, Patterns, and Practices in C#"


Service Locator


Service locator is a system were by a central store of 'services' is recorded, this central store is usually referred to as a 'registry'. When a component requires a particular service it calls the service locator to get an instance of what is required.

Microsoft MVC and WPF are built using the Service Locator pattern behind the scenes. They usually use the pattern as it's defined in Microsoft Patterns and Practices.

For instance in MVC you can use Microsoft.Practices.ServiceLocation.ServiceLocator as long as you have defined a ServiceLocator before hand.

You must also install the NuGet package Microsoft.Practices.ServiceLocation

The service locator is commonly referred to as an Anti Pattern due to the component parts needing to know about the service locator.


Dependency Injection


DI consists of several types these are:

  • Type 1 Interface injection
  • Type 2 Setter injection
  • Type 3 Constructor Injection

Interface injection


Interface injection is essentially the 'right' way of wiring applications together. That is you should define a contract between components. For instance in dependency injection you can wire it up like this.

For<Calculator>().Use<Add>();

What that means is that each component part of the system needs to know about the Calculator class and what operations it can perform. The way it should be done is like this.

For<iCalculator>().Use<Add>();

So you define an interface and that interface is swapped out for a concrete class.


Constructor Injection


Constructor Injection as the name implies takes the thing you want and passes it automagically into the constructor. Its usually done by checking the interfaces on the constructor and passing in the things required.

private readonly ICalculator _myCalculator;

public ConstructorInjectionExampleController(ICalculator myCalculator)

{

_myCalculator = myCalculator;

}

The above example with the correct dependency injection setup, the object will get automatically passed into the constructor for use by the rest of the class.


Setter injection


Setter injection will inject a class into a property on an object when its instantiated. So say your class had a property like this.

public ICalculator Calculator { get; set; }

You can setup dependency injection to create a new Add or Subtract object and inject it straightinto the property when your class is created.


Don't use ObjectFactory.GetInstance


Most Inversion Of Control containers give you a method for returning an object. For instance in Structure Map you can use ObjectFactory.GetInstance. This shouldn't be called directly, because the whole point is not to litter you code with code to create objects. You might as well use new Account in this example as ObjectFactory.GetInstance.

using System;

using NBehave.Spec.NUnit;

using StructureMap;

namespace StructureMapTest {

public interface ICustomer { string GetName(); }

public class Customer : ICustomer

{

public string GetName(){return "T. Boone Pickens";}

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

}

public class Account

{

public ICustomer MyCustomer { get; set;}

public Account(ICustomer customer) {

MyCustomer = customer;

}

}

class StructureMapRunner {

static void Main() {

ObjectFactory.Initialize(x => x.For<icustomer>().Use<customer>));

Account account = ObjectFactory.GetInstance<account>();

account.MyCustomer.GetName().ShouldEqual("T. Boone Pickens");

}

}

}


Beware the circular reference


Its quite easy to create a circular refernce for example:

public class ClassA

{

public ClassA(ClassB INeedClassB)

}

public class ClassB

{

public ClassB(ClassA INeedClassA)

}

Class A tries to inject Class B which in turn tries to inject Class A which in turn injects Class B which... You get the idea massive Stack Overflow exception.

That example is obviously pretty contrived but imagine several classes that are joined together in a chain its quite easy to accidentally do this.


Lifecycle aka Caching management


An insanely powerful feature in IoC is the ability to set a lifecycle also called caching in some systems. What this does is based on the type of lifecycle

  • PerRequest - The default operation. A new instance will be created for each request.
  • Singleton - A single instance will be shared across all requests
  • ThreadLocal - A single instance will be created for each requesting thread. Caches the instances with ThreadLocalStorage.
  • HttpContext - A single instance will be created for each HttpContext. Caches the instances in the HttpContext.Items collection.
  • HttpSession - A single instance will be created for each HttpSession. Caches the instances in the HttpContext.Session collection. Use with caution.
  • Hybrid - Uses HttpContext storage if it exists, otherwise uses ThreadLocal storage.

The objects that are being injected can be cached for a period of time. So say you have an object that takes a long time to create but can be reused over and over again. Well ideally you might want that object to last as long as the users session. Using lifecycle you can make an object stay in memory and be reused as long as you want it to.

If you would like to try this article out as an interactive inversion of control project then download it here.

https://www.dropbox.com/s/9zpe6pt7pvylspf/DI%20Example.rar?dl=0

Whatever your business, be it a regional or global brand, the content you produce plays a vital role in your success. You know that… hence you’re reading this.

A well formulated and executed content strategy not only drives more traffic, at the core, it defines what your business is and helps build a strong connection between you and your audiences.

So let's quickly look at why developing a coherent content strategy is important and how setting clear goals and understanding your audience will elevate your online performance. 

What is a Content Strategy?

It's basic right? Content is at the core of how you define the way your business presents itself and an effective strategy should look to ensure that tone of voice, messaging and the core values are surfaced across all channels, from service or product pages on your website, to blog posts, through social media updates blah blah blah.

But let's keep it simple - your content strategy should be a clear roadmap that connects your marketing activities to your business goals. Align to your customer’s wants and needs and engage them at every interaction point and boom, you're in business. 

Who are my Audience?

You likely start all your projects with this chalked on the wall because your business knows “exactly” who its customers are right? Sounds obvious but we often find its not been done forensically enough (not based on data), is too old (more than 12 months ago - forget it) or its a spin off from some brand work that was legitimately aspirational but doesn’t face the reality of who you your business is actually engaging today.

So start (or circle back) with audience research, building out those personas to understand their ambitions, their lifestyle, their pain points or concerns, and crucially their wants and needs - in your context. 

Do I need to tailor content?

As part of your research find out where your audiences spend their time online and how they interact with content: Some may spend time thoroughly researching a product or service, whereas other audiences may want their content to be quick, snappy or easily digestible in the form of a video, infographic or short blog posts.

 

Ultimately, the key is to produce a strategy that creates the type of content your customers want to see:

  • What are the problems that your product or service will help them solve?

  • Who are they most influenced by?

  • What voices influence their behaviour?

  • What type of content do they consume?

  • Where do they consume content and engage with brands?

Different Content, Different Objectives

 All content is not born equal: When producing your strategy, it is important that the objectives for each individual piece are defined, that these fulfil your marketing objectives and tie to the overarching goals for your business.

There are various content frameworks that exist to aid content development in this way, but one that is popular and effective is Google’s hero, hub and hygiene method: It provides a framework on developing content to achieve different goals and gives guidance on the effort needed to create each type of content.

Hero Content

Hero content is essentially campaign content, it is big splash ideas designed to appeal to a large audience with the aim of telling your brand’s story at scale. 

Ways of measuring hero include the amount of PR mentions or links from authoritative domains plus social interactions and mentions of your brand across all channels. 

Considering the scale of hero campaigns, this content is not regularly produced and is reserved for peak promotional times where it’s important for a business to stand out from their competitors.

Hub Content

Hub content is the stuff that keeps your audience engaged, it expands on the themes of product or service level content, educates users and helps create a connection between themselves and your brand.

Hygiene Content

Hygiene content is the bread and butter of any website, it is the BAU content for products and services, it is SEO focused and targets important keywords at a product, service or guide level.

How do I manage all this?

Content development is only one part of the ongoing work needed when working with an effective content strategy. We call it “feeding the beast” because it really is the fuel in your brand vehicle and once you start you really can’t stop (if it’s delivering results) but that’s where performance measurement comes in.

Your greatest gift in managing the outputs from your hero/hub/hygiene style efforts is to understand If your content is working. To truly deliver results your business must first understand the objectives and goals of each piece of content to effectively measure its success. That as a guiding light from day 1 will let you slow down, speed up, stop or start new content briefs and projects.

Remember - content strategies are not set in stone. They are living breathing things and should adapt and pivot as insights become available and your brand naturally evolves.

If ever you want to chat content and explore new initiatives we’re always here to help.

want to speak to one of our experts?

 
Richard Brisley
Richard Brisley
Tech Lead
Richard is the longest standing member of the Sagittarius team, he works tirelessly to support the development and side-facing team with problem solving and pitches alike. His skills as a .NET programmer and database administrator have been paramount to the success of Sagittarius and our continued success. 

In 2016 and again in 2019 Richard was recognise in the BIMA 100 awards for his outstanding work in Tech, his passion for digital and his contribution to the industry. 

Richard Brisley

Richard Brisley

17 Mar 2015 - 8 minute read
share this

stay in the know, stay ahead.

Get the latest from the agency, including news, events and expert content.
explore services in the article
find out what we can do for you
read some of our case studies