2011-01-17 10 views
5

que tienen dos clases que define así:implemento de la misma clase, solo padres diferentes, ¿cómo lidiar con esto?

public class RoleButton: Button 
{ 
    protected bool PrimaryRole; 
    protected bool SecondaryRole; 

    private string _role; 
    private AuthenticatedPage CurrentPage 
    { 
     get { return (AuthenticatedPage)Page; } 
    } 

    protected UserInfo CurrentUser 
    { 
     get { return CurrentPage.CurrentUser; } 
    } 

    protected void SetRole(string role) 
    { 
     _role = role; 
    } 

    protected override void OnPreRender(EventArgs e) 
    { 
     base.OnInit(e); 

     if (CurrentUser.IsSuperAdmin) return; 
     DataTable dt = CommandController.GetButtonRoleForUserByPortalID(CurrentUser.UserID, 
                     ConvertUtility.ToInt32(AppEnv.PortalId())); 

     if (dt.Rows.Count > 0) 
     { 
      if (dt.Rows.Count > 1) 
      { 
       PrimaryRole = ConvertUtility.ToBoolean(dt.Rows[0][_role]); 
       SecondaryRole = ConvertUtility.ToBoolean(dt.Rows[1][_role]); 

       if (!PrimaryRole && !SecondaryRole) 
       { 
        Visible = false; 
       } 
       else 
       { 
        Visible = true; 
       } 
      } 
      else 
      { 
       PrimaryRole = ConvertUtility.ToBoolean(dt.Rows[0][_role]); 
       Visible = PrimaryRole; 
      } 
     } 
     else 
     { 
      Visible = false; 
     }  
} 


public class RoleImageButton: ImageButton 
{ 
    /// 
    ///same as above 
    /// 
} 

la aplicación de estas clases son exactamente los mismos, así que quiero eliminar esta duplicación, pero no conocer la técnica para hacer esto.

¿Puede mostrarme la forma de hacerlo?

+1

¿El() Código OnPreRender necesitan tener acceso a las variables privadas o protegidas en el botón, clases RoleButton, ImageButton o RoleImageButton? Supongo que sí, pero siempre hay esperanza ... –

+0

JOC, ¿puedes publicar el código que se está duplicando en OnPreRender()? –

+0

Agregué la implementación de clase completa :). Gracias – Vimvq1987

Respuesta

1

Crearía una clase BaseButton que se deriva de Button. Si hay algún cambio específicas a cada botón, a continuación, proceder de la siguiente manera BaseButton:

public class BaseButton : Button 
{ 
    /// 
    protected override void OnPreRender(EventArgs e) 
    { 
     // Common base implementationi 
    }   
} 

public class ImageButton: BaseButton 
{ 
    // Specific implementation 
    public ImageButton() 
    { 
     this.Name = "ImageButton"; 
    } 
} 

public class RoleButton: BaseButton 
{ 
    // Specific implementation 
    public RoleButton() 
    { 
     this.Name = "RoleButton"; 
    } 
} 
+0

+1 porque no veo ninguna razón por la que alguien pueda rechazar esto. –

+0

Probablemente fue downvoted porque uno de esos botones deriva de 'ImageButton', no' Button'. Desafortunadamente, esta respuesta pierde la conexión entre 'RoleImageButton: ImageButton'. Hay un error en el código de ejemplo, también, porque ha declarado 'public class ImageButton: BaseButton', donde lo que quiere decir es' public class RoleImageButton: BaseButton' –

0

Se puede usar un T4 template. Le permitiría tener un solo archivo (la plantilla) que contiene la implementación una vez, y generaría las dos clases con las implementaciones idénticas para usted. (Por supuesto, el código aún estaría duplicado en el ensamblado compilado, pero al menos ya no existe ese problema de mantenimiento para mantenerlos sincronizados).

1

¿Puede tener una clase RoleButton que se ajuste a otros tipos de botones?

Si Button y ImageButton ambos tienen una base común o implementan una interfaz como IButton que podría tener algo como esto:

class RoleButton : IButton 
{ 
    private Button _realButton; 

    public RoleButton(Button realButton) { _realButton = realButton; } 

    // IButton implementation delegates non-role stuff to _realButton 
} 

De esa manera usted no termina encima de duplicar su código RoleButton:

