11.用反射为静态类的属性赋值 C#例子 WPF例子

  1. 获取字段信息:通过字段名从 Variable_Library 类中获取静态公共属性的 PropertyInfo

  2. 解析值:根据字段类型,将字符串值解析为对应类型的对象。

  3. 赋值:将解析后的值赋给字段,如果字段不存在则输出调试信息。

        public static void AssignValue(string variableName, string variableType, string variableValue)
        {

            // 获取当前类型的字段信息
            PropertyInfo? field = typeof(Variable_Library).GetProperty(variableName, BindingFlags.Static | BindingFlags.Public);

            if (field != null)
            {
                // 根据类型解析值
                object value = ParseValue(variableType, variableValue);

                // 为变量赋值
                field.SetValue(null, value);
            }
            else
            {
                Debug.WriteLine($"Field {variableName} not found.");
            }
        }
详细解析
  1. 获取字段信息

    PropertyInfo? field = typeof(Variable_Library).GetProperty(variableName, BindingFlags.Static | BindingFlags.Public);
    • 使用 typeof(Variable_Library) 获取 Variable_Library 类的类型信息。

    • 调用 GetProperty 方法,传入字段名 variableName 和绑定标志 BindingFlags.Static | BindingFlags.Public,查找静态且公共的属性。

    • 如果找到对应的属性,field 会被赋值为对应的 PropertyInfo 对象;否则为 null

  2. 解析值

    object value = ParseValue(variableType, variableValue);
            private static object ParseValue(string type, string value)
            {
                switch (type)
                {
                    case "string":
                        return value;
                    case "Int32":
                        return int.Parse(value, CultureInfo.InvariantCulture);
                    case "Boolean[]":
    
                        string[] strings = value.Split(' ');
                        bool[] bools=new bool[strings.Length];
                        for (int i = 0; i < strings.Length; i++)
                        {
                            if(!bool.TryParse(strings[i], out bools[i]))
                            {
                                bools[i] = false; // 如果解析失败,默认设置为false
                            }
                        }
                        return bools;
    
                    case "Int64":
                        return long.Parse(value);
                    case "DateTime":
                        return DateTime.Parse(value);
      
                    default:
                        throw new ArgumentException($"Unsupported type: {type}");
                }
            }
    • 调用 ParseValue 方法,根据字段类型 variableType 和字符串值 variableValue,解析出对应类型的对象。

    • ParseValue 方法的作用是将字符串转换为指定类型的值(例如,将字符串 "true" 转换为布尔值 true)。

  1. 赋值

    field.SetValue(null, value);
    • 如果字段存在(field != null),调用 SetValue 方法为字段赋值。

    • null 表示字段是静态的,value 是解析后的值。

  2. 处理字段不存在的情况

    Debug.WriteLine($"Field {variableName} not found.");
    • 如果字段不存在(field == null),输出调试信息,提示字段未找到。

总结

这段代码的作用是:

  • 通过字段名从 Variable_Library 类中查找静态公共属性。

  • 如果找到字段,解析字符串值为对应类型的对象,并为字段赋值。

  • 如果字段不存在,输出调试信息提示。

