I'm new to PostSharp (just got my license) and I've been trying to use it in my app. I have a settings class a following:
[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");
}
}
Then on my subscriber class:
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
The event doesn't fire when I use methods in my getters & setters, although marked pure, but works fine when it's a simple property.
I spent the last day scouring Google for answers, without luck; no thread solves my problem.
What am I missing ?
[NotifyPropertyChanged]
aspect detects changes to fields of the class and then fires appropriate events based on detected dependencies (property value depending on that specific field).
In your case this is exactly what test2
property does and why aspect works on that property.
On the other hand test
property cannot work automatically. The value of the property depends on ConfigurationManager.AppSettings.Item
. First problem is that AppSettings
is a static property, ie it is not possible to detect changes to it. If assumed that it never changes, then second problem is that NameValueCollection
does not implement INotifyPropertyChanged
, which means that there is no way of knowing that the value actually changed.
You are not getting any warnings because you have marked both methods as Pure
which they are not in usual sense of the word. GetValue
uses global mutable state. SetValue
changes the global mutable state.
Since there is no way to hook to AppSettings
in order to receive changes to the collection, you need to raise changed notification when the property is set. This can be done by calling NotifyPropertyChangedServices.SignalPropertyChanged
method. Your code would then look like this:
[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);
}
}
Note that if multiple instance of Consts
class exist, they will not share changes there is no way to pass that information through ConfigurationManaged
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.