2011-11-29 41 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

我希望这有助于!

相关问题