簡體   English   中英

更改后如何獲取自動實現屬性 C# 6.0 的默認編譯時值?

[英]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將常量作為默認值回答。

  1. 例如實例屬性,只需新建一個實例然后獲取默認屬性值是最簡單的方法。
  2. 對於 static 屬性,可以在 static 構造函數中保留默認值。
    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");

您可以使用以下方法

  1. 如果在初始化后不需要更改變量,使用常量是很好的。
  2. 如果只有變量可以在 cosntructor 中更改,則只讀使用 static。
  3. 使用字典

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM