Подтвердить что ты не робот

Авто реализованные свойства в С#

Есть ли способ продолжать использовать автоматически реализованные свойства, все еще поднимая событие изменения, например INotifyPropertyChanged, когда вызывается Set?

Вместо:

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); 
   }
}

Хотя сеттер выглядит неправильно, возможно ли это сделать, не заполняя мой класс переменными хранилища?

UPDATE: Похоже, что нет стандартного решения для моей ленивой цели, я считаю, что лучшим решением является использование CodeRush или Resharper для создания всех моих резервных хранилищ для меня.

4b9b3361

Ответ 1

Вы не можете этого сделать. Спецификация для автоматически реализованных свойств довольно ясна:

Автоматически реализовано автоматизировать автоматизированные свойства этот узор. Более конкретно, Не абстрактные объявления свойств допускается использование точек с запятой тела. Оба аксессора должны присутствовать и оба должны иметь точки с запятой, но они могут иметь разные модификаторы доступности. Когда свойство указано следующим образом: поле поддержки автоматически будет генерируется для свойства, и аксессоры будут реализованы для чтения от и писать в это фоновое поле. Имя поля поддержки - компилятор создан и недоступен для пользователя.

Другими словами, они могут иметь только "get;" и "set;", с возможностью модификаторов доступа.

Ответ 2

Нет, вы не можете, потому что у вас нет доступа к закрытому полю, сгенерированному для этого свойства

Ответ 4

Это было задано в команде Microsoft за С# 3.0, и они сказали, что подумают об этом, прочитайте здесь.

В комментариях вы найдете больше информации, в том числе, почему это плохая идея, если вам нужно больше контроля, а также способы ее достижения.

Ответ 5

Вы можете использовать некоторую инфраструктуру AOP, например PostSharp.

Но это может снизить производительность и время сборки.

Ответ 6

Поскольку я задал этот вопрос, эта проблема фактически была решена как задача атрибута и сборки: https://github.com/demigor/kindofmagic

Ответ 7

Такое поведение можно выполнить с помощью генератора типа прокси factory. Я уже сделал это в своей разработке Framework. Если вы используете System.Reflection.Emit, вы можете создать прокси-сервер типа. Рассмотрим пример ниже:

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

Ответ 8

Надстройка Fody PropertyChanged делает это. Так же, как KindOfMagic, Fody использует Mono.Cecil для изменения IL-сборников .net во время компиляции. Следующий пример приведен в документации 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));
        }
    }
}

wiki содержит несколько более сложных примеров.

Он доступен с помощью NuGet:

PM> Install-Package PropertyChanged.Fody