How is the Web API Controller's constructor called?

B. Clay Shannon picture B. Clay Shannon · Dec 24, 2013 · Viewed 24.7k times · Source

According to this article, a Controller should have a constructor that gets the interface to be implemented passed in, a la:

public class DuckbillsController : ApiController
{
    IDuckbillRepository _platypiRepository;

    public DuckbillsController(IDuckbillRepository platypiRepository)
    {
        if (platypiRepository == null)
        {
            throw new ArgumentNullException("platypiRepository is null");
        }
        _platypiRepository = platypiRepository;
    }
}

But how is this constructor called? A reckon via a client calling a Web API method contained within this class, but how does it get passed the Interface type? Or does that not have to happen (constructor is not explicitly called by anyone/from anywhere)?

UPDATE

The canonical examples show "private readonly" prepended to the Interface declaration, but that is not necessary for it to compile. Is there a compiling, I mean compelling, reason, for me to prepend "private readonly"?

Answer

George Mauer picture George Mauer · Jun 14, 2016

Since there's no documentation on this anywhere (the official docs just discuss doing it with Unity). Here's how you do it.

The HttpConfiguration.DependencyResolver property is an instance of IDependecyResolver which is basically a service locator (you ask for an instance of type, and it knows how to create it). What I would like is to provide my own controller instantiation.

Use like so:

config.DependencyResolver = 
   new OverriddenWebApiDependencyResolver(config.DependencyResolver)
   .Add(typeof(ScoreboardController), () => 
                                    new ScoreboardController(Messages) 
   ); 

Implemented like so:

/// <summary>
/// The standard web api dependency resolver cannot inject dependencies into a controller 
/// use this as a simple makeshift IoC
/// </summary>
public class OverriddenWebApiDependencyResolver : WebApiOverrideDependency<IDependencyResolver >, IDependencyResolver {
    public OverriddenWebApiDependencyResolver Add(Type serviceType, Func<object> initializer) {
        provided.Add(serviceType, initializer);
        return this;
    }
    public IDependencyScope BeginScope() => new Scope(inner.BeginScope(), provided);
    public OverriddenWebApiDependencyResolver(IDependencyResolver inner) : base(inner, new Dictionary<Type, Func<object>>()) { }
    public class Scope : WebApiOverrideDependency<IDependencyScope>, IDependencyScope {
        public Scope(IDependencyScope inner, IDictionary<Type, Func<object>> provided) : base(inner, provided) { }
    }
}
public abstract class WebApiOverrideDependency<T> : IDependencyScope where T : IDependencyScope {
    public void Dispose() => inner.Dispose();
    public Object GetService(Type serviceType) {
        Func<Object> res;
        return provided.TryGetValue(serviceType, out res) ? res() : inner.GetService(serviceType);
    }

    public IEnumerable<Object> GetServices(Type serviceType) {
        Func<Object> res;
        return inner.GetServices(serviceType).Concat(provided.TryGetValue(serviceType, out res) ? new[] { res()} : Enumerable.Empty<object>());
    }
    protected readonly T inner;
    protected readonly IDictionary<Type, Func<object>> provided;
    public WebApiOverrideDependency(T inner, IDictionary<Type, Func<object>> provided) {
        this.inner = inner;
        this.provided = provided;
    }

}

The trick is that you actually have to implement IDependencyScope twice - once for IDependencyResolver and once for the scope it creates on each request.