2011-11-29 113 views
3

我可以寫這樣beatiful簡單代碼:如果我需要自定義getter/setter,我可以省略字段創建嗎?

public int Delta { get; private set; } 

現在我想補充只需一個電話OnPropertyChanged("Delta");

這是我知道如何做到這一點的唯一方法:

public int Delta { get { return _delta; } private set 
{ 
    _delta = value; OnPropertyChanged("Delta"); } 
} 
private int _delta; 

這是太多的額外代碼!爲什麼我應該在這種情況下介紹領域?你能縮短這段代碼嗎?我想有類似的東西,但它不起作用:

public int Delta { get; private set { OnPropertyChanged("Delta"); } } 

回答

6

不,你不能用自動屬性做到這一點。自動屬性意味着對一個屬性在字段上的簡短語法。他們幾乎沒有其他能力。任何自定義代碼執行都需要一個完整的屬性。

0

不幸的是,情況就是如此。如果您使用的是C#4.0,則可以使用dynamic object,並使用較少的代碼來代替類型安全。

概括地說,你做

public override bool TrySetMember(SetMemberBinder binder, object value) 
{ 
    //set the actual property and do 
    OnPropertyChanged(binder.Name);  
} 

可能有更多的代碼在寫TrySetMember,但你可以在同一個班級跨多個屬性共享。

如果DONOT介意任何第三方框架,你可以使用一個AOP框架PostSharp,做鍋爐板代碼爲您服務。

1

.NET屬性是在引擎蓋下生成的方法type get_PropertyName()set_PropertyName(type value)的句法糖,get_返回基礎字段值,並且set_明顯更新它。所以有兩種選擇:要麼通過指定屬性getter/setter來提供自己的方法體,要麼通過爲你生成後臺字段來讓它執行,所以根本沒有第三種情況。

0

不幸的是,沒有辦法做到這一點。這種類型的構造對於面向Aspect的編程是可能的,但在目前爲止的任何產品發佈的C#編譯器中都不可用。

有沒有通用的更好的方法來做到這一點,但你可以嘗試使用模板引擎,如VS的片段的Resharpers片段來更快地寫入。

在某些情況下,當元數據可用時,您還可以使用代碼生成來簡化操作。

1

如果你想簡化你PropertyChanged例程,你可以看看notifypropertyweaver

而在這之後你的代碼將看起來像:

[NotifyProperty(PerformEqualityCheck = false)] 
public int Delta { get; set; } 
3

我創造了這個代碼段用於此目的(例如):

private string _Name; 
public string Name 
{ 
    get { return _Name; } 
    set 
    { 
     if (_Name != value) { 
      _Name = value; 
      OnPropertyChanged("Name"); 
     } 
    } 
} 

段:

<?xml version="1.0"?> 
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> 
    <CodeSnippet Format="1.0.0"> 
    <Header> 
     <SnippetTypes> 
     <SnippetType>Expansion</SnippetType> 
     </SnippetTypes> 
     <Title>propn (Creates a notifying property)</Title> 
     <Shortcut>propn</Shortcut> 
     <Description>This snippet helps implementing INotifyPropertyChanged by creating a property with backing store. The settter calls OnPropertyChanged if the value changes. Use the "notify" code snippet in order to implement INotifyPropertyChanged.</Description> 
     <Author>Olivier Jacot-Descombes</Author> 
    </Header> 
    <Snippet> 
     <Declarations> 
     <Literal Editable="false"> 
      <ID>classname</ID> 
      <ToolTip>Name of class</ToolTip> 
      <Default>ClassNamePlaceholder</Default> 
      <Function>ClassName()</Function> 
     </Literal> 
     <Literal Editable="true"> 
      <ID>NameOfProperty</ID> 
      <ToolTip> 
      </ToolTip> 
      <Default>MyProp</Default> 
      <Function> 
      </Function> 
     </Literal> 
     <Literal Editable="true"> 
      <ID>Type</ID> 
      <ToolTip> 
      </ToolTip> 
      <Default>int</Default> 
      <Function> 
      </Function> 
     </Literal> 
     </Declarations> 
     <Code Language="csharp"><![CDATA[private $Type$ _$NameOfProperty$; 
public $Type$ $NameOfProperty$ 
{ 
    get { return _$NameOfProperty$; } 
    set 
    { 
     if (_$NameOfProperty$ != value) { 
      _$NameOfProperty$ = value; 
      OnPropertyChanged("$NameOfProperty$"); 
     } 
    } 
} 
]]></Code> 
    </Snippet> 
    </CodeSnippet> 
