15

根据这篇文章,控制器应该有一个构造函数来获取要实现的接口,例如:

public class DuckbillsController : ApiController
{
    IDuckbillRepository _platypiRepository;

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

但是这个构造函数是怎么调用的呢?通过客户端调用包含在此类中的 Web API 方法进行估算,但它如何传递接口类型?或者这不是必须发生的(构造函数没有被任何人/从任何地方显式调用)?

更新

规范示例显示在接口声明前附加“私有只读”,但这不是编译所必需的。是否有一个编译,我的意思是令人信服的理由,让我在前面加上“私有只读”?

4

3 回答 3

19

由于在任何地方都没有这方面的文档(官方文档只是讨论了用 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它在每个请求上创建的范围。

于 2016-06-14T15:47:29.767 回答
8

控制器工厂为您创建它们......您需要看看依赖注入。

试试 Autofac,它对 MVC 有很好的集成。

于 2013-12-23T23:05:24.273 回答
6

你必须使用依赖注入(结构映射,ninject)。如果您不想使用 DI,那么您必须提供一个重载构造函数,如下所示

public DuckbillsController():this( new DuckbillRepository())
{
}
于 2013-12-23T23:05:12.883 回答