2019 年 5 月

第 34 卷,第 5 期

[程式設計師雜談]

Naked 撰寫程式碼:Naked 集合

藉由Ted Neward |2019 年

Ted Neward歡迎回來,NOFers。最後一個時間,我擴增演講者備忘網域類型具有一些屬性,以及數個註解和關於這些屬性,提供提示的慣例 (或者,若要更老實說,指示) 如何驗證或呈現這些屬性的 ui使用者。我沒討論,不過,是如何指定的網域物件可以有一個以上的項目參考。比方說,演講者通常會有多個的演講,它們可以提供,或可以 professional 在一或多個主題中的專業知識。收到的 NOF 會將這些稱為 「 集合 」,而且有周圍的運作方式的幾項規則會從先前的交談稍有不同。

我們來看看一些演講和主題,讓喇叭應我們嗎?

Naked 概念

若要開始,放棄所有全部皆是在此處輸入的所有陣列。收到的 NOF 並不能使用於集合屬性的陣列,並改為依賴完全集合物件 (IEnumerable < T >-衍生) 來保存零對多的其他類型。收到的 NOF 手動強烈建議您,這些集合是強型別 (使用泛型),且因為收到的 NOF 認為,如果類型為 「 重要事項 」 NOF 不允許多個關聯的實值型別 (例如字串、 列舉型別等等)足以產生關聯,它應該是完整的網域類型。

