C#中的自动属性实现

13
有没有一种方法可以在调用Set时仍然触发更改事件(例如< strong> INotifyPropertyChanged ),同时继续使用自动实现属性?
而不是:
private string _value;
public string Value
{
  get 
  { 
    return this._value;
  }
  set
  {
    this._value = value;
    this.ValueChanged(this,EventArgs.Empty);
  }
}

我可以直接这样做吗:

public string Value 
{ 
   get; 
   set 
   { 
     this.ValueChanged(this,EventArgs.Empty); 
   }
}

尽管setter看起来不对,但是有没有可能在不向我的类中添加后备存储变量的情况下完成这个任务?

更新:看起来没有标准解决方案符合我的懒惰目标,我认为最好的解决方案是使用CodeRush或Resharper为我生成所有后备存储。

8个回答

6
您无法这样做。自动实现属性的规范非常清晰:
自动实现属性自动化了这种模式。更具体地说,非抽象属性声明允许具有分号访问器主体。两个访问器必须都存在且都必须具有分号主体,但它们可以具有不同的可访问性修饰符。当以这种方式指定属性时,将自动生成用于该属性的后备字段,并实现访问器以从该后备字段读取和写入。后备字段的名称是由编译器生成的,对用户不可访问。
换句话说,它们只能具有“get;”和“set;”,并带有访问修饰符的可能性。

4

不可以,因为您无法访问为该属性生成的私有字段。


4

虽然我能看出这个方法可以工作,但实际上它看起来比使用备份存储变量更混乱。 - benPearce
benPearce: 自动属性是指当您不想在setter或getter中编写任何其他代码时使用的属性。如果您需要这样做(例如通知属性更改),则需要编写代码。我不同意PostSharp的方法,但它确实是某种解决方案。我很习惯手动编写变量的代码。 - Noon Silk
丝滑:我同意你关于Postsharp的看法,虽然它是一个解决方案,但我并不特别喜欢它。 - benPearce

1

1

这个问题已经被提出给了 C# 3.0 的微软团队,他们表示会考虑一下,可以在这里阅读

在评论中,您会找到更多信息,包括为什么如果您需要更多控制,这是一个不好的想法,以及实现它的方法。


1

你可以使用一些AOP框架,比如PostSharp

但这可能会降低性能和构建时间。


看起来Postsharp 2.0正好可以做到这一点 - http://www.postsharp.org/blog/introducing-postsharp-20-1-notifypropertychanged - benPearce

0

这种行为可以通过代理工厂类型生成器来实现。我已经在我的开发框架中做过了。如果你使用System.Reflection.Emit,你可以创建一个类型的代理。

var a = Proxier<InputType>.CreateInstance(new object[] { }); // object arrays are for different constructors
a.PropertyAccessed += ...

0
Fody插件PropertyChanged可以实现此功能。就像KindOfMagic一样,Fody在编译时使用Mono.Cecil修改.net程序集的IL代码。 PropertyChanged文档中列出了以下示例:

您可以这样写:

[ImplementPropertyChanged]
public class Person 
{        
    public string GivenNames { get; set; }
    public string FamilyName { get; set; }

    public string FullName
    {
        get
        {
            return string.Format("{0} {1}", GivenNames, FamilyName);
        }
    }
}

被编译的内容:

public class Person : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    string givenNames;
    public string GivenNames
    {
        get { return givenNames; }
        set
        {
            if (value != givenNames)
            {
                givenNames = value;
                OnPropertyChanged("GivenNames");
                OnPropertyChanged("FullName");
            }
        }
    }

    string familyName;
    public string FamilyName
    {
        get { return familyName; }
        set 
        {
            if (value != familyName)
            {
                familyName = value;
                OnPropertyChanged("FamilyName");
                OnPropertyChanged("FullName");
            }
        }
    }

    public string FullName
    {
        get
        {
            return string.Format("{0} {1}", GivenNames, FamilyName);
        }
    }

    public virtual void OnPropertyChanged(string propertyName)
    {
        var propertyChanged = PropertyChanged;
        if (propertyChanged != null)
        {
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

维基 包含一些更高级的示例。

可以使用 NuGet 获取:

PM> Install-Package PropertyChanged.Fody

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接