2012-02-09 84 views
-1

我有各種派生對象,希望用戶能夠使用對象初始化程序。我有一個「Initializing」屬性,我希望這些屬性被設置爲true,然後我希望Initializing屬性在之後設置爲false。如何判斷對象初始化程序何時完成

我該如何判斷對象初始值設定項何時可以執行此操作?

class Foo 
{  
    Public Foo(string p1, string p2) 
    { 
     Initializing = true; 
     Property1 = p1; 
     Property2 = p2; 
     Initializing = false; 
    } 

    bool Initializing; 

    string _property1; 
    string Property1 
    { 
     get { return _property1; } 
     set { _property1 = value; DoSomething(); } 
    } 

    string Property2 { get; set; } 

    public void DoSomething() 
    { 
     if(Initializing) return; // Don't want to continue if initializing 
     // Do something here 
    } 
} 

在上面的例子,如果你使用的構造函數,它工作正常。儘管如何使它與對象初始值設定項一樣工作也是個問題。

編輯:爲了你的反對者,這裏是別人找正是我追求 - http://blogs.clariusconsulting.net/kzu/how-to-make-object-initializers-more-useful/

不幸的是它看起來喜歡它是不可能的,但。

+0

你可以張貼一些代碼來說明更好你想要做什麼? – 2012-02-09 04:36:07

+0

@AndrewCooper你走了。 – 2012-02-09 04:44:07

+1

@BrandonMoore這是一個非常糟糕的主意。你從字面上讓我不寒而慄。 – asawyer 2012-02-09 04:45:47

回答

4

如果你真的需要跟蹤對象的初始化,那麼你需要手動實現該邏輯。一種方法是複製使用的WinForms的代碼生成器。當物體暴露ISupportInitialize接口,當他們想要的屬性在批處理更新。所以使用會是這樣的......

var x = new Foo(); 
x.BeginInit(); 
x.Property1 = 1; 
x.Property2 = 2; 
x.EndInit(); 
+0

+1作爲這裏唯一的建設性人物,發佈一些有用的東西,即使它不能幫助我的情況。我想我只需要找到一個更好的方法,因爲我想要的基本上就是像對待構造函數那樣對待對象初始值設定項,即使我知道它不是這樣。 – 2012-02-09 05:19:46

+0

@BrandonMoore:我也想回答這個問題。 ***這是你怎麼做的。***如果BeginInit/EndInit沒有被調用,或者沒有按照正確的順序調用,你應該檢查並拋出。唯一的另一種選擇是提供一個ctor,它需要一個包含初始化類型所需的所有數據的類型。這是框架中的另一個模式(查看AppDomain作爲相關示例)。這是答案,所以除了一個新問題之外,你不需要再問任何問題。 – Will 2012-02-10 16:51:57

+0

@願意謝謝。顯然不是我希望聽到的,但它是這樣的:/ – 2012-02-11 01:05:50

1

這個問題沒有意義。對象初始化語法只是語法糖的簡寫。

此:

var myInstance = new someClass() 
{ 
    Prop1 = "", 
    Prop2 = "", 
    Prop3 = "", 
    Prop4 = "", 
    Prop5 = "" 
} 

是完全一樣的:

var myInstance = new someClass(); 
myInstance.Prop1 = ""; 
myInstance.Prop2 = ""; 
myInstance.Prop3 = ""; 
myInstance.Prop4 = ""; 
myInstance.Prop5 = ""; 

沒有 「完成」 被檢測到。

你想要什麼可以做,我們是這樣的:

class someClass() 
{ 
    public string AStringProperty { get; set; } 
    public bool IsInitiazlied 
    { 
    return string.IsNullOrWhitespace(this.AStringProperty); 
    } 
} 

或者,使構造函數取值的inital狀態,那麼你guarantied是設置。

class someClass() 
{ 
    public string AStringProperty { get; set; } 
    public someClass(string AStringPropertyInit) 
    { 
     this.AStringProperty = AStringPropertyInit; 
    } 
} 

EDIT

class Foo 
{  
    Public Foo(string p1, string p2) 
    { 

     _property1= p1; //set the backing store directly, 
         //skips the side effect in the setter 
     Property2 = p2; 

     DoSomething(); // now cause the side effect 
         // we know everything is setup 
    } 



    string _property1; 
    string Property1 
    { 
     get { return _property1; } 
     set { _property1 = value; DoSomething(); } 
    } 

    string Property2 { get; set; } 

    public void DoSomething() 
    { 
     // Do something here 
    } 
} 
+0

術語是「語法糖」;) – 2012-02-09 04:40:00

+0

@Jeff它已經很晚了。 >< – asawyer 2012-02-09 04:42:41

+0

@asawyer感謝您終於嘗試幫助。如果屬性是從初始化程序中設置的,我不希望DoSomething()中的東西運行,但是如果它們沒有從初始化程序調用,我會這樣做。這個想法是,當我初始化對象時,它處於「初始」狀態。但是當屬性改變時,我真的希望DoSomething()運行。所以這個解決方案還沒有完全解決這個問題。 – 2012-02-09 05:06:05

0

一個目的初始化器只有很短的手用於創建對象並在其上設置了一堆屬性。詢問「何時完成」並不合乎情理。

