2

組織内の他の開発チームがMVCアプリケーションを構築するために使用する内部アプリケーションフレームワークを作成しています。その一環として、すべてのビューのメニュー構造を作成しています。これは、構成から読み取られ、現在のユーザーのアクセス許可に基づいて変更されます。フレームワークの一部としてメニューを作成するために、メニューを構築するWebViewPageためにに依存する必要があるカスタムHTMLヘルパークラスを使用してカスタム実装を作成しましたApplicationDataReader

WebViewPageMVCにはパラメーターなしのコンストラクターが必要であると説明しているさまざまな投稿を読んだので、プロパティインジェクションを使用する必要があります。Autofac MVC3 Integrationを構成しました。これには、の登録も含まれますViewRegistrationSource。問題は、依存プロパティにアクセスすると、常にnullになることです。

これが、私が行おうとしている呼び出しのカスタムビューページとヘルパーです。

public abstract class OuBaseViewPage<TModel> : WebViewPage<TModel> where TModel : class
{
    public OuHelper<TModel> Ou { get; set; }

    public override void InitHelpers()
    {
        base.InitHelpers();
        Ou = new OuHelper<TModel>(ViewContext, this);
    }
}

public class OuHelper<TModel> where TModel : class
{
    public OuHelper(ViewContext viewContext, IViewDataContainer viewDataContainer)
        : this(viewContext, viewDataContainer, RouteTable.Routes)
    {
    }

    public OuHelper(ViewContext viewContext, IViewDataContainer viewDataContainer, RouteCollection routeCollection)
    {
        ViewContext = viewContext;
        ViewData = new ViewDataDictionary<TModel>(viewDataContainer.ViewData);
    }

    public ViewDataDictionary<TModel> ViewData { get; private set; }

    public ViewContext ViewContext { get; private set; }

    public IList<BusinessFocusArea> ReadFocusAreas()
    {
        // this is null - yes, service location, but an isolated instance of...
        return DependencyResolver.Current.GetService<IDataReader>().Read();
    }
}

InitHelpersこの問題は、が呼び出される前に(を介してLayout.Execute())呼び出されているという事実に起因しているApplication_Startため、依存関係は登録されていません。ビューにロジックを挿入するのは良い習慣ではなく、ビューは単純に馬鹿げているはずですが、これはアプリケーションフレームワークであり、フレームワークを使用する開発者が可視化してはならない特定のセットアップ手順を実行する必要があります。

私が従うことができるより良いアプローチはありますか?

ここにも同様の問題があります。Autofacは依存関係をレイアウトビューファイルに挿入できますか?

4

1 に答える 1

5

この問題は、Application_Startが呼び出される前に(Layout.Execute()を介して)InitHelpersが呼び出されているという事実に起因します。

以前に何かが呼ばれたとは思いませんApplication_Start。私はあなたの問題を再現することはできません。

これが私が行ったステップであり、完全にうまく機能しました:

  1. インターネットテンプレートを使用して、新しいASP.NETMVC3アプリケーションを作成します
  2. Autofac.Mvc3NuGetをインストールします
  3. ダミーインターフェイスを定義します。

    public interface IDataReader
    {
    
    }
    
  4. そしてダミーの実装:

    public class DataReader : IDataReader
    {
    
    }
    
  5. カスタムヘルパーを定義します。

    public class OuHelper<TModel> where TModel : class
    {
        private readonly IDataReader dataReader;
        public OuHelper(ViewContext viewContext, IViewDataContainer viewDataContainer, IDataReader dataReader)
            : this(viewContext, viewDataContainer, RouteTable.Routes, dataReader)
        {
        }
    
        public OuHelper(ViewContext viewContext, IViewDataContainer viewDataContainer, RouteCollection routeCollection, IDataReader dataReader)
        {
            ViewContext = viewContext;
            ViewData = new ViewDataDictionary<TModel>(viewDataContainer.ViewData);
            this.dataReader = dataReader;
        }
    
        public ViewDataDictionary<TModel> ViewData { get; private set; }
    
        public ViewContext ViewContext { get; private set; }
    
        public IDataReader DataReader
        {
            get { return this.dataReader; }
        }
    
    }
    
  6. このヘルパーを使用してカスタムWebViewPageを定義します。

    public abstract class OuBaseViewPage<TModel> : WebViewPage<TModel> where TModel : class
    {
        public OuHelper<TModel> Ou { get; set; }
    
        public override void InitHelpers()
        {
            base.InitHelpers();
            var dataReader = DependencyResolver.Current.GetService<IDataReader>();
            Ou = new OuHelper<TModel>(ViewContext, this, dataReader);
        }
    }
    
  7. デフォルトのビューページを次のカスタムページに置き換えます~/Views/web.config

    <pages pageBaseType="MvcApplication1.OuBaseViewPage">
    
  8. 次の場所でコンテナを構成しますApplication_Start

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);
    
        var builder = new ContainerBuilder();
        builder.RegisterControllers(typeof(MvcApplication).Assembly);
        builder.RegisterType<DataReader>().As<IDataReader>();
        var container = builder.Build();
        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
    }
    
  9. これで、_Layoutを含むすべてのビューで問題なくカスタムヘルパーを問題なく使用できるようになりました。

    @Ou.DataReader.GetType()
    

もちろん、この例では、IDataReader依存関係をパブリックプロパティとして公開して、依存関係が常に挿入され、nullになることはないことを示しています。もちろん、特定のコードでは、ヘルパー内のプライベート読み取り専用フィールドのみを使用してタスクを実行できます。

于 2013-02-18T11:15:56.257 に答える