この記事 によると、コントローラーには、実装するインターフェイスを渡すコンストラクターが必要です。
public class DuckbillsController : ApiController
{
IDuckbillRepository _platypiRepository;
public DuckbillsController(IDuckbillRepository platypiRepository)
{
if (platypiRepository == null)
{
throw new ArgumentNullException("platypiRepository is null");
}
_platypiRepository = platypiRepository;
}
}
しかし、このコンストラクターはどのように呼ばれますか?このクラスに含まれるWebAPIメソッドを呼び出すクライアントを介した計算ですが、どのようにしてインターフェイスタイプが渡されますか?または、それが発生する必要はありません(コンストラクターは誰からも/どこからでも明示的に呼び出されません)?
正規の例では、インターフェイス宣言の前に「プライベート読み取り専用」が追加されていますが、コンパイルする必要はありません。 「プライベート読み取り専用」を追加するためのコンパイル、つまり説得力のある理由はありますか?
コントローラファクトリがそれらを作成します...依存性注入を確認する必要があります。
Autofacを試してみてください。MVCとの統合が優れています。
これに関するドキュメントはどこにもありません(公式ドキュメントは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
twice --1回はIDependencyResolver
に、もう1回はリクエストごとに作成するスコープに実装する必要があるということです。
依存性注入(structuremap、ninject)は何でも使用する必要があります。 DIを使用したくない場合は、以下に示すようにオーバーロードコンストラクターを提供する必要があります。
public DuckbillsController():this( new DuckbillRepository())
{
}