I answered the same question once, please read my answer here .
In short, this is a very bad design decision, because your method is a hypocrite - it speaks different for different subscribers, but does not speak about it openly. Your API should never, never rely on whoever calls it. In addition, the compiler may unexpectedly break the stack trace due to language functions such as lambdas, yield and await , so even if it worked in Release mode, it would certainly break once.
You effectively create a complex mechanism of indirection instead of using a language function designed to transmit information to methods - method parameters .
Why are you using attributes? Do you read them elsewhere?
If you do this and you do not want to repeat "Email" as a parameter for the GetValue call and attribute value, you can consider passing the Expression<> property to GetValue , which will retrieve the attribute. This seems like your solution, but it is explicit:
[UserPreferenceProperty(Category = "Email", DefaultValue = "My default value")] public string Signature { get { return GetValue (prefs => prefs.Signature); } set { SetValue (prefs => prefs.Signature, value); } }
This answer shows how to implement this.
I see that you are checking Thread.CurrentPrincipal in your code. Again, this is not a good practice, because it is not obvious to the client code that access to the property can lead to an exception. It will be a debugging nightmare for someone who supports your code (and believe me, your code can work for many years in the production process, long after you switch to another project ).
Instead, you should make the VTXIdentity parameter in your settings class constructor. This will ensure that the calling code knows ensure security at this level and, by definition, knows where to get this token. In addition, it allows you to rule out as soon as you know something is wrong. , but not when accessing some property. This will help administrators catch errors earlier, just as compilation errors are better than runtime errors.
Finally, while this is a fun exercise, there are many tried and tested solutions for storing and reading configurations in C # . Why do you think you need to reinvent the wheel?