var roleButton = new RoleButton(myButton); 
var roleImageButton = new RoleButton(myImageButton); 
+0

Nuevamente, pierdes la conexión entre 'RoleImageButton: ImageButton' ...' Button' y 'ImageButton' son dos clases distintas en' System.Web.UI.WebControls'; ambas heredan de WebControl. (Bueno, ImageButton hereda de 'System.Web.UI.WebControls.Image', que hereda directamente de WebControl ... el punto es que ImageButton y Button son tan diferentes como Frog y Unicorn) –

+0

Ambos implementan IButtonControl por lo que podría estar capaz de salirse con la tuya. La implementación publicada arriba no parece depender de nada específico de los botones. –

3

El punto de disparo es si necesita o no acceder a variables privadas de cualquiera de esas clases, o propiedades que son específicas para ellas.

Cuando desee encapsular y compartir el comportamiento, utilice el Patrón de comando. Se ve algo como:

public interface ICommand { 
    void ExecuteOnPreRender(WebControl control, EventArgs args); 
} 

// This class encapsulates the functionality common 
// to both OnPreRender commands 
public class SharedPreRenderCommand : ICommand { 
    public void ExecuteOnPreRender(WebControl control, EventArgs args) { 
     // Modify the size, border, etc... any property that is 
     // common to the controls in question 
    } 
} 

public class RoleImageButton : ImageButton { 

    private ICommand onPreRenderCommand = null; 

    public void SetPreRenderCommand (ICommand command) { 
     onPreRenderCommand = command; 
    } 

    protected override void OnPreRender(EventArgs args) { 
     if (null != onPreRenderCommand) { 
      onPreRenderCommand.ExecuteOnPreRender(this, args); 
     } 
     else { 
      base.OnPreRender(args); 
     } 
    } 
} 


public class RoleButton : Button { 

    private ICommand onPreRenderCommand = null; 

    public void SetPreRenderCommand (ICommand command) { 
     onPreRenderCommand = command; 
    } 

    protected override void OnPreRender(EventArgs args) { 
     if (null != onPreRenderCommand) { 
      onPreRenderCommand.ExecuteOnPreRender(this, args); 
     } 
     else { 
      base.OnPreRender(args); 
     } 
    } 
} 

Esto le permite encapsular y extraer funcionalidad ... la limitación, por supuesto, es que no se puede tener acceso a los miembros privados o protegidos, o miembros específicos a RoleButton, etc., porque tienes que pasar una base común al comando. No poder acceder a los miembros específicos de RoleButton/RoleImageButton no debería ser un problema; su código no puede ser código común si utiliza algo específico para cualquiera de estos:)

Si tiene que acceder a miembros privados/protegidos, deberá crear una interfaz que exponga las propiedades e implementarlo por separado para tanto RoleButton como RoleImageButton, y pasan esa interfaz al comando ... pero básicamente estás forzando esas propiedades a ser públicas y hacerlas accesibles a otras clases. Si es absolutamente necesario que haga esto, puedo darle un código de muestra para mostrarle cómo, pero realmente no es una buena idea.

Lo que realmente buscas es herencia múltiple, un concepto que C# no admite.



EDITAR

Hay dos maneras de pelar este gato ...Lo recomendaría el primero, que es encapsular las variables que se van a cambiar en su mando y pasarlo como un parámetro, como por ejemplo:

// Encapsulate these fields if you want to be PC 
public class Roles { 
    public bool PrimaryRole; 
    public bool SecondaryRole; 
} 

public class RoleButton: Button { 
    protected Roles buttonRoles;  
    ... 
} 

public class SharedPreRenderCommand : ICommand { 

    public void ExecuteOnPreRender(WebControl control, Roles roles, EventArgs args) { 
     // Modify the Roles class, which the RoleButton or 
     // RoleImageButton has a handle to 
    } 

} 

otra parte, hacer la clase Roles una estructura y pase por ref. Esto le impide exponer sus roles, lo que le permite mantenerlos como protegidos. Todo lo demás del código de patrón de comando que escribí se usa tal cual.

El segundo enfoque ni siquiera vale la pena mencionarlo ... Lo abandonaré bajo coacción, pero es una mala idea, no me gustaría promocionarlo a menos que me torturaran. : D

HTH,
James

Cuestiones relacionadas