同一个类的实现,只是不同的父级,如何处理这个?

时间:2011-01-17 03:14:08

标签: c# .net design-patterns

我有两个类定义如下:

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

这些类的实现完全相同,所以我想删除这个重复,但我不知道这样做的技巧。

你能告诉我这样做的方法吗?

4 个答案:

答案 0 :(得分:3)

跳闸点是您是否需要访问任何这些类的私有变量或特定于它们的属性。

如果要封装和共享行为,请使用命令模式。它看起来像:

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
    }

}

或者,将Roles类作为结构并通过ref传递它。这可以防止您暴露自己的角色,从而使您可以保护自己的角色。我写的命令模式代码中的其他所有内容都按原样使用。

第二种方法甚至不值得一提......我会在胁迫下放弃它,但这是一个坏主意,我不想推广它,除非它被折磨出来。 :D

HTH,
詹姆斯

答案 1 :(得分:1)

我会创建一个派生自BaseButton的{​​{1}}类。如果每个按钮都有特定的更改,则从Button派生,如下所示:

BaseButton

答案 2 :(得分:1)

你有一个包含其他按钮类型的RoleButton类吗?

如果Button和ImageButton都有一个共同基础或实现像IButton这样的界面,你可以这样:

class RoleButton : IButton
{
  private Button _realButton;

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

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

这样你最终不会重复你的RoleButton代码:

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

答案 3 :(得分:0)

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