15

この記事によると、コントローラーには、実装されるインターフェースを取得するコンストラクターが必要です。

public class DuckbillsController : ApiController
{
    IDuckbillRepository _platypiRepository;

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

しかし、このコンストラクターはどのように呼び出されるのでしょうか? このクラスに含まれる Web API メソッドを呼び出すクライアントを介して計算されますが、どのようにして Interface 型が渡されるのでしょうか? それとも、そうする必要はありませんか (コンストラクターは誰からもどこからも明示的に呼び出されません)。

アップデート

正規の例では、Interface 宣言の前に「private readonly」が追加されていますが、コンパイルする必要はありません。「プライベート読み取り専用」を先頭に追加するためのコンパイル、つまり説得力のある理由はありますか?

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 2 回実装する必要があることです。1回目IDependencyResolverは各リクエストで作成されるスコープ用です。

于 2016-06-14T15:47:29.767 に答える