因此,比方說,如果我想要擷取主題的概念 (例如"C#,""Java 」 或 「 分散式系統 」) 收到的 NOF 堅持在會議系統中,其中其他程式設計方法可讓您擺脫這個簡單的 「 清單字串 」 做為屬性類型,主題是完整的網域物件型別 (也就是說,具有屬性的公用類別),完成,但它自己的定義域規則。很合理,主題的清單可能是一組固定,不過,因此我會植入資料庫與一組完整的我的會議想要考慮的主題。

同樣地,雖然談一談可能只有一個標題,但它其實一系列的項目: 標題、 描述、 一個主題 (所屬或它是指),且會由一個 (或以上) 的主講人。很明顯地,我有一些網域模型化之前我尚未。

Naked 集合

在許多方面,開始的最簡單方式是與演講和主題的網域類別本身,不存在的任何 (或演講者) 之間的連線。到目前為止,許多功能撰寫以下的每一種應該是很重要,而且那樣簡單直接, [圖 1顯示。

[圖 1 演講和主題的網域類別

public class Talk
  {
    [NakedObjectsIgnore]
    public virtual int Id { get; set; }
    [Title]
    [StringLength(100, MinimumLength = 1,
       ErrorMessage = "Talks must have an abstract")]
    public virtual string Title { get; set; }
    [StringLength(400, MinimumLength = 1,
       ErrorMessage = "Talks must have an abstract")]
    public virtual string Abstract { get; set; }
  }
  public class TalkRepository
  {
    public IDomainObjectContainer Container { set; protected get; }
    public IQueryable<Talk> AllTopics()
    {
      return Container.Instances<Talk>();
    }
  }
  [Bounded]
  public class Topic
  {
    [NakedObjectsIgnore]
    public virtual int Id { get; set; }
    [Title]
    [StringLength(100, MinimumLength = 1,
       ErrorMessage = "Topics must have a name")]
    public virtual string Name { get; set; }
    [StringLength(400, MinimumLength = 1,
       ErrorMessage = "Topics must have a description")]
    public virtual string Description { get; set; }
  }
  public class TopicRepository
  {
    public IDomainObjectContainer Container { set; protected get; }
    public IQueryable<Topic> AllTopics()
    {
      return Container.Instances<Topic>();
    }
  }

到目前為止,這是非常直接了當。(很顯然無法和/或應新增至每個兩個類別,其他項目,但這很好抓出重點)。 使用,一個新的屬性 [繫結] 會指示 NOF,完整的 (且不可變的) 的清單執行個體可以並應該保留在記憶體,在用戶端,並呈現給可供選擇的下拉式清單中的使用者。同樣地,接著,主題的完整清單必須建立在資料庫中,最簡單的方式在中顯示的 DbInitializer 類別從"SeedData 」 專案中 (以討論於先前資料行在這一系列),種子方法完成**[圖 2**.

[圖 2 建立的主題清單

protected override void Seed(ConferenceDbContext context)
{
  this.Context = context;
  Context.Topics.Add(new Topic() { Name = "C#",
    Description = "A classical O-O language on the CLR" });
  Context.Topics.Add(new Topic() { Name = "VB",
    Description = "A classical O-O language on the CLR" });
  Context.Topics.Add(new Topic() { Name = "F#",
    Description = "An O-O/functional hybrid language on the CLR" });
  Context.Topics.Add(new Topic() { Name = "ECMAScript",
    Description = "A dynamic language for browsers and servers" });
  Context.SaveChanges();
  // ...
}

這會提供從用來工作的主題 (較小,但很有用) 清單。順便一提,如果您使用家庭遊戲玩法,而以手動方式撰寫的程式碼,請記得將 TalkRepository 新增至主功能表中,藉由將它新增至伺服器專案中 NakedObjectsRunSettings.cs MainMenus 方法。此外,請確定兩個存放庫類型也會列在同一個檔案中的服務方法。

基本上,談一談說話者所指定,而是特定主題。我要忽略的更複雜的案例,當談一談就會提供兩個的說話者,或如果談一談跨多個主題,以簡化目前。因此,針對第一個步驟中,讓我們將討論演講者:

private ICollection<Talk> _talks = new List<Talk>();
public virtual ICollection<Talk> Talks
{
  get { return _talks; }
  set { _talks = value; }
}

如果您建置並執行專案時,您會看到"演講"顯示為集合 (資料表),在 UI 中,但其為空白。無法,當然,新增一些演講 SeedData,但在一般情況下,說話者需要能夠討論加入他們的設定檔。

Naked 動作

這可以藉由將說話者類別中的動作來完成:一種方法,會出現,「 神奇地,"做為可選取的項目,在 [動作] 功能表中顯示的說話者的物件時。屬性,例如動作會探索透過神奇的反映,因此,需要進行是演講者備忘類別上建立的公用方法:

public class Speaker
{
  // ...
  public void SayHello()
  {
  }
}

現在,當建置並執行之後啟動的說話者,就會顯示 [動作] 功能表,並內"SayHello"會出現。目前沒有執行任何動作;那就天下太平了,做為起點,將至少一個訊息傳回給使用者。在收到的 NOF 世界中,這是藉由使用服務,其目的是要提供一些額外的功能並不隸屬於特定網域物件的物件。在一般 「 訊息傳回給使用者,」 的情況下,這被提供所收到的 NOF 本身 IDomainObjectContainer 介面中定義的泛型服務。我需要的其中一個執行個體才能執行任何動作,不過,並收到的 NOF 使用相依性插入來提供隨選的其中一個:宣告的型別 IDomainObjectContainer,演講者備忘類別上的屬性,並收到的 NOF 可確保每個執行個體有一個:

public class Speaker
{
  public TalkRepository TalkRepository { set; protected get; }
  public IDomainObjectContainer Container { set; protected get; }

容器物件具有用來傳達一般訊息傳回給使用者,因此使用它從 SayHello 動作很簡單,只要 「 InformUser"方法:

public class Speaker
{
  // ...
  public void SayHello()
  {
    Container.InformUser("Hello!");
  }
}

但我開始想来允許使用者加入指定說話者的所有產品; 談一談具體來說,我需要擷取演講,也就是抽象的標題 (或描述,因為 「 抽象 」 是中的保留的字C#),以及這段演講所屬的主題。呼叫這個方法 「 EnterNewTalk 」,接著,我可以有下列實作:

public void EnterNewTalk(string title, string description, Topic topic)
{
  var talk = Container.NewTransientInstance<Talk>();
  talk.Title = title;
  talk.Abstract = description;
  talk.Speaker = this;
  Container.Persist<Talk>(ref talk);
  _talks.Add(talk);
}

幾件事會發生在這裡,我們將解除封裝。首先,我可以使用 IDomainObjectContainer 建立演講的暫時性 (非持續性) 執行個體。這是必要的因為收到的 NOF 必須能夠將插入每個網域物件中的 「 勾點 」,才能發揮它。(這是為什麼所有屬性必須都是虛擬的如此 NOF 可以管理 UI-物件同步處理,例如)。 然後,談話內容的設定,以及容器會再次用來保存演講;若尚未完成,演講不是永續性的物件,並不會儲存,當我將演講將討論演講者的清單。

這是公平詢問,使用者指定這項資訊來 EnterNewTalk 方法本身的方式。同樣地,反映的各種秘訣都可以:收到的 NOF 研究超出方法參數的類型與參數名稱,並建構一個對話方塊,來擷取這些項目,包括主題本身。還記得主題已與 「 已繫結 」 註解嗎?指示 NOF 建置在這個對話方塊中為下拉式清單中,因此非常輕鬆地從清單中選取主題的主題清單。(它應該很容易推斷在此時,我將主題加入系統時,這些將所有會加入至這個下拉式清單中不需要任何額外的工作。)

現在,是合理的建議,建立討論的項目支援 TalkRepository,請在演講者備忘類別本身,不應該是,為您可以看到在**[圖 3**,很容易進行重構。

[圖 3 支援 TalkRepository Talk 建立

public class Speaker
  {
    public TalkRepository TalkRepository { set; protected get; }
    public IDomainObjectContainer Container { set; protected get; }
    public void EnterNewTalk(string title, string description, Topic topic)
    {
      var talk = TalkRepository.CreateTalk(this, title, description, topic);
      _talks.Add(talk);
    }
  }
  public class TalkRepository
  {
    public IDomainObjectContainer Container { set; protected get; }
    public Talk CreateTalk(Speaker speaker, string title, string description,
                Topic topic)
    {
      var talk = Container.NewTransientInstance<Talk>();
      talk.Title = title;
      talk.Abstract = description;
      talk.Speaker = speaker;
      Container.Persist<Talk>(ref talk);
      return talk;
    }
  }

不僅如此,如此一來,"的演講 「 功能表將自動裝飾與新的功能表項目,「"CreateTalk,這會 — 同樣地,透過反映的魔力,自動建立對話方塊中,輸入建立談一談所需的資料。說話者,當然,只要類型不可以是在中,NOF 會做出的 「 可卸除 」 欄位中,這表示收到的 NOF 會預期要拖曳-和-放入此欄位的說話者物件。(若要查看此預設 NOF Gemini 介面中的動作,啟動應用程式,選取說話者,然後按一下 「 交換窗格 」 按鈕,顯示畫面底部的雙箭號按鈕。說話者,選取將會轉換到螢幕的右邊,首頁介面會出現,讓您選取的 「 討論/建立交談 」 的項目。拖放在演講者身上的說話者的名稱欄位,在建立交談] 對話方塊中,瞧,已選取 [演講者備忘。)

它是絕對一定要了解以下情況:我現在有兩個不同 UI 的路徑 (從最上層功能表中,建立談一談或從指定的說話者建立談一談),讓兩個不同的使用者瀏覽情況下,輕輕鬆鬆和零個重複項目。TalkRepository 擔心一切 」 CRUD 」 和 「 交談 」 關聯性,並將說話者會使用該程式碼,同時保持完全在說話者的使用者互動,如果使用者想要排列它的方式。

總結

這不是 2 位最好的 UI 工具組。在只需幾行程式碼,我有一個可行的介面 (而,考慮該資料會儲存與擷取自標準 SQL 後端,資料儲存系統) 的至少目前為止,可直接由使用者。更重要的是,但這是專屬的格式或語言,這是直接C#,直接的 SQL Server 及 UI 本身是 Angular。有幾個收到的 NOF 的預設介面,我會在下一個部分,包括驗證和授權功能的相關討論。在此同時,不過...祝各位編碼程式 !


Ted Neward是西雅圖的 polytechnology 顧問、 演說家導師。他已撰寫了無數的文章,撰寫與合著過十幾個書籍,並在世界各地發表演說。與他連絡ted@tedneward.com或閱讀他的部落格blogs.tedneward.com

非常感謝下列技術專家檢閱這篇文章:Richard Pawson


MSDN Magazine 論壇中的這篇文章的討論