<think>我们正在讨论的是C#WPF中的依赖属性,特别是只读的静态依赖属性如何赋值的问题。根据引用[1]和引用[2]中的代码示例,我们看到依赖属性是通过`DependencyProperty.Register`方法注册的,并且声明为`publicstaticreadonly`。这意味着依赖属性字段本身是静态且只读的,即一旦注册后,该字段的引用不能被改变(不能重新赋值)。但是,依赖属性的值(即存储在依赖对象中的实际值)是可以改变的。关键点:1.依赖属性字段(如`nameProperty`)是静态只读的,这意味着我们无法在类外部重新给这个字段赋值(例如,`Person.nameProperty=...`是不允许的)。2.但是,依赖属性的值可以通过依赖对象(即`DependencyObject`的实例)的`SetValue`方法来设置。例如,我们可以通过实例的属性包装器(如`Name`属性)来设置值,而属性包装器内部调用`SetValue`方法。因此,问题中的“赋值”实际上有两个不同的层面:-对依赖属性字段本身的赋值(不允许,因为它是只读的)-对依赖属性所关联的值的赋值(允许,通过实例的`SetValue`方法)为什么可以给只读的静态依赖属性赋值(这里指的是属性的值)?因为依赖属性的值并不是存储在依赖属性字段中,而是存储在WPF属性系统中的每个实例的存储空间中。依赖属性字段(静态只读字段)只是一个标识,用于在属性系统中查找和操作该属性的值。具体步骤:1.注册依赖属性:使用`DependencyProperty.Register`方法创建一个`DependencyProperty`实例,并将其赋值给静态只读字段。2.在类中提供属性包装器(CLR包装器),通过调用`GetValue`和`SetValue`来读写该依赖属性的值。所以,当我们通过实例设置依赖属性的值时,实际上是在设置该实例在依赖属性系统中对应此依赖属性的值,而不是修改静态只读字段(也不可能修改)。示例代码(基于引用[1]):```csharppublicclassPerson:DependencyObject{//静态只读的依赖属性字段publicstaticreadonlyDependencyPropertyNameProperty;staticPerson(){//注册依赖属性,初始化NamePropertyNameProperty=DependencyProperty.Register("Name",typeof(string),typeof(Person),newPropertyMetadata("LearningHard",OnValueChanged));}//属性包装器publicstringName{get{return(string)GetValue(NameProperty);}set{SetValue(NameProperty,value);}//这里设置的是当前实例的依赖属性值}privatestaticvoidOnValueChanged(DependencyObjectdpobj,DependencyPropertyChangedEventArgse){//值改变回调}}```使用:```csharpPersonperson=newPerson();person.Name="Tom";//这里通过属性包装器设置值,实际调用SetValue方法```总结:虽然依赖属性字段(如`NameProperty`)是静态且只读的,但我们仍然可以通过实例的`SetValue`方法(或通过属性包装器)来设置每个实例的依赖属性值。这是因为静态只读字段仅仅是一个标识符,真正的值存储在每个实例的依赖属性存储中。因此,只读静态依赖属性的“赋值”实际上是指设置每个实例的值,而不是修改静态字段本身。静态字段在注册后就是固定的,不可修改。相关问题:1.WPF依赖属性的值存储机制是怎样的?2.如何创建只读的依赖属性(即不允许外部设置值)?3.依赖属性与CLR属性在性能上有何差异?注意:在WPF中,还有一种只读依赖属性,即整个依赖属性在实例中都是只读的(不允许通过SetValue设置)。这种依赖属性需要使用`DependencyProperty.RegisterReadOnly`来注册。但问题中讨论的是静态字段只读,而不是依赖属性本身只读。</think>### C# WPF 只读静态依赖属性赋值机制 在C# WPF中,**静态依赖属性字段**声明为`static readonly`(如引用[1][2][4]所示),但可以通过特定方式赋值,这是因为WPF依赖属性系统采用了独特的实现机制。以下是核心原理和实现方式: #### 1. **依赖属性的特殊结构** 依赖属性由两部分组成: ```csharp // 静态只读标识符(不可直接赋值) public static readonly DependencyProperty MyProperty; // 属性包装器(提供访问接口) public int MyValue { get => (int)GetValue(MyProperty); set => SetValue(MyProperty, value); // 通过此方法间接赋值 } ``` - **静态字段只读性**:`DependencyProperty`类型的静态字段是`readonly`,意味着**该字段引用不可更改**(不能重新指向新对象) - **值可修改性**:依赖属性关联的**值**可通过`SetValue()`修改(引用[1][2]) #### 2. **赋值实现原理** 通过**依赖属性系统**而非直接字段赋值: ```csharp // 正确赋值方式(通过属性包装器) myInstance.MyValue = 100; // 等效于底层调用: myInstance.SetValue(MyClass.MyProperty, 100); ``` 此过程: 1. 通过静态只读字段`MyProperty`作为键 2.WPF属性系统中查找/存储值 3. 值存储在**实例的依赖属性存储区**而非静态字段中 #### 3. **只读依赖属性实现** 如需完全只读(禁止外部修改值),需使用`RegisterReadOnly`: ```csharp // 注册只读依赖属性(引用[3]扩展) private static readonly DependencyPropertyKey ReadOnlyPropertyKey = DependencyProperty.RegisterReadOnly( "ReadOnlyValue", typeof(int), typeof(MyClass), new PropertyMetadata(0)); public static readonly DependencyProperty ReadOnlyProperty = ReadOnlyPropertyKey.DependencyProperty; // 仅限类内部赋值 public int ReadOnlyValue { get => (int)GetValue(ReadOnlyProperty); private set => SetValue(ReadOnlyPropertyKey, value); // 使用Key赋值 } ``` 关键点: - `DependencyPropertyKey`提供**受控写权限** - 外部只能通过`ReadOnlyProperty`读取值 - 类内部通过`SetValue(ReadOnlyPropertyKey, value)`修改值 #### 4. **值变更回调(引用[1][3])** 可在注册时指定值变更回调: ```csharp DependencyProperty.Register( "Name", typeof(string), typeof(Person), new PropertyMetadata("Default", OnValueChanged)); // 回调方法 private static void OnValueChanged( DependencyObject d, DependencyPropertyChangedEventArgs e) { // d: 发生值变更的实例 // e.NewValue: 新赋值 } ``` #### 5. **内存优化原理(引用[4])** 依赖属性采用**值继承+默认值共享**机制: - 未显式赋值的实例共享默认值存储 - 显式赋值时创建独立存储 - 大幅减少内存占用(尤其大对象时) ### 总结赋值流程 ```mermaid graph TD A[实例调用属性设置器] --> B[触发SetValue方法] B --> C[通过静态只读DependencyProperty字段定位属性] C --> D[更新实例专属存储区中的值] D --> E[触发PropertyChangedCallback回调] ``` > **关键结论**:静态依赖属性字段的`readonly`仅保护**字段引用不被修改**,通过WPF依赖属性系统的`SetValue()`机制,仍可为每个实例**独立存储和修改属性值**,这是WPF的核心设计特性[^1][^2][^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值