Shortly, The new C# 6.0 Auto-Implemented Property allows us to make this
public static bool IsSoundEffects { get; set; } = true; // C# 6.0 allows this
Now in somewhere, I changed the property IsSoundEffects = false
, So accessing it will be false.
hmm, So how to get the actual real default compile-time auto-implemented property value.
Something Like :Type.GetPropertyDefaultValue(IsSoundEffects);
// A real compile-time one =
true
OR
default(IsSoundEffects) // idk, something like that
Why I need that?
because I filling the properties from the database. and restore it if user need to restore the default values. for example settings.
Looks strange? I searched enough but all examples about the auto-implemented feature did not restore the default value.
Edited
The best approaches provided by
xiangbin.pang answer for reflection way [Short-One]
Christopher answers for constants as default values.
public static class MyClass
{
public static int MyProp1 { get; set; } = 100;
public static bool MyProp2 { get; set; } = false;
private static Dictionary<string, object> defaultValues;
static MyClass()
{
defaultValues = new Dictionary<string, object>();
foreach(var prop in typeof(MyClass).GetProperties(BindingFlags.Static| BindingFlags.Public | BindingFlags.NonPublic))
{
defaultValues[prop.Name] = prop.GetValue(null);
}
}
public static (T,bool) GetDefault<T>(string propName)
{
if(defaultValues.TryGetValue(propName, out object value))
{
return ((T)(value), true);
}
return (default, false);
}
}
//test codes
static void Main(string[] args)
{
MyClass.MyProp1 = 1000;
MyClass.MyProp2 = true;
var defaultValueOrProp1 = MyClass.GetDefault<int>("MyProp1");
if(defaultValueOrProp1.Item2)
{
Console.WriteLine(defaultValueOrProp1.Item1);//100
}
var defaultValueOrProp2 = MyClass.GetDefault<bool>("MyProp2");
if (defaultValueOrProp2.Item2)
{
Console.WriteLine(defaultValueOrProp2.Item1);//false
}
}
Following Line added by question author:
For setting property with default value
private static void ResetPropertyValue(string PropertyName)
{
typeof(Options).GetProperty(PropertyName).SetValue(null,
defaultValues[PropertyName]);
}
Properties are little more then Syntax sugar for get/set function pairs. And what you got there is little more then a basic, bog-standart assignment/function call around when the constructor runs. As all literals and constatns, it should no longer exist at runtime.
The naive way would be to have a constant like IsSoundEffectsDefaultValue
. And I do think that is sufficient in most cases.
There is a off-chance that a old idea of mine might apply to your broader problem. I need to search for the code however.
Edit:
I could not find my old code, unfortunately. I can re-create it however. The basic idea is to have multiple "layers" of values, with one value hiding (but not overwriting) the other.
public class defaultAble<T>{
readonly T defaultValue;
//constructor
public defaultAble(T defaultValue){
this.defaultValue = defaultValue;
//First set the value
RestoreDefault();
}
public RestoreDefault(){
value = this.defaultValue;
}
public T value { get; set; }
}
Edit 2:
There might be a even better solution in WPF/MVVM circles. A lot of MVVM is writing properties with the same code - one that raises change notification by INotifyPropertyChanged. And a big issue with Properties is not writing the backing field by accident.
Some people figured out solutions like putting the actuall value and all the code into a something like a Dictionar<string, object>
mostly automagically. I am not sure about the details, however. Also DependancyProperties might get close to it too.
One approach you could use would be based on Custom Attributes. You could define as Custom Attribute to hold the default value. For example,
public class DefaultValueAttribute:Attribute
{
public object DefaultValue{get;set;}
public DefaultValueAttribute(object defaultValue)=>DefaultValue = defaultValue;
}
You can now use the Attribute to store the default value as
public static class SomeClass
{
[DefaultValueAttribute(true)]
public static bool IsSoundEffects { get; set; } = true;
}
For retrieving the same, you could depend on reflection.
var defaultValue = typeof(SomeClass).GetProperty(nameof(SomeClass.IsSoundEffects), BindingFlags.Public | BindingFlags.Static)
.GetCustomAttribute<DefaultValueAttribute>().DefaultValue;
Making the reflection call a generic method to be used with other properties.
public T GetDefaultValue<T>(string propertyName)
{
var result = typeof(SomeClass).GetProperty(nameof(SomeClass.IsSoundEffects), BindingFlags.Public | BindingFlags.Static)
.GetCustomAttribute<DefaultValueAttribute>().DefaultValue;
return (T)Convert.ChangeType(result,typeof(T));
}
Usage
var defaultValue = GetDefaultValue<bool>(nameof(SomeClass.IsSoundEffects));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With