[英]How to get default compile-time value of Auto-Implemented property C# 6.0 after it changed?
不久,新的 C# 6.0 自動實現的屬性使我們能夠做到這一點
public static bool IsSoundEffects { get; set; } = true; // C# 6.0 allows this
現在在某個地方,我更改了屬性IsSoundEffects = false
,因此訪問它是錯誤的。
嗯,那么如何獲得實際真正的默認編譯時自動實現的屬性值。
就像是:
Type.GetPropertyDefaultValue(IsSoundEffects);
// 真正的編譯時 one = true
或者
default(IsSoundEffects) // idk, something like that
為什么我需要那個?
因為我從數據庫中填充屬性。 如果用戶需要恢復默認值,則恢復它。 例如設置。
看起來很奇怪? 我進行了足夠多的搜索,但所有關於自動實現功能的示例都沒有恢復默認值。
已編輯
提供的最佳方法
xiangbin.pang對反射方式的回答[Short-One]
Christopher將常量作為默認值回答。
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
}
}
問題作者添加的以下行:
用於設置具有默認值的屬性
private static void ResetPropertyValue(string PropertyName)
{
typeof(Options).GetProperty(PropertyName).SetValue(null,
defaultValues[PropertyName]);
}
屬性只是獲取/設置 function 對的語法糖。 當構造函數運行時,你得到的只是一個基本的、沼澤標准的賦值/函數調用。 與所有文字和常量一樣,它在運行時不應再存在。
天真的方法是有一個像IsSoundEffectsDefaultValue
這樣的常量。 我確實認為在大多數情況下這已經足夠了。
我的一個舊想法很有可能適用於您更廣泛的問題。 但是,我需要搜索代碼。
編輯:
不幸的是,我找不到我的舊代碼。 但是,我可以重新創建它。 基本思想是擁有多個“層”值,其中一個值隱藏(但不覆蓋)另一個值。
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; }
}
編輯2:
WPF/MVVM 圈子中可能有更好的解決方案。 許多 MVVM 正在使用相同的代碼編寫屬性 - 一個通過 INotifyPropertyChanged 引發更改通知的代碼。 屬性的一個大問題不是偶然寫入支持字段。
有些人想出了解決方案,例如將實際值和所有代碼自動放入Dictionar<string, object>
之類的東西中。 但是,我不確定細節。 DependancyProperties 也可能接近它。
您可以使用的一種方法是基於自定義屬性。 您可以定義為自定義屬性來保存默認值。 例如,
public class DefaultValueAttribute:Attribute
{
public object DefaultValue{get;set;}
public DefaultValueAttribute(object defaultValue)=>DefaultValue = defaultValue;
}
您現在可以使用 Attribute 將默認值存儲為
public static class SomeClass
{
[DefaultValueAttribute(true)]
public static bool IsSoundEffects { get; set; } = true;
}
為了檢索相同的內容,您可以依賴反射。
var defaultValue = typeof(SomeClass).GetProperty(nameof(SomeClass.IsSoundEffects), BindingFlags.Public | BindingFlags.Static)
.GetCustomAttribute<DefaultValueAttribute>().DefaultValue;
使反射調用成為與其他屬性一起使用的通用方法。
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));
}
用法
var defaultValue = GetDefaultValue<bool>(nameof(SomeClass.IsSoundEffects));
OP :我從數據庫中填充屬性。 如果用戶需要恢復默認值,則恢復它。
這篇文章試圖根據您在問題中提到的上述要求來回答。(不是基於問題標題。)
選項 1 - 使用 System.ComponentModel.DefaultValue
設置屬性默認值的標准解決方案之一是使用 .NET 框架的DefaultValue
屬性。 您可以在 .NET 框架的很多類中看到這種模式。 例如:
[System.ComponentModel.DefaultValue(true)]
public static bool MyProperty{ get; set; } = true;
然后 .NET 框架通過PropertyDescriptor.ResetValue
方法為您提供重置功能:
System.ComponentModel.TypeDescriptor.GetProperties(this)["MyProperty"].ResetValue(this);
選項 2 - 創建 static 默認實例
您可以擁有 class 的默認實例 static 並將其用於重置屬性。
如果您想將默認實例設為private
,您可以將其保留為單個實例字段。
如果您希望將默認實例設為public
,您需要創建一個屬性並在 getter 中返回一個新實例。
public class MyClass
{
private static readonly MyClass Default = new MyClass();
//OR
//public static MyClass Default { get { return new MyClass(); } }
public bool MyProperty{ get; set; } = true;
public void Reset()
{
this.MyProperty = Default.MyProperty;
}
}
使用PropertyInfo.GetConstantValue 方法。
考慮您的 class
class YourClass
{
public static bool IsSoundEffects { get; set; } = true; // C# 6.0 allows this
}
並考慮您創建的“吸氣劑” class
class DefaultGetter
{
T GetDefault<TClass, TProp>(string propertyName) where T : new()
{
if (!defaults.TryGetValue(typeof(T), out var defaultValues)
if (!defaultValues.TryGetValue(propertyName, out var value))
{
// reflect on prototype getting all the PropertyInfo
// and store them in the dictionary of dictionaries
// then assign to value...
defaults[typeof(TClass)] = defaultValues = typeof(TClass).GetProperties().Select(x => new { x.Name, Value = x.GetConstantValue() }).ToDictionary(x => x.Name);
}
value = defaultValues[propertyName]
}
return (TProp)value;
}
IDictionary<Type, IDictionary<string, object> defaults = new ... // elided for brevity
}
你會像這樣使用它:
var defaultIsSoundEffects = defaultGetter.GetDefault<YourClass, bool>("IsSoundEffects");
您可以使用以下方法
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.