NotifyPropertyChanged没有触发事件[PostSharp]

时间:2016-07-17 18:31:33

标签: c# postsharp

我是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

当我在getter&amp ;;中使用方法时,事件不会触发setters虽然标记为纯粹,但是当它是一个简单的属性时工作正常。

我花了最后一天在谷歌搜索答案,没有运气;没有线程解决了我的问题。

我错过了什么?

1 个答案:

答案 0 :(得分: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传递该信息。