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

发布于 2024-10-12 01:25:04 字数 1660 浏览 2 评论 0原文

我有两个类的定义如下:

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

这些类的实现完全相同,因此我想删除此重复项,但我不知道执行此操作的技术。

你能告诉我如何做到这一点吗?

I have two classes that defined like this:

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

The implementation of these classes are exactly the same, so I want to remove this duplication, but I don't know the technique to do this.

Can you show me the way to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

深白境迁sunset 2024-10-19 01:25:04

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

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

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,
詹姆斯

The tripping point is whether or not you need to access private variables of any of those classes, or properties that are specific to them.

When you want to encapsulate and share behavior, you use the Command Pattern. It looks something like:

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);
        }
    }
}

This allows you to encapsulate and extract functionality... the limitation, of course, is that you can't access private or protected members, or members specific to RoleButton, etc., because you have to pass a common base to the command. Not being able to access RoleButton/RoleImageButton-specific members should be a non-issue; your code can't be common code if it uses anything specific to either of these : )

If you have to access private/protected members, you would need to create an interface that exposes the properties, and implement it separately for both RoleButton and RoleImageButton, and pass that interface to the command... but then you're basically forcing those properties to be public, and making them accessible to other classes. If you absolutely need to do this, I can give you some sample code to show you how, but it's really not a good idea.

What you're really after is multiple inheritance, a concept that C# doesn't support.

EDIT

There are two ways to skin this cat... I'd recommend the first one, which is to encapsulate the variables you're going to change in your command and pass it as a parameter, as such:

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

}

Alternatively, make the Roles class a struct and pass it by ref. This keeps you from exposing your roles, allowing you to keep them as protected. Everything else from the command-pattern code I wrote is used as-is.

The second approach isn't even worth mentioning... I'll give it up under duress, but it's such a bad idea, I wouldn't want to promote it unless it were tortured out of me.
: D

HTH,
James

指尖凝香 2024-10-19 01:25:04

您可以有一个包含其他按钮类型的 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);

Can you have a RoleButton class that wraps around other button types?

If Button and ImageButton both have a common base or implement an interface like IButton you could have something like this:

class RoleButton : IButton
{
  private Button _realButton;

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

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

That way you don't end up duplicating your RoleButton code:

var roleButton = new RoleButton(myButton);
var roleImageButton = new RoleButton(myImageButton);
起风了 2024-10-19 01:25:04

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

I would create a BaseButton class that derives from Button. If there are any changes specific to each button, then derive from BaseButton as follows:

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";
   }
}
三生路 2024-10-19 01:25:04

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

You could use a T4 template. It would allow you to have a single file (the template) containing the implementation once, and it would generate the two classes with the identical implementations for you. (Of course, the code would still be duplicated in the compiled assembly, but at least there’s no more of that maintenance problem of keeping them in sync.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文