在自动实现的属性C#6.0发生更改后,如何获取其默认编译时值?

在自动实现的属性C#6.0发生更改后,如何获取其默认编译时值?,c#,.net,properties,default-value,c#-6.0,C#,.net,Properties,Default Value,C# 6.0,很快,新的C#6.0自动实现属性允许我们实现这一点 public static bool IsSoundEffects { get; set; } = true; // C# 6.0 allows this 现在在某处,我更改了属性IsSoundEffects=false,因此访问它将是false 嗯,那么如何获得实际的默认编译时自动实现的属性值 类似于: Type.GetPropertyDefaultValue(IsSoundEffects)//一个真正的编译时代码= 真的 或

很快,新的C#6.0自动实现属性允许我们实现这一点

    public static bool IsSoundEffects { get; set; } = true;   // C# 6.0 allows this
现在在某处,我更改了属性
IsSoundEffects=false
,因此访问它将是false

嗯,那么如何获得实际的默认编译时自动实现的属性值

类似于:
Type.GetPropertyDefaultValue(IsSoundEffects)//一个真正的编译时代码=
真的

为什么我需要这个

因为我从数据库中填充属性。并在用户需要恢复默认值时进行恢复。例如设置

看起来很奇怪?我搜索了很多,但是所有关于自动实现功能的示例都没有恢复默认值

已编辑

提供的最佳方法

向彬.庞回答反思方式[短一]

Christopher将常量作为默认值进行回答


属性比get/set函数对的语法更简单。当构造函数运行时,你得到的只是一个基本的、标准的赋值/函数调用。与所有文本和常量一样,它在运行时不应再存在

最简单的方法是使用一个常量,如
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; }
}
公共类可默认{
只读T默认值;
//建造师
公共默认值(T默认值){
this.defaultValue=defaultValue;
//首先设置值
恢复故障();
}
公共过失{
value=this.defaultValue;
}
公共T值{get;set;}
}
编辑2:

在WPF/MVVM圈子里可能有更好的解决方案。许多MVVM使用相同的代码编写属性—一个通过INotifyPropertyChanged发出更改通知的代码。房地产的一个大问题不是偶然写下支持字段


一些人想出了解决方案,比如将实际值和所有代码放入一个类似于
字典的字典中,大部分是自动完成的。然而,我不确定细节。此外,依赖性属性也可能接近它。

您可以使用的一种方法是基于自定义属性。您可以定义为自定义属性来保存默认值。比如说,

public class DefaultValueAttribute:Attribute
{
    public object DefaultValue{get;set;}
    public DefaultValueAttribute(object defaultValue)=>DefaultValue = defaultValue;
}
现在可以使用该属性将默认值存储为

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;
var defaultValue=typeof(SomeClass).GetProperty(nameof(SomeClass.IsSoundEffects),BindingFlags.Public | BindingFlags.Static)
.GetCustomAttribute().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));
}
公共T GetDefaultValue(字符串propertyName) { var result=typeof(SomeClass).GetProperty(nameof(SomeClass.IsSoundEffects),BindingFlags.Public | BindingFlags.Static) .GetCustomAttribute().DefaultValue; return(T)Convert.ChangeType(result,typeof(T)); }
用法

var defaultValue=GetDefaultValue(nameof(SomeClass.IsSoundEffects));
使用

以你的班级为例

class YourClass
{
    public static bool IsSoundEffects { get; set; } = true;   // C# 6.0 allows this
}

并考虑创建“/gp>”的“吸气剂”类

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
}
class DefaultGetter
{
T GetDefault(字符串propertyName),其中T:new()
{        
如果(!defaults.TryGetValue(typeof(T),out var defaultValues)
如果(!defaultValues.TryGetValue(propertyName,out var value))
{
//反思原型获取所有属性信息
//并将它们存储在词典中
//然后分配给值。。。
默认值[typeof(TClass)]=defaultValues=typeof(TClass).GetProperties().Select(x=>new{x.Name,Value=x.GetConstantValue()}.ToDictionary(x=>x.Name);
}
value=defaultValues[propertyName]
}
返回(TProp)值;
}
词典
  • 例如实例属性,只需新建一个实例,然后获取默认属性值是最简单的方法
  • 对于静态属性,可以在静态构造函数中保留默认值

  • 您可以使用以下方法

        public static bool IsSoundEffects { get; set; } = true;   // C# 6.0 allows this
    
  • 如果初始化后不需要更改变量,则使用常量是很好的
  • 如果在协构造函数中只能更改变量,则使用静态只读
  • 使用字典
  • OP:我从数据库中填充属性。如果用户 需要恢复默认值

    这篇文章试图根据你在问题中提到的上述要求来回答。(不是根据问题标题。)

    选项1-使用System.ComponentModel.DefaultValue

    在为属性设置默认值的标准解决方案中,有一种是使用.NET Framework的属性。此模式在.NET Framework的许多类中都存在。例如:

    [System.ComponentModel.DefaultValue(true)]
    public static bool MyProperty{ get; set; } = true; 
    
    然后.NET Framework通过以下方法为您提供重置功能:

    选项2-创建静态默认实例

    您可以拥有该类的静态默认实例,并使用它重置属性

    如果希望将默认实例设置为
    private
    ,可以将其保留为单个实例字段

    如果希望默认实例为
    public
    ,则需要创建一个属性并在
    var defaultIsSoundEffects = defaultGetter.GetDefault<YourClass, bool>("IsSoundEffects");
    
        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]);
    }
    
    [System.ComponentModel.DefaultValue(true)]
    public static bool MyProperty{ get; set; } = true; 
    
    System.ComponentModel.TypeDescriptor.GetProperties(this)["MyProperty"].ResetValue(this);
    
    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;
        }
    }