簡體   English   中英

C#中的多重繼承 - 再次

[英]Multiple inheritance in C# - again

我知道C#不提供多重繼承。 我知道有一些像這樣的解決方法。

但這是我今天面臨的一個問題,無法找出任何優雅的解決方法。 我將添加一些抽象的代碼示例,以便您更快地獲得它...

(讓它成為現實生活中的ASP.NET代碼 - 導致那些“A類,B類”代碼樣本真的令人困惑):

public class AdminPage : System.Web.UI.Page
{
    protected override void OnInit(EventArgs e)
    {
        //if not an admin - get out
        if(!CurrentUserIsAdmin()) Response.End();

        base.OnInit (e);
    }
}

public class JQueryPage : System.Web.UI.Page
{
    protected override void OnInit(EventArgs e)
    {
        RegisterJQueryScript();
        base.OnLoad (e);
    }
}

//now here's what I REALLY miss in C#
public class AdminJQueryPage : AdminPage, JQueryPage;

撰寫功能? 這對單一責任更好。 你必須仔細考慮你的構造函數。

interface IAdminPage {
  public string AdminPageMethod();
}

interface IJQueryPage {
  public string JQueryPageMethod();
}

internal class AdminPage : IAdminpage {
  private string someString;

  internal AdminPage(string value) {
    this.someString = value;
  }

  public string AdminPageMethod() {
    return "AdminPage result with some string: " + this.someString;
  }
}

internal JQueryPage : IJQueryPage {
  private int someNumber;

  internal JQueryPage(int value) {
    this.someNumber = value;
  }

  public string JQueryPageMethod() {
    return "JQueryPage result with number: " + this.someNumber;
  }
}

class AdminJQueryPage : IQueryPage, IAdminpage {
  private readonly IAdminPage adminPage;
  private readonly IJQueryPage jqueryPage;

  public AdminJQueryPage(string someString, int someNumber) {
    this.adminPage = new AdminPage(someString);
    this.jqueryPage = new JQueryPage(someNumber);
  }

  public string AdminPageMethod() {
    return this.adminPage.AdminPageMethod();
  }

  public string JQueryPageMethod() {
    return this.adminPage.JQueryPageMethod();
  }
}

如果您真的想要多重繼承,請查看Scala的特征

編輯 :將構造函數值的傳遞添加到組合的類中。 還使類內部(不能在程序集外部訪問或構造),因為它們只是由AdminJQueryPage類構建,這是“面向公眾”的類。

我也來自C ++並且不要錯過它,尤其是在閱讀Refactoring [並使用非OOTB工具]之后。

您可以使用PostSharp基於在AdminJQueryPage上放置屬性來發布流程,這將實現完全相同的效果。

或者你可以將方法代碼提取到輔助類中並調用它(即Joe的例子)

或者您可以將幫助程序放在一個基類中並從中調用。

無論哪種方式,您的代碼都會更清晰。

你的mixin開始重疊只是一個時間問題,然后你管理復雜性的一般技術套件需要啟動 - 在C ++中,MI應該只是套件中的一個工具 - 而不是一個非常性感的錘子。

可以通過指定接口並為該接口創建擴展方法來偽造mixin 但是我不使用這將有助於重寫方法,只添加新的方法。 你當然能夠在覆蓋時調用擴展方法,但這與將方法提取到輔助類基本相同,但是加了一點糖

即使有可能,基於MI的解決方案對您提出的具體問題的語義有一個問題就是標記方面會發生什么? 生成標記的Render()方法首先在一個類中運行,然后在另一個類中運行? 當兩個類生成整個頁面時,這可能不是您想要的行為。

如果您對語言本身之外的解決方案持開放態度,那么ASP.NET中有幾個優雅的選項可以解決您提出的問題類型(更改頁面生命周期中事件期間采取的操作)。 例如:

  1. 頁面適配器
  2. 控制適配器
  3. 自定義用戶控件
  4. 的HttpModules
  5. 母版頁
  6. 標簽映射

最佳選擇當然取決於您的應用程序的詳細信息。 如果它有用,我會在本書中介紹這些選項,包括示例代碼: Ultra-Fast ASP.NET

最簡單的方法是構建層次結構 - 允許AdminPage繼承JQueryPage,如下所示:

public class AdminPage : JQueryPage
{
    protected override void OnInit(EventArgs e)
    {
        //if not an admin - get out
        if(!CurrentUserIsAdmin()) Response.End();

        base.OnInit (e);
    }
}

public class JQueryPage : System.Web.UI.Page
{
    protected override void OnLoad(EventArgs e)
    {
        RegisterJQueryScript();
        base.OnLoad (e);
    }
}

//now here's what I REALLY miss in C#
public class AdminJQueryPage : AdminPage

我的猜測是一些尷尬來自ASP.NET頁面模型,它使用重寫的基類方法。

您可以使用Interfaces執行此操作

    public interface IJQueryPage
    {
    }

    public abstract class AdminPage : System.Web.UI.Page
    {
        protected override void OnInit(EventArgs e)
        {
            //if not an admin - get out
            if(!CurrentUserIsAdmin()) Response.End();
            base.OnInit (e);
        }
        protected override void OnLoad(EventArgs e)
        {
            if (this is IJQueryPage)
            {
                RegisterJQueryScript();
            }            

            base.OnLoad (e);
        }
    }

    public class AdminJQueryPage : AdminPage, IJQueryPage
    { 
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM