1. ホーム
  2. c#

[解決済み] Unityを使用したASP.NET Web APIコントローラへの依存関係のインジェクションができない

2023-07-08 16:14:51

質問

ASP.NET WebAPI コントローラに依存性を注入するために IoC コンテナを使用して実行することに成功した人はいますか。私はそれを動作させることができないようです。

これは、私が今やっていることです。

私の global.ascx.cs :

    public static void RegisterRoutes(RouteCollection routes)
    {
            // code intentionally omitted 
    }

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);

        IUnityContainer container = BuildUnityContainer();

        System.Web.Http.GlobalConfiguration.Configuration.ServiceResolver.SetResolver(
            t =>
            {
                try
                {
                    return container.Resolve(t);
                }
                catch (ResolutionFailedException)
                {
                    return null;
                }
            },
            t =>
            {
                try
                {
                    return container.ResolveAll(t);
                }
                catch (ResolutionFailedException)
                {
                    return new System.Collections.Generic.List<object>();
                }
            });

        System.Web.Mvc.ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory(container)); 

        BundleTable.Bundles.RegisterTemplateBundles();
    }

    private static IUnityContainer BuildUnityContainer()
    {
        var container = new UnityContainer().LoadConfiguration();

        return container;
    }

私のコントローラファクトリです。

public class UnityControllerFactory : DefaultControllerFactory
            {
                private IUnityContainer _container;

                public UnityControllerFactory(IUnityContainer container)
                {
                    _container = container;
                }

                public override IController CreateController(System.Web.Routing.RequestContext requestContext,
                                                    string controllerName)
                {
                    Type controllerType = base.GetControllerType(requestContext, controllerName);

                    return (IController)_container.Resolve(controllerType);
                }
            }

依存関係を解決するために私のユニティファイルを見ることはないようで、次のようなエラーが発生します。

タイプのコントローラを作成しようとしたときにエラーが発生しました。 PersonalShopper.Services.WebApi.Controllers.ShoppingListController' タイプのコントローラを作成しようとしたときにエラーが発生しました。 コントローラにパラメータなしのパブリックコンストラクタがあることを確認してください。

で System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpControllerContext controllerContext, Type controllerType) at System.Web.Http.Dispatcher.DefaultHttpControllerFactory.CreateInstance(HttpControllerContext ControllerContext, HttpControllerDescriptor controllerDescriptor) at System.Web.Http.Dispatcher.DefaultHttpControllerFactory.CreateController(HttpControllerContext ControllerContext, String controllerName) at System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncInternal(HttpRequestMessage request, CancellationToken キャンセルトークン) at System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync(HttpRequestMessage request, CancellationToken cancelToken) を実行します。

コントローラは以下のような感じです。

public class ShoppingListController : System.Web.Http.ApiController
    {
        private Repositories.IProductListRepository _ProductListRepository;


        public ShoppingListController(Repositories.IUserRepository userRepository,
            Repositories.IProductListRepository productListRepository)
        {
            _ProductListRepository = productListRepository;
        }
}

私のユニティファイルはこんな感じです。

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
  <container>
    <register type="PersonalShopper.Repositories.IProductListRepository, PersonalShopper.Repositories" mapTo="PersonalShopper.Implementations.MongoRepositories.ProductListRepository, PersonalShopper.Implementations" />
  </container>
</unity>

以前のバージョンの mvc では、コントローラファクトリが依存関係を解決する必要があることを把握していたため、コントローラ自体の登録はしていないことに注意してください。

私のコントローラファクトリは決して呼び出されていないようです。

どのように解決するのですか?

解決しました。

のために ApiControllers を使用することで、MVC 4 では System.Web.Http.Dispatcher.IHttpControllerFactory を使用します。 System.Web.Http.Dispatcher.IHttpControllerActivatorを使用します。 を使用してコントローラを作成します。 これらの実装が何であるかを登録する静的メソッドがない場合、それらが解決されると、mvcフレームワークは依存性解決手段で実装を探し、見つからない場合は、デフォルトの実装を使用します。

私は以下のようにすることで、コントローラの依存性の統一的な解決を動作させました。

UnityHttpControllerActivatorを作成しました。

public class UnityHttpControllerActivator : IHttpControllerActivator
{
    private IUnityContainer _container;

    public UnityHttpControllerActivator(IUnityContainer container)
    {
        _container = container;
    }

    public IHttpController Create(HttpControllerContext controllerContext, Type controllerType)
    {
        return (IHttpController)_container.Resolve(controllerType);
    }
}

そのコントローラアクティベータを実装としてユニティコンテナ自体に登録。

protected void Application_Start()
{
    // code intentionally omitted

    IUnityContainer container = BuildUnityContainer();
    container.RegisterInstance<IHttpControllerActivator>(new UnityHttpControllerActivator(container));

    ServiceResolver.SetResolver(t =>
       {
         // rest of code is the same as in question above, and is omitted.
       });
}