繁体   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