6

Microsoft Unity を使用して、ASP.NET MVC 3 アプリケーションで依存性注入を機能させようとしています。最初に、独自の IDependencyResolver を実装し、次のように Global.asax ファイルでアクティブにしました。

DependencyResolver.SetResolver(new UnityDependencyResolver(container));

コントローラー インジェクション (コンストラクターと [Dependency] 属性の両方を介して) を機能させるために、他に何もする必要がないことがわかりました。デフォルトのビューエンジンを使用すると、[Dependency] 属性を標準ビューで機能させることができますが、レイアウトビューでは機能しません。これをレイアウトビューでも機能させることは可能ですか?

ただし、CreateView/CreatePartialView メソッドをオーバーライドし、独自のカスタム ビューを返す (IView を実装する) VirtualPathProviderViewEngine から継承する独自のビュー エンジンを実装しました。以下のカスタム ビューの Render メソッドを参照してください。

public void Render(ViewContext viewContext, TextWriter writer) {
    var webViewPage = DependencyResolver.Current.GetService(_type) as WebViewPage;
    //var webViewPage = Activator.CreateInstance(_type) as WebViewPage;

    if (webViewPage == null)
        throw new InvalidOperationException("Invalid view type");

    webViewPage.VirtualPath = _virtualPath;
    webViewPage.ViewContext = viewContext;
    webViewPage.ViewData = viewContext.ViewData;
    webViewPage.InitHelpers();

    WebPageRenderingBase startPage = null;

    if (_runViewStartPages)
        startPage = StartPage.GetStartPage(webViewPage, "_ViewStart", _viewStartFileExtensions);

    var pageContext = new WebPageContext(viewContext.HttpContext, webViewPage, null);
    webViewPage.ExecutePageHierarchy(pageContext, writer, startPage);
}

コメントアウトされた行で、ビュー内の依存性注入が完全に失われたため、上記の行に変更しました。これは、標準ビューでは正常に機能しますが、レイアウト ビューでは機能しません。上記をレイアウトビューでも機能するように変更する方法を教えていただければ幸いです。

最後に、アクションフィルターインジェクションも機能させようとしています。私は2つの異なるケースを見つけました:

  1. 属性を介してフィルターをアクションに適用します。

  2. グローバル フィルターとして定義します。たとえば、次のようになります。

    GlobalFilters.Filters.Add(新しい TestAttribute());

どちらも依存関係リゾルバーを使用していないようです。したがって、追加の作業を行う必要があります。より良い方法があれば修正してください。最初のシナリオを有効にするために、次のことを行いました。

public class UnityFilterAttributeFilterProvider : FilterAttributeFilterProvider {
    private IUnityContainer _container;

    protected override IEnumerable<FilterAttribute> GetControllerAttributes(ControllerContext controllerContext, ActionDescriptor actionDescriptor) {
        var attributes = base.GetControllerAttributes(controllerContext, actionDescriptor);

        foreach (var attribute in attributes) {
            _container.BuildUp(attribute.GetType(), attribute);
        }

        return attributes;
    }

    protected override IEnumerable<FilterAttribute> GetActionAttributes(ControllerContext controllerContext, ActionDescriptor actionDescriptor) {
        var attributes = base.GetActionAttributes(controllerContext, actionDescriptor);

        foreach (var attribute in attributes) {
            _container.BuildUp(attribute.GetType(), attribute);
        }

        return attributes;
    }
}

そして、これを Global.asax ファイル内で次のように定義しました。

FilterProviders.Providers.Remove(FilterProviders.Providers.Single(f => f is FilterAttributeFilterProvider));
FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(container));

これは問題なく動作しますが、これが正しい方法であるかどうか疑問に思っていましたか? 2 番目のケースを解決するために、グローバル フィルターを定義した場所を次のように変更しました。

GlobalFilters.Filters.Add(DependencyResolver.Current.GetService<TestAttribute>());

これも機能するようになりましたが、これは正しい方法ですか?

助けていただければ幸いです。ありがとう

4

1 に答える 1