SettingsPropertyValue.SerializedValue 为 null,除非我通过局部变量查看变量

发布于 2024-12-16 11:41:44 字数 1261 浏览 3 评论 0原文

我将 C# 程序中使用的一些常见设置存储在 ApplicationSettings 中。大多数设置都是字符串,但其中之一是 StringCollection。

某些循环遍历 Properties.Settings.Default 处的默认设置并将它们添加到字典中(准备作为参数发送)的代码中发生空异常,如下所示。

// Generate parameters
Dictionary<string, string> signalparams = new Dictionary<string, string>();

// Add parameters
foreach (SettingsProperty property in Properties.Settings.Default.Properties)
{
    SettingsPropertyValue value = new SettingsPropertyValue(property);

    if (value.Property.SerializeAs == SettingsSerializeAs.Xml)
    {
        // Here's where the error occurs
        signalparams.Add(value.Name, value.SerializedValue.ToString());
    }
    else if (value.Property.SerializeAs == SettingsSerializeAs.String)
    {
        signalparams.Add(value.Name, value.PropertyValue.ToString());
    }
}

字符串设置添加得很好,但是当它到达 StringCollection 时,它(正确地)评估该属性具有 SerializeAs == SettingsSerializeAs.Xml。但是,SerializedValue 为 null,因此 ToString() 会引发异常。

奇怪的是,运行调试器时,SerializedValue 为 null ,直到我尝试在本地窗口中查看 value 变量的属性。此时,SerializedValue 包含 StringCollection 的正确 XML 序列化格式,并且程序继续正常运行。

为什么会发生这种情况?

I'm storing some common settings used in a C# program inside the ApplicationSettings. Most of the settings are strings, but one of them is a StringCollection.

A null exception is occurring in some code that loops through the default settings at Properties.Settings.Default and adds them to a dictionary (in preparation to send as parameters), as shown below.

// Generate parameters
Dictionary<string, string> signalparams = new Dictionary<string, string>();

// Add parameters
foreach (SettingsProperty property in Properties.Settings.Default.Properties)
{
    SettingsPropertyValue value = new SettingsPropertyValue(property);

    if (value.Property.SerializeAs == SettingsSerializeAs.Xml)
    {
        // Here's where the error occurs
        signalparams.Add(value.Name, value.SerializedValue.ToString());
    }
    else if (value.Property.SerializeAs == SettingsSerializeAs.String)
    {
        signalparams.Add(value.Name, value.PropertyValue.ToString());
    }
}

The strings settings are added fine, but when it reaches the StringCollection, it (correctly) evaluates that the property has SerializeAs == SettingsSerializeAs.Xml. However, the SerializedValue is null, and thus ToString() throws an exception.

The strange thing is that when running the debugger, the SerializedValue is null until I try viewing the value variable's properties in the locals windows. At that point, SerializedValue contains the correct XML serialized format for the StringCollection, and the program continues fine.

Why is this happening?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浸婚纱 2024-12-23 11:41:44

该问题可能源于以下事实: SerializedValue 是一个实现类似以下内容的属性:

public object SerializedValue
{
  get
  {
    if (this._ChangedSinceLastSerialized)
       return CalculateSerializedData();
    else
       return _cachedData;
   }
}

在我看来,在您的情况下发生的情况是,当您第一次访问SettingPropertyValue 时,您将获得 _cachedData,然后,通过调试器查看 value,您会导致 _ChangedSinceLastSerializedtrue,从而导致下一次调用SerializedValue 属性返回实际的序列化值。

下一个问题是找出为什么在您的情况下 _ChangedSinceLastSerialized 设置为 falseSettingsPropertyValue 的逻辑表明(您可以在 Reflector 中类的 PropertyValue 属性中看到它),当用户访问设置(对于大多数对象类型),因此例如仅像这样访问您的设置: MyAppSettings.Default.MySettingObject 就会更改_ChangedSinceLastSerializedtrue

如果您有与此类似的代码,可能会发生什么情况:

object storingObject = MyAppSettings.Default.MySettingObject;
// Now I will use storingObject to access the setting.

一旦您执行了类似的操作并继续使用 storingObject 而不是直接访问 MyAppSettings 您可以创建一种情况:对象已更改,而 _ChangedSinceLastSerialized 仍为 false

我希望这有帮助。

The issue stems probably from the fact that SerializedValue is a property that is implemented something like that:

public object SerializedValue
{
  get
  {
    if (this._ChangedSinceLastSerialized)
       return CalculateSerializedData();
    else
       return _cachedData;
   }
}

What happens in your case, in my opinion, is that you're getting _cachedData when you first access the SettingPropertyValue, then, by viewing value via the debugger, you cause _ChangedSinceLastSerialized to be true which causes the next call to SerializedValue property to return the actual serialized value.

The next question is to find out why _ChangedSinceLastSerialized in your case is set to false. The logic of SettingsPropertyValue says (you can see it in Reflector in PropertyValue property of the class) that _ChangedSinceLastSerialized is set to true when the user either accesses the settings (in case of most object types), so for example merely accessing your setting like that: MyAppSettings.Default.MySettingObject would change _ChangedSinceLastSerialized to true.

What could happen in your case that you have code similar to this:

object storingObject = MyAppSettings.Default.MySettingObject;
// Now I will use storingObject to access the setting.

Once you do something like that and keep using storingObject instead of directly accessing MyAppSettings you can create a situation in which the object changed while _ChangedSinceLastSerialized remains false.

I hope that was helpful.

温馨耳语 2024-12-23 11:41:44

实际上,我放弃了使用 SettingsPropertyValue 的尝试,并决定手动将对象序列化为 XML。我只是使用 SettingsProperty.Name 作为键来检索存储在 Properties.Settings.Default 中的设置值,因为它是一个类似字典的对象。它解决了这个问题,但当然根本原因仍然未知。修改后的代码看起来像这样:

// Generate parameters
Dictionary<string, string> signalparams = new Dictionary<string, string>();

// Add parameters
foreach (SettingsProperty property in Properties.Settings.Default.Properties)
{
    if (property.SerializeAs == SettingsSerializeAs.String)
    {
        signalparams.Add(property.Name, Properties.Settings.Default[property.Name].ToString());
    }
    else if (property.SerializeAs == SettingsSerializeAs.Xml)
    {
        // Serialize collection into XML manually
        XmlSerializer serializer = new XmlSerializer(Properties.Settings.Default[property.Name].GetType());

        StringBuilder sb = new StringBuilder();
        XmlWriter writer = XmlWriter.Create(sb);

        serializer.Serialize(writer, Properties.Settings.Default[property.Name]);
        writer.Close();

        signalparams.Add(property.Name, sb.ToString());
    }
}

I actually dropped trying to use SettingsPropertyValue and decided to serialize the object to XML manually. I simply used the SettingsProperty.Name as a key to retrieve the values of the settings stored in Properties.Settings.Default, since it is a dictionary-like object. It fixed the issue, but of course the root cause still remains unknown. The revised code looks something like this:

// Generate parameters
Dictionary<string, string> signalparams = new Dictionary<string, string>();

// Add parameters
foreach (SettingsProperty property in Properties.Settings.Default.Properties)
{
    if (property.SerializeAs == SettingsSerializeAs.String)
    {
        signalparams.Add(property.Name, Properties.Settings.Default[property.Name].ToString());
    }
    else if (property.SerializeAs == SettingsSerializeAs.Xml)
    {
        // Serialize collection into XML manually
        XmlSerializer serializer = new XmlSerializer(Properties.Settings.Default[property.Name].GetType());

        StringBuilder sb = new StringBuilder();
        XmlWriter writer = XmlWriter.Create(sb);

        serializer.Serialize(writer, Properties.Settings.Default[property.Name]);
        writer.Close();

        signalparams.Add(property.Name, sb.ToString());
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文