Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 同一类实现,只是不同的父类,如何处理?_C#_.net_Design Patterns - Fatal编程技术网

C# 同一类实现,只是不同的父类,如何处理?

C# 同一类实现,只是不同的父类,如何处理?,c#,.net,design-patterns,C#,.net,Design Patterns,我有两个类的定义如下: public class RoleButton: Button { protected bool PrimaryRole; protected bool SecondaryRole; private string _role; private AuthenticatedPage CurrentPage { get { return (AuthenticatedPage)Page; } } prote

我有两个类的定义如下:

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
   ///
}
class RoleButton : IButton
{
  private Button _realButton;

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

  // IButton implementation delegates non-role stuff to _realButton
}
这些类的实现是完全相同的,所以我想消除这种重复,但我不知道如何实现


你能告诉我怎么做吗?

我将创建一个从
按钮
派生的
基本按钮
类。如果每个按钮都有特定的更改,则从
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";
   }
}

您可以使用。它将允许您拥有一个包含实现的单一文件(模板),并且它将为您生成具有相同实现的两个类。(当然,代码仍然会在编译后的程序集中重复,但至少不再存在保持同步的维护问题。)

是否可以有一个RoleButton类来包装其他按钮类型

如果Button和ImageButton都有一个共同的基础或实现一个像IButton这样的接口,那么您可以有这样的接口:

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
   ///
}
class RoleButton : IButton
{
  private Button _realButton;

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

  // IButton implementation delegates non-role stuff to _realButton
}
这样,您就不会复制角色按钮代码:

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

触发点是您是否需要访问这些类中任何一个的私有变量或特定于它们的属性

当您想要封装和共享行为时,可以使用命令模式。它看起来像:

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);
        }
    }
}
这允许您封装和提取功能。。。当然,限制是您不能访问私有或受保护的成员,或特定于RoleButton的成员等,因为您必须向命令传递公共基。无法访问RoleButton/RoleImageButton特定成员应该不是问题;如果您的代码使用了以下任一特定的内容,则它不能是通用代码:)

如果必须访问私有/受保护的成员,则需要创建一个公开属性的接口,并分别为RoleButton和RoleImageButton实现该接口,然后将该接口传递给命令。。。但是你基本上是强迫这些属性是公共的,并且让其他类可以访问它们。如果您确实需要这样做,我可以给您一些示例代码来演示如何操作,但这并不是一个好主意

你真正想要的是多重继承,一个C#不支持的概念



编辑

有两种方法可以剥这只猫的皮。。。我建议使用第一种方法,即封装要在命令中更改的变量,并将其作为参数传递,如下所示:

//  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
    }

}
或者,将角色类设为一个结构并通过引用传递。这样可以避免暴露角色,从而使角色保持受保护状态。我编写的命令模式代码中的所有其他内容都按原样使用

第二种方法甚至不值得一提。。。我会被迫放弃,但这是一个糟糕的主意,除非它被折磨出我的身体,否则我不想推广它。 :D

HTH,

James

OnPreRender()代码是否需要访问Button、RoleButton、ImageButton或RoleImageButton类中的私有或受保护变量?我的猜测是肯定的,但总有希望……JOC,你能发布OnPreRender()中复制的代码吗?我添加了完整的类实现:)。谢谢您问题是您要设置的成员变量,
PrimaryRole
SecondaryRole
。它们在公共类中不是同一个变量,而是具有相同名称的两组独立成员。我将添加代码,给你一个如何处理这个想法,如果你想。。。这基本上就是我说的,你必须在两个按钮上实现一个公开这两个属性的公共接口。不幸的是,这意味着您已经有效地将它们设置为公共属性。您可以将接口实现为内部接口,这至少会限制您向自己的dll公开的内容的范围。。。我将不得不考虑+1,因为我看不出有人会否决这一点的任何原因。这可能是因为其中一个按钮来自
ImageButton
,而不是
按钮
。不幸的是,此答案丢失了
RoleImageButton:ImageButton
之间的连接。示例代码中也有一个错误,因为他声明了
公共类ImageButton:BaseButton
,他的意思是
公共类RoleImageButton:BaseButton
,您再次失去了
RoleImageButton:ImageButton
之间的连接
Button
ImageButton
System.Web.UI.WebControl
中的两个不同类,它们都继承自WebControl。(好吧,ImageButton继承自
System.Web.UI.WebControls.Image
,它直接继承自WebControl…重点是ImageButton和Button与Frog和Unicorn一样不同)它们都实现了IButtonControl,因此您可能可以摆脱它。上面发布的实现似乎并不依赖于特定于按钮的任何东西。