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)?
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"?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With