2009-01-21 72 views
19

看看這個例子代碼:可以從NHibernate實體的構造函數中調用虛擬屬性嗎?

public class Comment 
{ 
    private Comment() 
    { } 

    public Comment(string text, DateTime creationDate, string authorEmail) 
    { 
     Text = text; 
     CreationDate = creationDate; 
     AuthorEmail = authorEmail; 
    } 

    public virtual string Text { get; private set; } 
    public virtual DateTime CreationDate { get; set; } 
    public virtual string AuthorEmail { get; private set; } 
} 

我知道這是被認爲不好的做法,調用虛成員函數從構造,然而在NHibernate的,我需要的屬性是虛擬的,以支持延遲加載。在這種情況下它被認爲是可以的嗎?

+1

我覺得你的問題應該得到更多的注意,我想添加此參考:http://stackoverflow.com/tw/sea​​rch?q=nhibernate+virtual+constructor 我認爲,添加一個Initialize()方法或參數較少的構造函數正在改變你的設計,以適應框架 - 在我看來這是一個不好的做法;也許你希望你的對象在任何時候都是有效的(我認爲你應該)... Initialize()方法/參數少的構造函數允許構造沒有它們需要的對象。 – W3Max 2009-08-30 19:48:25

回答

5

我很確定這是好的,但如果你擔心你總是可以在參數少的構造函數調用後分配屬性。

0

我知道如果你在構造函數中調用一個虛擬方法,但我不知道FxCop說你是否在構造函數中調用一個虛擬屬性...
我認爲FxCop會因爲財產被翻譯成IL中的方法,所以也抱怨。

您還可以創建屬性爲'非虛擬',並在NHIbernate的'類映射'中指定'lazy = false'。 這不會影響集合的延遲加載行爲。我一直這樣做,因爲我不喜歡我的基礎設施(NHibernate)要求我具有虛擬屬性
我也不知道在NHibernate中具有動態代理的性能好處是不是重大)。

0

我想,你不應該在構造函數中調用它。 您可以提供一個方法Initialize(),您可以在構造該對象後調用它。

在初始化(),您可以調用所需的虛擬方法

1

這是該樣品中確定,但是當你繼承類和替換的屬性,可能會出現問題。通常,您可以更好地爲虛擬屬性創建字段。

2

要擴大Paco的答案:

在大多數情況下,它不會傷害。但是,如果這個類是繼承的,虛擬允許屬性get/set被重寫,所以行爲不再被完全封裝和控制,因此理論上它可能會破壞。 FxCop對此提出警告,因爲這是一個潛在的問題。

FxCop的意義在於幫助提醒您潛在的問題。如果你知道你是誰/繼續從類繼承什麼,那麼它不是錯誤在構造函數中使用屬性,但它不是正式的「最佳實踐」。

所以,答案是,只要你控制類的繼承,就沒問題。否則,請勿使用它並直接設置字段值。 (這意味着你不能使用C#3.0自動獲取/設置屬性 - 你必須自己編寫屬性包裝字段。)

備註:就我個人而言,我所有的項目都是我們爲客戶託管的網站。因此,假設這個設置對於一個項目來說保持不變,那麼就不得不重複不同的空/參數檢查。但是,在其他任何情況下,我不確定我們會保持對項目的完全控制和課程的使用,我不會採取這種捷徑。

0

恕我直言,最好的做法是使用性能與支持字段:

public class Comment 
{ 
    private DateTime _creationDate; 
    private string _text; 
    private string _authorEmail; 
    private Comment() { } 
    public Comment(string text, DateTime creationDate, string authorEmail) 
    { 
     _text = text; 
     _creationDate = creationDate; 
     _authorEmail = authorEmail; 
    } 
    public virtual string Text 
    { 
     get { return _text; } 
     private set { _text = value; } 
    } 
    public virtual string AuthorEmail 
    { 
     get { return _authorEmail; } 
     private set { _authorEmail = value; } 
    } 
    public virtual DateTime CreationDate 
    { 
     get { return _creationDate; } 
     set { _creationDate = value; } 
    } 
} 

所以,你就可以避免子類的問題,你看不到任何警告了

相關問題