2011-02-15 28 views
13

如果我此行的內部工作的理解是正確的:C#getter和setter速記

public int MyInt { get; set; } 

然後,它在幕後做這個的:

private int _MyInt { get; set; } 
Public int MyInt { 
    get{return _MyInt;} 
    set{_MyInt = value;} 
} 

我真正需要的是:

private bool IsDirty { get; set; } 

private int _MyInt { get; set; } 
Public int MyInt { 
    get{return _MyInt;} 
    set{_MyInt = value; IsDirty = true;} 
} 

但我想寫這樣的:

private bool IsDirty { get; set; } 

public int MyInt { get; set{this = value; IsDirty = true;} } 

哪一個不行。事情是我需要做IsDirty的一些對象有幾十個屬性,我希望有一種方法可以使用auto getter/setter,但是當字段被修改時仍然會設置IsDirty。

這是可能的,還是我只需要自己辭職以使我的類中的代碼量增加三倍?

+0

與IronPython的反潛。它在CLR上,但支持面向方面的編程,這就是你所需要的。 :) – bzlm 2011-02-15 21:37:51

+0

如果您使用的是Visual Studio,您可以創建一個代碼片段來幫助您節省時間。 – ebrown 2011-02-15 21:42:18

回答

21

你需要這樣處理自己:

private bool IsDirty { get; set; } 

private int _myInt; // Doesn't need to be a property 
Public int MyInt { 
    get{return _myInt;} 
    set{_myInt = value; IsDirty = true;} 
} 

沒有可用的語法,同時還採用了自動屬性機制,增加了自定義邏輯的制定者。你需要用自己的支持字段來寫這個。

這是一個常見問題 - 例如,在執行INotifyPropertyChanged時。

11

創建一個IsDirty裝飾器(設計模式)來包裝一些需要isDirty標誌功能的屬性。

public class IsDirtyDecorator<T> 
{ 
    public bool IsDirty { get; private set; } 

    private T _myValue; 
    public T Value 
    { 
     get { return _myValue; } 
     set { _myValue = value; IsDirty = true; } 
    } 
} 

public class MyClass 
{ 
    private IsDirtyDecorator<int> MyInt = new IsDirtyDecorator<int>(); 
    private IsDirtyDecorator<string> MyString = new IsDirtyDecorator<string>(); 

    public MyClass() 
    { 
     MyInt.Value = 123; 
     MyString.Value = "Hello"; 
     Console.WriteLine(MyInt.Value); 
     Console.WriteLine(MyInt.IsDirty); 
     Console.WriteLine(MyString.Value); 
     Console.WriteLine(MyString.IsDirty); 
    } 
} 
+0

有趣。問題是,我的對象有很多屬性,我真的只想要一個IsDirty。當我的任何屬性更新時,我希望無論哪個更新設置IsDirty = true。這仍然適用於您的代碼? – William 2011-02-15 21:55:59

1

我創建了一個自定義的Property<T>類來完成這樣的常見操作。儘管如此,我還沒有徹底使用它,但它可以在這種情況下使用。

代碼可以在這裏找到:http://pastebin.com/RWTWNNCU

你可以按如下方式使用它:當一個新的值傳遞感謝SetterCallbackOption參數

readonly Property<int> _myInt = new Property<int>(); 
public int MyInt 
{ 
    get { return _myInt.GetValue(); } 
    set { _myInt.SetValue(value, SetterCallbackOption.OnNewValue, SetDirty); } 
} 

private void SetDirty(int oldValue, int newValue) 
{ 
    IsDirty = true; 
} 

物業類只處理調用通過委託。這是默認值,因此可以丟棄。

UPDATE:

,當你需要支持多種類型的(除了int)這將不會明顯起作用了,因爲代表不那麼匹配。您可以隨時調整代碼以滿足您的需求。

2

您可以簡單或複雜。這取決於你想投資多少工作。您可以使用面向方面的編程通過IL編織器將該方面添加到IL代碼中,例如PostSharp。 或者你可以創建一個簡單的類來處理你的財產狀態。這很簡單,前一種方法只有在你有很多屬性來處理這種方式時才能帶來回報。

using System; 

class Dirty<T> 
{ 
    T _Value; 
    bool _IsDirty; 

    public T Value 
    { 
     get { return _Value; } 
     set 
     { 
      _IsDirty = true; 
      _Value = value; 
     } 
    } 

    public bool IsDirty 
    { 
     get { return _IsDirty; } 
    } 

    public Dirty(T initValue) 
    { 
     _Value = initValue; 
    } 
} 

class Program 
{ 
    static Dirty<int> _Integer; 
    static int Integer 
    { 
     get { return _Integer.Value; } 
     set { _Integer.Value = value; } 
    } 

    static void Main(string[] args) 
    { 
     _Integer = new Dirty<int>(10); 
     Console.WriteLine("Dirty: {0}, value: {1}", _Integer.IsDirty, Integer); 
     Integer = 15; 
     Console.WriteLine("Dirty: {0}, value: {1}", _Integer.IsDirty, Integer); 
    } 
} 

另一種可能性是使用在運行時生成的代理類,它爲您添加方面。在.NET 4中,有一個類已經爲您處理了這方面的問題。它被稱爲ExpandObject,當屬性發生變化時,它會通過事件通知您。好的事情是,ExpandoObject允許你在運行時定義任何數量的屬性,並且你會得到關於屬性的每一個變化的通知。使用這種類型的WPF數據綁定非常簡單。

dynamic _DynInteger = new ExpandoObject(); 

_DynInteger.Integer = 10; 
((INotifyPropertyChanged)_DynInteger).PropertyChanged += (o, e) => 
{ 
    Console.WriteLine("Property {0} changed", e.PropertyName); 
}; 

Console.WriteLine("value: {0}", _DynInteger.Integer); 
_DynInteger.Integer = 20; 
Console.WriteLine("value: {0}", _DynInteger.Integer); 

你的, 阿洛伊斯·克勞斯

2

我要添加到西蒙·休斯的答案。我提出了同樣的事情,但添加了一種方法來允許裝飾器類自動更新全局IsDirty標誌。你可能會發現用老式的方式做它不那麼複雜,但這取決於你要公開多少個屬性以及多少個類需要相同的功能。

public class IsDirtyDecorator<T> 
{ 
    private T _myValue; 
    private Action<bool> _changedAction; 

    public IsDirtyDecorator<T>(Action<bool> changedAction = null) 
    { 
     _changedAction = changedAction; 
    } 

    public bool IsDirty { get; private set; } 

    public T Value 
    { 
     get { return _myValue; } 
     set 
     { 
      _myValue = value; 
      IsDirty = true; 
      if(_changedAction != null) 
       _changedAction(IsDirty); 
     } 
    } 
} 

現在你可以有你的裝飾類另一類自動更新一些其他IsDirty屬性:

class MyObject 
{ 
    private IsDirtyDecorator<int> _myInt = new IsDirtyDecorator<int>(onValueChanged); 
    private IsDirtyDecorator<int> _myOtherInt = new IsDirtyDecorator<int>(onValueChanged); 

    public bool IsDirty { get; private set; } 

    public int MyInt 
    { 
     get { return _myInt.Value; } 
     set { _myInt.Value = value; } 
    } 

    public int MyOtherInt 
    { 
     get { return _myOtherInt.Value; } 
     set { _myOtherInt.Value = value; } 
    } 

    private void onValueChanged(bool dirty) 
    { 
     IsDirty = true; 
    } 

}