Как называется конструктор конструктора веб-API?

Согласно в этой статье, контроллер должен иметь конструктор, который получает реализованный интерфейс, a la:

public class DuckbillsController : ApiController
{
    IDuckbillRepository _platypiRepository;

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

Но как называется этот конструктор? Рассчитывается через клиент, вызывающий метод Web API, содержащийся в этом классе, но как он проходит интерфейс типа? Или это не должно произойти (конструктор явно не вызывается кем-либо/из любого места)?

UPDATE

Канонические примеры показывают "private readonly", добавленный к объявлению интерфейса, но это не обязательно для его компиляции. Есть ли компиляция, я имею в виду неотразимую причину для меня, чтобы добавить "личное чтение только"?

Ответ 1

Контроллер factory создает их для вас... Вам нужно взглянуть на Injection Dependency.

Попробуйте Autofac, он имеет приятную интеграцию для MVC.

Ответ 2

Поскольку там нигде нет документации (официальные документы просто обсуждают это с Unity). Вот как вы это делаете.

Свойство HttpConfiguration.DependencyResolver - это экземпляр IDependecyResolver, который в основном является локатором службы (вы запрашиваете экземпляр типа, и он знает, как его создать). Я хотел бы предоставить свою собственную реализацию контроллера.

Используйте так:

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

Реализовано так:

/// <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;
    }

}

Хитрость в том, что вам нужно реализовать IDependencyScope дважды - один раз для IDependencyResolver и один раз для области, которую он создает для каждого запроса.

Ответ 3

Вам нужно использовать инъекцию зависимостей (structuremap, ninject). Если вы не хотите использовать DI, вам необходимо предоставить конструктор перегрузки, как показано ниже.

public DuckbillsController():this( new DuckbillRepository())
{
}