【问题标题】:PropertyInfo.SetValue for an array is not working数组的 PropertyInfo.SetValue 不起作用
【发布时间】:2015-01-21 06:36:43
【问题描述】:

我正在使用 .Net 2013、Windows7。我能够使用反射设置和获取单个值。当我尝试使用反射在数组中设置值时,我无法这样做。使用反射,我可以获取数组中的值。

我发现在数组中设置值似乎是一种解决方法,但我不明白为什么 SetValue 函数不起作用。下面是我的代码。

            property = type.GetProperty("propDeviceMessageMask", BindingFlags.Public | BindingFlags.Instance);
            if (property != null)
            {
                DEVICE_MESSAGE_MASK_Types[] value = (DEVICE_MESSAGE_MASK_Types[])property.GetValue(device, null);

                value[0] = DEVICE_MESSAGE_MASK_Types.Disabled;
                value[1] = DEVICE_MESSAGE_MASK_Types.Disabled;
                value[2] = DEVICE_MESSAGE_MASK_Types.Disabled;
                value[3] = DEVICE_MESSAGE_MASK_Types.Disabled;

                property.SetValue(device, DEVICE_MESSAGE_MASK_Types.Disabled, new object[] { (int)4 });
            }

propDeviceMessageMask 是一个包含 8 个 DEVICE_MESSAGE_MASK_Type 的数组。我可以使用 GetValue 函数获取整个数组。我可以使用索引 0-3 编辑值。当我尝试使用 SetValue 函数更新索引 4 时,我在 TargetParameterCountException 中得到参数计数不匹配。

【问题讨论】:

  • 顺便说一句,没有.Net 2013之类的东西。有一个Visual Studio 2013版,但这无助于我们回答您的问题,因为那是一个没有直接关系的编辑器与最终产品。您的目标是哪个版本的 .Net 将是包含在 C# 中的更好标签。

标签: c# reflection


【解决方案1】:

异常意味着索引中的参数数量与索引属性所采用的参数数量不匹配。所以在你的情况下,数字是 4,但数组没有这个索引。试试这个,它会工作:

// valid indexes are 0, 1, 2 and 3
property.SetValue(device, DEVICE_MESSAGE_MASK_Types.Disabled, new object[] { (int)3 });

有关如何使用 SetValue 方法以及如何解释 MSDN 中抛出的异常的更多详细信息:https://msdn.microsoft.com/en-us/library/xb5dd1f1(v=vs.110).aspx

【讨论】:

    【解决方案2】:

    首先,了解arrays 是.NET 中的固定大小。如果您的 propDeviceMessageMask 数组最初有 8 个项目,那么您应该能够使用与索引 0 到 3 相同的语法来设置索引 0 到 7 的值:

     value[4] = DEVICE_MESSAGE_MASK_Types.Disabled;
    

    但是,如果您的数组最初只有 4 个项目,那么您可以在索引 0 到 3 处设置这些值,但不能在索引 4(第五个项目)处设置值。如果您需要存储 5 个项目,则必须分配一个包含 5 个项目的新数组,并将前 4 个值复制到新数组中。然后您可以将该新数组分配给该属性。

    或者,如果您可以修改原始类,您可能应该使用List<T>,它比数组更优雅地处理动态添加/删除项目。

    其次,听起来你有一个这样定义的属性:

    public DEVICE_MESSAGE_MASK_Types[] propDeviceMessageMask { get; set; }
    

    重要的是要意识到这与索引器属性非常不同(即使语法在某些方面相似),看起来像这样:

    public DEVICE_MESSAGE_MASK_Types this[int index] { ... }
    

    GetValue / SetValue 方法中的index 参数只能用于后一种属性。因此,要将这个修改后的数组的值设置回您的原始对象,您必须将 index 参数留空:

    property.SetValue(device, value, null);
    

    【讨论】:

    • 感谢您指出属性和索引器属性之间的区别。
    【解决方案3】:

    具有数组类型的属性与索引属性不同,尽管两者的“通常”源代码看起来像

    obj.prop[index]
    

    在进行反思时,差异非常重要。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多