如果您希望對象的狀態依賴於正在初始化的特定屬性集,那麼您可以將代碼添加到每個屬性的setter中並在內部跟蹤它。但這真的取決於你想要達到的目標。

更新

只是閱讀@ asawyer的回答您的意見。沒有辦法確定是否在初始化程序中設置了屬性。只是爲了說明 - 這裏有三段代碼完全相同,除了你似乎想要每個代碼都有不同的行爲。

var someVar1 = new SomeClass() 
       { 
        Prop1 = "value1"; 
        Prop2 = "value2"; 
       }; 

var someVar2 = new SomeClass() 
       { 
        Prop1 = "value1"; 
       }; 
someVar2.Prop2 = "value2"; 

var someVar3 = new SomeClass(); 
someVar3.Prop1 = "value1"; 
someVar3.Prop2 = "value2"; 

它不會是很難跟蹤個人財產setter方法的執行,並觸發所有,但第一次執行一些副作用,但說我只想要觸發如果客戶改變副作用ctor完成後,初始對象配置沒有任何意義。

+0

不要將限制與邏輯等同。只是因爲不能做的事情並不意味着如果可以做到這一點就沒有意義。 – 2012-02-09 05:40:05

+0

@BrandonMoore不過,在C#中,可能在大多數OO語言中,對象的初始狀態是構造函數完成後的初始狀態。如前所述,對象初始化器只是用於設置一組屬性的語法糖。使用默認構造函數和顯式屬性調用可以完成同樣的事情。如果你想強迫你的類的用戶在對象被初始化之前設置一組特定的屬性,那麼你最好在構造函數中編碼並且沒有默認構造函數。 – 2012-02-09 06:05:34

1

因爲對象的初始化只是語法糖,你不能告訴它和正常的屬性集之間的區別。我也能想到,你會希望區別對待合理的情況。也就是說,如果你要說至少必須設置x個屬性中的一個(無論是longhand還是shorthand語法),那麼你可以在ctor中設置初始化爲true,然後在每個屬性集上設置它爲false 。

3

有一個在設置任何標誌沒有意義。直到初始化器運行後才能訪問對象。例如:

var object = new object() { Prop1 = "Boo" } 

由於參考從新返回不能直到PROP1設置後進行訪問,就沒有辦法訪問任何屬性的,因此沒有必要控制訪問,也不用擔心它是否還是ISN」 t「完成」。

雖然,我想我可以看到你怎麼可能有這樣的事情:

public class Foo { 
    private int _value; 
    public int Bar { 
     set { 
      _value = value * Baz; // don't want to do this if initializing 
     } 
    } 

    public int Baz { get; set; } 
} 

如果這是你關心的問題,那麼你就錯誤地設計你的對象。屬性不應該有這樣的副作用。沒有辦法知道是否所有的初始化已經完成。

1

,而不是依賴於一個明確的屬性來告訴你當你的對象初始化,你可以有你的DoSomething方法驗證,它有它需要做的工作信息。你舉的例子是相當粗糙,我希望你真正的實現是比較複雜的,所以我就姑且認爲Property1Property2必須分配給東西(繼續之前的意思只是沒有一個空字符串):

class Foo 
{  
    public Foo(string p1, string p2) 
    { 
     Property1 = p1; 
     Property2 = p2; 
    } 

    string Property1 { get; set; } 
    string Property2 { get; set; } 

    public void DoSomething() 
    { 
     // *** Replace this with something valid to your real code 
     if(!string.IsNullOrEmpty(Property1) || !string.IsNullOrEmpty(Property2)) 
      return; // Don't want to continue if not initialized 
     // Do something here 
    } 
} 

UPDATE

有沒有你實際上是與工作對象模型的知識,這裏是基於整個框架廣泛使用的模型可能的替代:

class Foo 
{ 
    public void DoSomething(FooConfig config) 
    { 
    } 
} 

OR

class Foo 
{ 
    private FooConfig config_; 

    public Foo(FooConfig config) 
    { 
     config_ = config; 
    } 

    public void DoSomething() 
    { 
    } 
} 

FooConfig定義:

(new Foo()).DoSomething(new FooConfig() { Property1 = "abc"; Property2 = "def"; }); 

OR

01:

class FooConfig 
{ 
    public string Property1 { get; set; } 
    public string Property2 { get; set; } 
} 

而且DoSomething使用調用

這可以很容易地改變,以適應在任FooFooConfig構造的使用。

+0

事情就是我想要DoSomething運行,如果一個屬性已被「更改」。但是,如果該對象與屬性初始化,我不希望DoSomething運行。 – 2012-02-09 05:28:34

+0

@BrandonMoore - 這有點令人困惑。所以如果屬性有一個值,只要它沒有通過屬性的'set'方法顯式設置,就希望'DoSomething'運行? – 2012-02-09 05:32:08

+0

好吧......顯然,如果它是從初始化程序設置的,那麼它是通過set方法設置的,儘管我明白你想說什麼。除了這個問題不是它是否通過setter「明確」設置的,而是它是否通過初始化設置。在我目前的方法中,這兩件事似乎是同義詞,但不同之處在於,對於我實際上想要做的事情,可能有更好的方法,而另一方面可能沒有。我不會像我提議的那樣去做,如果我有一個更好的設計來嘗試它。 – 2012-02-09 05:36:54

相關問題