</CodeSnippets> 

複製這段代碼放到一個文本文件中。給它擴展名「.snippet」,你可以使用代碼段管理器(工具菜單)將它導入到Visual Studio中。

在這裏,它創建的事件處理程序(例如)另一片段:

#region INotifyPropertyChanged Members 

public event PropertyChangedEventHandler PropertyChanged; 
//TODO: Inherit interface System.ComponentModel.INotifyPropertyChanged. 
//TODO: Create properties with the propn code snippet. 

private void OnPropertyChanged(string propertyName) 
{ 
    var handler = PropertyChanged; 
    if (handler != null) { 
     handler(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

#endregion 

段:

<?xml version="1.0"?> 
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> 
    <CodeSnippet Format="1.0.0"> 
    <Header> 
     <SnippetTypes> 
     <SnippetType>Expansion</SnippetType> 
     </SnippetTypes> 
     <Title>notify (Implements INotifyPropertyChanged)</Title> 
     <Shortcut>notify</Shortcut> 
     <Description>This snippet the inserts the INotifyPropertyChanged implementation into a class</Description> 
     <Author>Olivier Jacot-Descombes</Author> 
    </Header> 
    <Snippet> 
     <Declarations> 
     <Literal Editable="false"> 
      <ID>classname</ID> 
      <ToolTip>Name of class</ToolTip> 
      <Default>ClassNamePlaceholder</Default> 
      <Function>ClassName()</Function> 
     </Literal> 
     </Declarations> 
     <Code Language="csharp"><![CDATA[#region INotifyPropertyChanged Members 

public event PropertyChangedEventHandler PropertyChanged; 
//TODO: Inherit interface System.ComponentModel.INotifyPropertyChanged. 
//TODO: Create properties with the propn code snippet. 

private void OnPropertyChanged(string propertyName) 
{ 
    var handler = PropertyChanged; 
    if (handler != null) { 
     handler(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

#endregion]]></Code> 
    </Snippet> 
    </CodeSnippet> 
    <CodeSnippet Format="1.0.0"> 
    <Header> 
     <Title> 
     </Title> 
     <Shortcut> 
     </Shortcut> 
     <Description> 
     </Description> 
     <Author> 
     </Author> 
    </Header> 
    <Snippet> 
     <Code Language="csharp"><![CDATA[]]></Code> 
    </Snippet> 
    </CodeSnippet> 
</CodeSnippets> 
+0

這些片段是幹什麼的?你能提供一個C#示例嗎? – sll

+0

@sll:我將exmaples添加到了我原來的答案中。 –

0

自動屬性是一個 「全有或全無」 的交易。

他們所做的只是創建一個支持字段,在get訪問器中返回它的值並在set訪問器中設置它的值。如果你想做額外的事情,你必須定義後臺字段並手動實現get和set。沒有辦法繞過它。

你可能想知道爲什麼你甚至需要一個自動屬性,如果它沒有任何邏輯?爲什麼不只是定義一個公共領域?但讓我們假設你定義了一個自動屬性和其他程序集使用你的程序集。現在,如果您決定更改爲手動實現的屬性來添加一些邏輯,則使用您的程序集的程序集不必重新編譯。如果你從一個字段切換到一個屬性,他們將會中斷並且必須重新編譯。

這裏是直接鏈接到我的我的互動.NET教程,我討論了很多細節性的部分:http://motti.me/s2a

,這裏是整個教程鏈接,如果傻冒感興趣:http://motti.me/c0

我希望這有助於!

相關問題