83

IoCコンテナーを使用してASP.NETWebAPIコントローラーに依存関係を注入することに成功した人はいますか?私はそれを機能させることができないようです。

これが私が今していることです。

私の中で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 cancelToken)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では、コントローラーファクトリが依存関係を解決する必要があると判断するため、コントローラー自体の登録がないことに注意してください。

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

4

11 に答える 11

43

理解した。

ApiControllersの場合、MVC 4 はSystem.Web.Http.Dispatcher.IHttpControllerFactorySystem.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.
       });
}
于 2012-03-03T06:38:28.350 に答える
38

ここで正しく機能するより良い解決策があります

http://www.asp.net/web-api/overview/extensibility/using-the-web-api-dependency-resolver

于 2012-05-14T23:45:52.307 に答える
24

これらすべてを整理し、IDisposable コンポーネントにも対応する Unity.WebApi NuGet パッケージを確認することをお勧めします。

見る

http://nuget.org/packages/Unity.WebAPI

また

http://www.devtrends.co.uk/blog/introducing-the-unity.webapi-nuget-package

于 2012-03-20T16:30:34.050 に答える
10

Microsoft は、このためのパッケージを作成しました。

パッケージ マネージャー コンソールから次のコマンドを実行します。

インストール パッケージ Unity.AspNet.WebApi

Unity が既にインストールされている場合は、App_Start\UnityConfig.cs を上書きするかどうかを尋ねられます。いいえと答えて続行します。

他のコードを変更する必要はなく、DI (ユニティあり) が機能します。

于 2015-05-20T22:48:07.320 に答える
2

最近の RC では、SetResolver メソッドがなくなっていることがわかりました。コントローラーと webapi の両方の IoC を有効にするために、Unity.WebApi (NuGet) と次のコードを使用します。

public static class Bootstrapper
{
    public static void Initialise()
    {
        var container = BuildUnityContainer();

        GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);

        ControllerBuilder.Current.SetControllerFactory(new DefaultControllerFactory(new ControllerActivator()));
    }

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

        container.Configure(c => c.Scan(scan =>
        {
            scan.AssembliesInBaseDirectory();
            scan.With<UnityConfiguration.FirstInterfaceConvention>().IgnoreInterfacesOnBaseTypes();
        }));

        return container;
    }
}

public class ControllerActivator : IControllerActivator
{
    IController IControllerActivator.Create(RequestContext requestContext, Type controllerType)
    {
        return GlobalConfiguration.Configuration.DependencyResolver.GetService(controllerType) as IController;
    }
}

また、IoC マジックには UnityConfiguration (これも NuGet から) を使用します。;)

于 2012-07-06T12:33:31.297 に答える
1

同じ例外がスローされました。私の場合、MVC3 バイナリと MVC4 バイナリの間に競合がありました。これにより、コントローラーが IOC コンテナーに正しく登録されませんでした。web.config をチェックして、正しいバージョンの MVC を指していることを確認してください。

于 2012-03-02T16:14:56.070 に答える