簡體   English   中英

如何定義必須由類實例實現的功能的簽名?

[英]How do I define the signature of a function that must be implemented by instances of a class?

說我有一類Book

public class Book{
   public string Title {get; set;}
}

我希望每本書都有一個Read函數,該函數返回一個字符串並接受頁碼-但是每本書的內部結構都不同(我知道例子很差)。 如何定義必須由此類實例實現的功能的簽名?

像這樣:

public class Book{ // need to make this abstract?
   public string Title {get; set;}
   public abstract string Read(int pageNum);
}

// I want to define instances that define their own behavior...
public static Book It => new Book(){ // can't create instance of abstract...
   Title = "It", 
   Read... // what do I do here?
}

我主要關心的是:

  • 使事情盡可能簡單。 在抽象類下實現接口是可行的,但是當我添加更多實例時,它給我帶來了n * 2件事。
  • 我將需要添加大量這些自定義函數-通過構造函數傳遞Funcs似乎很麻煩。
  • 在實踐中-這用於定義Tenant Tenants是在內存中定義的,並且具有許多靜態屬性,例如domainnameadminEmail等。這些是租戶特定的屬性...但是現在我正在嘗試實現租戶特定的行為 ,例如GetBooksFilterUsers 我想使實現盡可能地簡單。 現在,我的代碼中始終散布着“如果使用TenantA,請執行此操作,如果使用TenantB,請執行此操作...”。 我試圖將所有特定於租戶的邏輯和詳細信息集中在一個地方- Tenant類的實例。
  • 租戶特定行為的更多示例-您擁有SaaS論壇軟件。 在論壇A的主頁上,通過讀取靜態文件來獲取GetCoverPhoto 在論壇B的主頁上,您可以通過閱讀博客主頁來獲取GetCoverPhoto 目前,我說“如果論壇A,請執行此操作,否則,如果論壇B,請執行此操作”。 這是我想在Tenant對象上而不是在代碼中定義的特定於租戶的行為的類型。 我的核心邏輯中不需要任何特定於租戶的代碼。

C#語言中是否有一個簡單的功能/模式可以實現這一目標?

NineBerry所說的非常正確。

還有另一種方法可以實現您想要的。 如果要動態地將read方法實現注入Book中。 這可以看作是策略模式 並且可以像許多語言一樣作為接口來完成,但是以C#的最簡單形式可以由委托來完成。 例:

public class Book{
   Func<int, string> readFunc;
   public Book(Func<int, string> readFunc)
   {
     this.readFunc = readFunc;
   }
   public string Title {get; set;}
   public string Read(int pageNum) { return readFunc(pageNum); }
}

然后將其用作:

public static Book It => new Book(){
   Title = "It", 
   Read = (pageNum) => ... // Do actual reading in delegate
}

編輯:隨着需求的更多細節(但仍然不是一切都是顯而易見的),我會做這樣的事情:

public class Tenant 
{
  // core things go here
  public Extensions Extensions { get; }
}

public class Extensions : IEnumerable<IExtension>
{
  private IList<IExtension> list = new List<IExtension();
  private Tenant { get; set; }

  public Extensions(Tenant tenant)
  {
    Tenant = tenant;
  }

  public void Add(IExtension extension)
  {
    extension.Tenant = Tenant;
    list.Add(extension);
  }
}

public interface IExtension
{
  Tenant { get; set; }
  // shared interface of extensions if any can be abstracted
}

public interface ICoverPhotoExtension : IExtension
{
  Photo GetCoverPhoto();
}

public class FileCoverPhotoExtension : ICoverPhotoExtension 
{
  public Tenant { get; set; }
  Photo GetCoverPhoto() { } // gets photo from file
}

public class BlogCoverPhotoExtension : ICoverPhotoExtension 
{
  public Tenant { get; set; }
  Photo GetCoverPhoto() { } // gets photo from blog
}

用法:

Tenant tenant; // initialized somehow
var coverPhotoExtension = tenant.Extensions.FirstOrDefault<ICoverPhotoExtension>();
Photo photo = coverPhotoExtension?.GetCoverPhoto();
public Interface IBook{ 
   string Title {get; set;}
   func<int,string> ReadPage
}

在繼承中使用包容性。 在上面的接口示例中,每本書中都有一個實現IBook的函數,該函數將為該頁面返回一個字符串。

public class MyBook : IBook{

   public Title : {get;set;} = "MyBook";
   public func<int,string> ReadPage =(pagenumber)=>{
       return GetText(pagenumber);
   }  
   public string GetText(int pageNumber){
      //read the page text by number here.
   }
}

我將使GetText成為與此類似的擴展方法,因此每本書都不需要實現GetText本身。

public static class XBook{
    public static string GetText(this IBook book, int pageNumber){
        ///do the work here and returng string
    } 
}

要使用擴展方法概念:

using XBook;
public class MyBook : IBook{

   public Title : {get;set;} = "MyBook";
   public func<int,string> ReadPage =(pagenumber)=>{
       return this.GetText(pagenumber);
   }  
}

有更多方法可以執行此操作...現在,嘗試一下。

一個類的不同實例無法以不同方式實現功能。 而是,您繼承一個新類,在其中實現單獨的行為。

public abstract class Book
{
   public string Title {get; set;}
   public abstract string Read(int pageNum);
}

public class ITBook : Book
{
   public override string Read(int pageNum)
   {
      // Code here
   }
}

然后使用這樣的類:

public static Book It => new ITBook()
{ 
   Title = "It", 
}

您可以在Book類中使用委托類型的屬性在Book類的不同實例中使用不同的函數,但是這些函數將無法訪問它們將使用的實例的其他屬性和方法。

暫無
暫無

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

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