在自动实现的属性C#6.0发生更改后,如何获取其默认编译时值?
很快,新的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)//一个真正的编译时代码= 真的 或
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;
}
}