2011-02-25 11 views
5

Al igual que puedo establecer el DefaultControllerFactory a mi propia en el global.asax llamando ControllerBuilder.Current.SetControllerFactory() y proporcionar una implementación personalizada de la fábrica, es posible proporcionar algún modo la aplicación con mi propia implementación de la WebPageRazorHostFactory?personalizada WebPageRazorHostFactory

Lo que quiero lograr es encapsular las vistas en un contenedor IoC para proporcionar inyección de dependencia. He leído el siguiente artículo sobre Haacked: http://haacked.com/archive/2011/02/21/changing-base-type-of-a-razor-view.aspx y creo que esto podría agregar a esa solución.

Lo siguiente no parecen funcionar y arroja un error:

Unable to cast object of type 'ASP._Page_Views__ViewStart_cshtml' to type 'System.Web.WebPages.StartPage

Global.asax: (proyecto de C#)

protected void Application_Init() 
    { 
     System.Web.WebPages.Razor.RazorBuildProvider.RegisterBuildProvider("cshtml", typeof(DefaultRazorBuildProvider)); 
    } 

Las definiciones de clases: (VB Project)

Public Class DefaultRazorBuildProvider : Inherits System.Web.WebPages.Razor.RazorBuildProvider 
    Private Shared _factories As New ConcurrentDictionary(Of String, Func(Of IKernel, DefaultWebPageRazorHostFactory))(StringComparer.OrdinalIgnoreCase) 
    Private Shared _kernel As IKernel 

    Friend Shared TypeFactory As Func(Of String, Type) = AddressOf DefaultTypeFactory 

    Public Shared Function GetKernel() As IKernel 
     If _kernel Is Nothing Then Throw New NullReferenceException("_kernel is not set") 

     Return _kernel 
    End Function 

    Public Shared Sub SetKernel(ByVal kernel As IKernel) 
     _kernel = kernel 
    End Sub 

    Public Shared Function CreateHostFromConfig(ByVal virtualPath As String) As WebPageRazorHost 
     Return CreateHostFromConfig(virtualPath, Nothing) 
    End Function 

    Public Shared Function CreateHostFromConfig(ByVal virtualPath As String, ByVal physicalPath As String) As WebPageRazorHost 
     If [String].IsNullOrEmpty(virtualPath) Then 
      Throw New ArgumentNullException("virtualPath") 
     End If 

     Return CreateHostFromConfigCore(GetRazorSection(virtualPath), virtualPath, physicalPath) 
    End Function 

    Public Shared Function CreateHostFromConfig(ByVal config As RazorWebSectionGroup, ByVal virtualPath As String) As WebPageRazorHost 
     Return CreateHostFromConfig(config, virtualPath, Nothing) 
    End Function 

    Public Shared Function CreateHostFromConfig(ByVal config As RazorWebSectionGroup, ByVal virtualPath As String, ByVal physicalPath As String) As WebPageRazorHost 
     If config Is Nothing Then 
      Throw New ArgumentNullException("config") 
     End If 
     If [String].IsNullOrEmpty(virtualPath) Then 
      Throw New ArgumentNullException("virtualPath") 
     End If 

     Return CreateHostFromConfigCore(config, virtualPath, physicalPath) 
    End Function 

    Friend Shared Function CreateHostFromConfigCore(ByVal config As RazorWebSectionGroup, ByVal virtualPath As String) As WebPageRazorHost 
     Return CreateHostFromConfigCore(config, virtualPath, Nothing) 
    End Function 




    Private Shared Function CreateFactory(ByVal typeName As String) As Func(Of IKernel, DefaultWebPageRazorHostFactory) 
     Dim factoryType As Type = TypeFactory(typeName) 
     If factoryType Is Nothing Then 
      Throw New InvalidOperationException("Factory type not valid") 
     End If 



     Dim param = Expression.Parameter(GetType(IKernel)) 

     Dim body = Expression.[New](factoryType.GetConstructor(New Type() {GetType(IKernel)}), param) 
     Return Expression.Lambda(Of Func(Of IKernel, DefaultWebPageRazorHostFactory))(body, param).Compile() 
    End Function 



    Public Shared Sub ApplyConfigurationToHost(ByVal config As RazorPagesSection, ByVal host As WebPageRazorHost) 
     host.DefaultPageBaseClass = config.PageBaseType 

     For Each import As String In config.Namespaces.OfType(Of NamespaceInfo)().[Select](Function(ns) ns.[Namespace]) 
      host.NamespaceImports.Add(import) 
     Next 
    End Sub 


    Friend Shared Function CreateHostFromConfigCore(ByVal config As RazorWebSectionGroup, ByVal virtualPath As String, ByVal physicalPath As String) As WebPageRazorHost 

     virtualPath = EnsureAppRelative(virtualPath) 

     If virtualPath.StartsWith("~/App_Code", StringComparison.OrdinalIgnoreCase) Then 
      Return New WebCodeRazorHost(virtualPath, physicalPath) 
     End If 

     Dim factory As DefaultWebPageRazorHostFactory = Nothing 
     If config IsNot Nothing AndAlso config.Host IsNot Nothing AndAlso Not [String].IsNullOrEmpty(config.Host.FactoryType) Then 
      Dim factoryCreator As Func(Of IKernel, DefaultWebPageRazorHostFactory) = _factories.GetOrAdd(config.Host.FactoryType, CreateFactory(config.Type)) 
      Debug.Assert(factoryCreator IsNot Nothing) 
      factory = factoryCreator(_kernel) 
     End If 

     Dim host As WebPageRazorHost = (If(factory, New DefaultWebPageRazorHostFactory(_kernel))).CreateHost(virtualPath, physicalPath) 

     If config IsNot Nothing AndAlso config.Pages IsNot Nothing Then 
      ApplyConfigurationToHost(config.Pages, host) 
     End If 

     Return host 
    End Function 

    Friend Shared Function GetRazorSection(ByVal virtualPath As String) As RazorWebSectionGroup 
     Return New RazorWebSectionGroup() With { _ 
      .Host = DirectCast(WebConfigurationManager.GetSection(HostSection.SectionName, virtualPath), HostSection), _ 
      .Pages = DirectCast(WebConfigurationManager.GetSection(RazorPagesSection.SectionName, virtualPath), RazorPagesSection) _ 
     } 
    End Function 

    Private Shared Function EnsureAppRelative(ByVal virtualPath As String) As String 
     If HostingEnvironment.IsHosted Then 
      virtualPath = VirtualPathUtility.ToAppRelative(virtualPath) 
     Else 
      If virtualPath.StartsWith("/", StringComparison.Ordinal) Then 
       virtualPath = "~" & virtualPath 
      ElseIf Not virtualPath.StartsWith("~/", StringComparison.Ordinal) Then 
       virtualPath = "~/" & virtualPath 
      End If 
     End If 
     Return virtualPath 
    End Function 

    Private Shared Function DefaultTypeFactory(ByVal typeName As String) As Type 
     Return BuildManager.[GetType](typeName, False, False) 
    End Function 
End Class 

Public Class DefaultWebPageRazorHostFactory : Inherits System.Web.WebPages.Razor.WebRazorHostFactory 
    Private _kernel As IKernel 

    Public Sub New() 
     Me._kernel = Nothing 
    End Sub 

    Public Sub New(ByVal kernel As IKernel) 
     Me._kernel = kernel 
    End Sub 

    Public Overrides Function CreateHost(ByVal virtualPath As String, ByVal physicalPath As String) As System.Web.WebPages.Razor.WebPageRazorHost 
     Return New DefaultWebPageRazorHost(Me._kernel, virtualPath, physicalPath) 
    End Function 
End Class 

Public Class DefaultWebPageRazorHost : Inherits System.Web.WebPages.Razor.WebPageRazorHost 
    Private _kernel As IKernel 

    Sub New(ByVal kernel As IKernel, ByVal virtualPath As String, ByVal physicalPath As String) 
     MyBase.New(virtualPath, physicalPath) 
     Me._kernel = kernel 
    End Sub 
End Class 

Respuesta

8

Yes; en Web.config:

<system.web.webPages.razor> 
    <host factoryType="MyProject.MyWebPageRazorHost" /> 
    <pages pageBaseType="MyProject.CustomWebPage"> 
     <namespaces> 
      <add namespace="MyProject.SomeNamespace" /> 
     </namespaces> 
    </pages> 
</system.web.webPages.razor> 

EDITAR

Para crear el huésped en el código, puede heredar RazorBuildProvider y reemplazar el método CreateHost, a continuación, registrar su versión heredada de CSHTML y VBHTML.
En su reemplazo, deberá devolver un WebCodeRazorHost para las páginas dentro de App_Code.

Debe descargar the source code; Te ayudará tremendamente.
Mire en mvc3-rtm-sources\webpages\src\System.Web.WebPages.Razor.

+0

Me refiero a configurarlo en 'global.asax' para que pueda proporcionar el kernel de Windsor (el framework IoC que estoy usando) – Ropstah

+1

Buena pregunta; Déjame ver en el interior. Al menos, podría crear un contenedor que cree una instancia interna desde IoC. – SLaks

+0

@Ropstah: aquí tienes. – SLaks