2016-07-17 2 views
0

Я новичок в PostSharp (только что получил мою лицензию), и я пытался использовать его в своем приложении. У меня есть класс параметров следующий:NotifyPropertyChanged not firing event [PostSharp]

[NotifyPropertyChanged] 
public class Consts 
{ 
    public string test2 {get; set;} = "foobar"; 

    public string test 
    { 
     get { return GetValue("test"); } 
     set { UpdateSetting(nameof(test), value.ToString(CultureInfo.InvariantCulture)); } 
    } 

    [Pure] 
    public static string GetValue(string s) => ConfigurationManager.AppSettings[nameof(s)]; 

    [Pure] 
    private static void UpdateSetting(string key, string value) 
    { 
     var cfg = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); 

     cfg.AppSettings.Settings[key].Value = value; 
     cfg.Save(ConfigurationSaveMode.Modified); 

     ConfigurationManager.RefreshSection("appSettings"); 
    } 
} 

Тогда на мой абонентский класс:

var cst = new Consts(); 
Post.Cast<Consts, INotifyPropertyChanged>(cst).PropertyChanged += 
       (o, args) => Debug.Write("PropertyChanged fired"); 
cst.test = "test test"; // Gives no result 
cst.test2 = "test test"; // Event firing correctly 

событие не срабатывает, когда я использую методы в моих добытчиками & сеттеров, хотя отмечен чистый, но работает отлично, когда это простое свойство.

Я провел последний день, пытаясь найти ответы на ваши вопросы без везения; ни одна нить не решает мою проблему.

Что мне не хватает?

ответ

1

[NotifyPropertyChanged] аспект обнаруживает изменения в полях класса, а затем запускает соответствующие события на основе обнаруженных зависимостей (значение свойства зависит от этого конкретного поля).

В вашем случае это именно то, что делает свойство test2, и почему аспект работает над этим свойством.

С другой стороны, test не может работать автоматически. Значение свойства зависит от ConfigurationManager.AppSettings.Item. Первая проблема заключается в том, что AppSettings является статическим свойством, то есть невозможно обнаружить изменения в нем. Если предположить, что он никогда не изменяется, то вторая проблема заключается в том, что NameValueCollection не реализует INotifyPropertyChanged, что означает, что нет способа узнать, что значение действительно изменилось.

Вы не получаете никаких предупреждений, потому что вы отметили оба метода как Pure, которые они не в обычном понимании этого слова. GetValue использует глобальное изменчивое состояние. SetValue изменяет глобальное изменяемое состояние.

Поскольку для получения изменений в коллекции нет возможности подключиться к AppSettings, вам необходимо поднять измененное уведомление, когда свойство установлено. Это можно сделать, вызвав метод NotifyPropertyChangedServices.SignalPropertyChanged. Ваш код будет выглядеть следующим образом:

[NotifyPropertyChanged] 
public class Consts 
{ 
    public string test2 { get; set; } = "foobar"; 

    public string test 
    { 
     get { return GetValue("test"); } 
     set { UpdateSetting(nameof(test), value.ToString(CultureInfo.InvariantCulture)); } 
    } 

    [SafeForDependencyAnalysis] 
    public string GetValue(string s) => ConfigurationManager.AppSettings[nameof(s)]; 

    private void UpdateSetting(string key, string value) 
    { 
     var cfg = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); 

     cfg.AppSettings.Settings[key].Value = value; 
     cfg.Save(ConfigurationSaveMode.Modified); 

     ConfigurationManager.RefreshSection("appSettings"); 
     NotifyPropertyChangedServices.SignalPropertyChanged(this, key); 
    } 
} 

Обратите внимание, что если несколько экземпляра Consts класса существует, то они не будут делить изменения нет никакого способа, чтобы передать эту информацию через ConfigurationManaged.

+0

Я не знаю, кто вы, но я найду вас и дам вам медаль. –