Simple Injectorで基本的なコンストラクターDIを実行しようとしていますが、Web APIコントローラーの依存関係を解決できないようです。
SimpleInjectorWebApiDependencyResolver
があります。これは、見つかった here と同じです。これは問題ではないようですが、次のエラーが表示されます。
タイプ「MyProject.API.ArticleController」にはデフォルトのコンストラクタがありません
System.ArgumentException at
System.Web.Http.Internal.TypeActivator.Create [TBase](Type instanceType)のSystem.Linq.Expressions.Expression.New(Type type)System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request、Type controllerType) 、Func`1&アクティベーター)System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request、HttpControllerDescriptor controllerDescriptor、Type controllerType)で
現在の状態/呼び出し順序から何かを変更する必要があるかどうかについて、誰かが私にいくつかの提案を提供できれば幸いです。
ArticleController(基本構造):
public class ArticleController : ApiController
{
private readonly IArticleRepository articleRepository;
private readonly IUserRepository userRepository;
private readonly IReleaseRepository releaseRepository;
public ArticleController(IArticleRepository articleRepository, IUserRepository userRepository, IReleaseRepository releaseRepository)
{
this.articleRepository = articleRepository;
this.userRepository = userRepository;
this.releaseRepository = releaseRepository;
}
// GET api/Article
public IEnumerable<Article> GetArticles(){ // code }
// GET api/Article/5
public Article GetArticle(int id){ // code }
// PUT api/Article/5
public HttpResponseMessage PutArticle(int id, Article article){ // code }
// POST api/Article
public HttpResponseMessage PostArticle(ArticleModel article){ // code }
// DELETE api/Article/5
public HttpResponseMessage DeleteArticle(int id){ // code }
}
SimpleInjectorInitializer:
public static class SimpleInjectorInitializer
{
public static void Initialize()
{
var container = new Container();
InitializeContainer(container);
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
container.RegisterMvcAttributeFilterProvider();
container.Verify();
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
}
private static void InitializeContainer(Container container)
{
container.Register<IArticleRepository, ArticleRepository>();
container.Register<IUserRepository, UserRepository>();
container.Register<IReleaseRepository, ReleaseRepository>();
}
}
Global.asax.cs:
public class WebApiApplication : System.Web.HttpApplication
{
private void ConfigureApi()
{
// Create the container as usual.
var container = new Container();
// Verify the container configuration
// container.Verify();
// Register the dependency resolver.
GlobalConfiguration.Configuration.DependencyResolver =
new SimpleInjectorWebApiDependencyResolver(container);
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
ConfigureApi();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
TLTR:この問題は、Web APIがコントローラータイプの解決を処理する暗黙的な方法が原因です。 Web APIコントローラーを明示的に登録すると、問題の場所がわかります。
以下は、裏側で何が起こっているかを段階的に示しています。
System.Web.Http.DefaultHttpControllerActivator
_はSimpleInjectorWebApiDependencyResolver
を呼び出し、APIコントローラーの作成を要求します。SimpleInjectorWebApiDependencyResolver
は、その呼び出しを_SimpleInjector.Container
_インスタンスに転送します。Container
インスタンスには、そのAPIコントローラーの明示的な登録はありません(空のコンテナーをリゾルバーに提供したため)。IServiceProvider.GetService
_メソッドを介して要求され、タイプが明示的に登録されていないためです。SimpleInjectorWebApiDependencyResolver
のGetService
メソッドもnull
を返します。定義によりnullを返す必要があるためです。登録が存在しない場合はnullを返す必要があります(現在のところ)。DependencyResolver
はnullを返したため、DefaultHttpControllerActivator
はデフォルトの動作に戻ります。つまり、そのタイプ自体を作成しますが、これにはコントローラーにデフォルトのコンストラクターが必要です。要するに、この問題は、Web APIがコントローラータイプの解決を暗黙的に処理するために発生します。
したがって、ここでの解決策は次のとおりです。
Container
のみがあります。これにより、あらゆる種類のトラブルや設定の複雑化を防ぎます。container.Verify()
を呼び出すことができます。これにより、構成が無効な場合、起動時にアプリケーションが失敗します( 検証可能な構成が重要 )。また、これにより 構成の診断 が可能になり、構成の正確さについてさらに自信が持てます。私 アドバイスはMVCとWeb APIを独自のプロジェクトに配置することです 。これにより、物事がずっと簡単になります。
すべてのWeb APIコントローラーの登録は、次のコードで実行できます。
_container.RegisterWebApiControllers(GlobalConfiguration.Configuration);
_
UPDATE:
このエラーは非常に一般的であるため、新しいバージョンのSimpleInjectorWebApiDependencyResolver
クラスは、コントローラーが入力されたときに単にneverがnull
を返します。要求されます。代わりに、説明的なエラーがスローされます。このため、公式のSimpleInjectorWebApiDependencyResolver
を使用している限り、エラーは表示されなくなります。