2011-10-20 16 views
5

clases Base de página y control de usuario:¿Cómo hacer una clase base para Page y UserControl?

public class MyWebPage : System.Web.UI.Page { } 

public class MyUserControl : System.Web.UI.UserControl { } 

Helper que cualquiera de ellos podría utilizar:

void SetSessionValue<T>(string key, T value) { Session[key] = value; } 

¿Cómo puedo lograr algo como lo siguiente?

public class WebObject // can't inherit from both Page and UserControl { 
    protected void SetSessionValue<T>(string key, T value) { 
     Session[key] = value; 
    } 
} 

public class MyWebPage : WebObject { } 

public class MyUserControl : WebObject { } 

Actualización: Me emocioné por un segundo con la esperanza de que pudiera resolver de esta manera, pero por desgracia no compila.

public class WebObject<T> : T 
{ 
} 
public class MyWebPage : WebObject<System.Web.UI.Page> 
{ 
} 
+1

¿Cuántos métodos como este tendrá y cuánto código habrá en cada método? ¿Por qué no solo duplicar el código?Este one-liner parece demasiado corto para preocuparse por esto. Además, si 'Page' y' UserControl' tienen cualquier clase base común, simplemente podría hacer un método de extensión en ese tipo. P.ej. en 'System.Web.UI.Control' o' System.Web.UI.TemplateControl'; solo podría hacer esto si no necesitara el estado de su clase base personalizada. –

Respuesta

4

No puede. No es fácil de todos modos. Recomiendo simplemente crear una clase base para páginas y controles de usuario, y duplicar el código común en ambos. Dado que los controles de usuario están contenidos en las páginas, también puede delegar métodos de la clase de control de usuario de base a la clase de página de base simplemente echando la propiedad Page a su propio tipo:

// Code in the MyUserControlBase class 
public int SomeCommonMethod() { 
    return ((MyBasePageType)this.Page).SomeCommonMethod(); 
} 

También puede hacer su vida miserable por crear una interfaz implementada por ambas clases base y usar DI para interceptar las llamadas de acceso de método y propiedad, que luego se enrutarían a algún tipo de clase sustituta común que realmente proporcione la implementación. Probablemente no vaya allí :)

+0

terminé haciendo una clase de contexto que se crea en la página base, y colocando un acceso de acceso de propiedad en la base de control utilizando el patrón descrito en su fragmento aquí - gracias. –

1

IIRC tanto de página y control de usuario heredan de TemplateControl por lo que podría ser capaz de heredar de eso.

+0

Sí, estaba mirando eso. Tenga en cuenta que la propiedad Session no está en la clase TemplateControl. Si fuera así, solo tendría que agregar un método de extensión a TemplateControl. – AaronLS

1

Una forma de evitar la duplicación es tener una clase auxiliar, instanciada a través de una propiedad estática y accesible desde cualquier lugar en su UI (Página, UserControl o cualquier otra clase en el nivel UI) .

Algo así como:

public class ApplicationContext 
{ 
    // Private constructor to prevent instantiation except through Current property. 
    private ApplicationContext() {} 

    public static ApplicationContext Current 
    { 
     get 
     { 
      ApplicationContext current = 
       HttpContext.Current.Items["AppContext"] as ApplicationContext; 
      if (current = null) 
      { 
       current = new ApplicationContext(); 
       HttpContext.Current.Items["AppContext"] = current; 
      } 
      return current; 
     } 
    } 

    public void SetSessionValue<T>(string key, T value) 
    { 
     HttpContext.Current.Session[key] = value; 
    } 
    ... etc ... 
} 

Una instancia Application Context solo vivirá durante toda la vida de la petición actual, y se puede utilizar ApplicationContext.Current.SetSessionValue y otros miembros comunes de cualquier parte del código de nivel de interfaz de usuario.

A menudo voy más allá de poner métodos de propósito general como su SetSessionValue en dicha clase de ayuda, y podría tener propiedades específicas de la aplicación allí, p. Ej.

public class ApplicationContext 
{ 
    ... as above ... 

    public ShoppingBasket ShoppingBasket 
    { 
     ShoppingBasket shoppingBasket = 
      HttpContext.Current.Session["Basket"] as ShoppingBasket; 
     if (shoppingBasket == null) 
     { 
      shoppingBasket = ... e.g. retrieve from database 
      HttpContext.Current.Session["Basket"] = shoppingBasket; 
     } 
     return shoppingBasket; 
    } 
} 

De esta manera se puede acceder a la corriente ShoppingBasket instancia en cualquier lugar de la interfaz de usuario sin saber o preocuparse de que se almacenan en caché en la Sesión - eso es un detalle de implementación que sólo conoce su clase ApplicationContext.

0
  • 1) Hacer una clase estática que tiene todas las variables, funciones que necesitan
  • 2) Haga su propia clase de control de usuario y la página, y hacer que estas clases llaman sus funciones estáticas en el Pre_Init y carga anula
  • 3) Haga que cada página herede sus clases base.

Esa es la manera más fácil.

+0

No es una buena idea, creo. Las clases estáticas son el enemigo de la inyección de dependencia y no te permiten burlarte de las pruebas fáciles. También son singletons que pueden no funcionar bien. Si quieres una clase de ayuda que usan ambas clases; crea una clase normal que es la implementación de una interfaz e inyecta la interfaz en los lugares que necesitas en la construcción de esos objetos. De esta forma, puede simular todo lo que desee para una prueba fácil y no terminará con estática que ensucia su código y lo hará más difícil de probar. –

Cuestiones relacionadas