2012-01-17 3 views
1

私は、サービスをプロパティ(ロギングサービスを想定)がMVC3プロジェクト内にあるカスタムWebViewPageでWindsorのIDependencyResolver実装を使用しています。誰が_Layout.cshtmlを作成していますか

サービスはすべてのビューに挿入されます(作成はIDependencyResolverを通過します)。

問題は、_Layout.cshtml(レイアウト)ではサービスがnullのままであることです。

だから、それはIDependencyResolverで作成されていないので、誰がレイアウトを作成しているのですか?

編集:その後、

public abstract class WebViewPage<TModel> : System.Web.Mvc.WebViewPage<TModel> 
{ 
    public ILocalizer Localizer { get; set; } 
} 

からweb.configファイルの両方のsystem.web.webPages.razorとのsystem.webセクション〜で

<pages pageBaseType="[full namespace].WebViewPage"> 

/ビュー 、最終的に依存関係リゾルバ:

public class WindsorDependencyResolver : IDependencyResolver 
{ 
    private readonly IKernel kernel; 

    public WindsorDependencyResolver(IKernel kernel) 
    { 
     this.kernel = kernel; 
    } 

    public object GetService(Type serviceType) 
    { 
     return kernel.HasComponent(serviceType) ? kernel.Resolve(serviceType) : RegisterAndResolve(serviceType); 
    } 

    public IEnumerable<object> GetServices(Type serviceType) 
    { 
     return kernel.HasComponent(serviceType) ? kernel.ResolveAll(serviceType).Cast<object>() : new object[] { }; 
    } 

    private object RegisterAndResolve(Type serviceType) 
    { 
     if (!serviceType.IsAbstract && !serviceType.IsInterface) 
     { 
      kernel.Register(Component.For(serviceType).ImplementedBy(serviceType).LifestylePerWebRequest()); 
      return kernel.Resolve(serviceType); 
     } 
     return null; 
    } 
} 

依存リゾルバはGlobal.asax.csに設定されている:

var dependencyResolver = new WindsorDependencyResolver(container.Kernel); 
DependencyResolver.SetResolver(dependencyResolver); 

任意のビューがインスタンス化されるとき(Index.cshtmlは)依存リゾルバからのgetServiceメソッドが呼び出され、ビューはコンテナによって作成されます。 _Layout.cshtmlの場合、そのメソッドは呼び出されません。

だから私はIndex.cshtmlでこれを行うとき:@Localizer.Localize(....) localizaerサービスがnullではないですが、_Layout.cshtmlで、それはnullで、具体的な問題は、私はビューに何をローカライズすることはできません(と私は望んでいないことサポートされているロケールごとに表示する)。

私はそれが今より明らかに希望です。

編集:私はMVCのソースをチェックする時間を持っていなかったが、答えは確かに存在している必要があり、この1 ... に まだ明確な答え...

+2

なぜあなたはあなたの見解であなたのサービスを手に入れようとしていますか? – Hammerstein

+0

より良い例は、ある種のローカリゼーションサービスです。 – Padel

+0

私は同じ問題に遭遇しています。これを理解することに運がありましたか? – BrooklynDev

答えて

1

それはによって作成されていますRazorビューエンジン基本型は、pagesノードのpageBaseType属性の~/views/web.configの内部に定義されています。デフォルトではSystem.Web.Mvc.WebViewPageです。あなたは基本タイプを設定し~/views/web.configで、その後

public abstract class MyWebViewPage<T> : WebViewPage<T> 
{ 
    public MyWebViewPage() 
    { 
     SomeDependency = DependencyResolver.Current.GetService<IFoo>(); 
    } 

    public IFoo SomeDependency { get; private set; } 
} 

:あなたは(_layoutまたはいくつかの他の図である場合に関係なく)カスタムページの基本型を定義することができ、あなたのカミソリテンプレートに依存性注入をやってみたかった場合

@model MyViewModel 
@SomeDependency.FooBar() 
<pages pageBaseType="AppName.Controllers.MyWebViewPage"> 

はその後、すべてのテンプレートが利用可能 SomeDependency性質を持っています

ただし、状況によってはこれが適切な設計選択ではない可能性があります。あなたのビューにいくつかのカスタムHTMLヘルパーを注入しようとするなら、それは問題ありません。しかし、ドメイン・サービスを注入し、ビュー・モデルを使用するのではなく、ビューの依存関係を左右から取得しようとする場合、ビューの責任は依存関係をフェッチすることではないため、深刻な設計ミスです。その責任は、ビューモデルの形式で渡される情報を表示することです。この情報がどこから来るのかは、見解の責任ではありません。データのフェッチを調整し、それをビューに渡されるビューモデルに入れるのはコントローラです。

+0

それはまさに私がやっていることです。そして問題は、すべてのビューで@Localizer(この例のように)を呼び出すことができますが、_Layout.cshtml(nullの場合)にあります。 – Padel

+0

@Padel、問題を再現できません。私の例では、依存関係リゾルバを使用している 'MyWebViewPage'コンストラクタで依存関係がどのように取得されるのか分かりましたか?それはサービスロケータパターンと呼ばれています。それは依存症注射に比べていくつかの純粋主義者による反パターンと見なされますが、それはあなたの唯一のRazorの希望です。おそらく将来のバージョンのエンジンでは、実際の依存関係注入を使用するために提供されるでしょう。 –

+0

すべてが上記のように実装されていますが、1つは例外です。つまり、依存関係リゾルバを明示的に呼び出さないことです。依存リゾルバは、IoCコンテナ(すなわちWindsor)をMVCアーキテクチャにプラグインする。私は誰もが何が起こっているかを見るために私の投稿を編集します。 – Padel