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

C# SettingsPropertyValue.SerializedValue为null,除非我通过局部变量查看变量,c#,serialization,application-settings,C#,Serialization,Application Settings,我将C程序中使用的一些常用设置存储在应用程序设置中。大多数设置都是字符串,但其中一个是StringCollection 某些代码中出现空异常,该代码在Properties.settings.default中循环默认设置,并将它们添加到字典中(准备作为参数发送),如下所示 // Generate parameters Dictionary<string, string> signalparams = new Dictionary<string, string>(); //

我将C程序中使用的一些常用设置存储在
应用程序设置
中。大多数设置都是字符串,但其中一个是
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());
    }
}
//生成参数
Dictionary signalparams=新字典();
//添加参数
foreach(Properties.Settings.Default.Properties中的SettingsProperty属性)
{
SettingsPropertyValue值=新的SettingsPropertyValue(属性);
if(value.Property.SerializeAs==SettingsSerializeAs.Xml)
{
//这里是错误发生的地方
添加(value.Name,value.SerializedValue.ToString());
}
else if(value.Property.SerializeAs==SettingsSerializeAs.String)
{
添加(value.Name、value.PropertyValue.ToString());
}
}
字符串设置添加得很好,但是当它到达
StringCollection
时,它(正确地)评估属性是否具有
SerializeAs==SettingsSerializeAs.Xml
。但是,
SerializedValue
为null,因此
ToString()
引发异常

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


为什么会发生这种情况?

问题可能源于这样一个事实,即
SerializedValue
是一个实现如下内容的属性:

public object SerializedValue
{
  get
  {
    if (this._ChangedSinceLastSerialized)
       return CalculateSerializedData();
    else
       return _cachedData;
   }
}
在我看来,在你的情况下,当你第一次访问SettingPropertyValue时,你得到了缓存数据,然后,通过调试器查看
,您将使
\u ChangedSinceLastSerialized
变为
true
,这将导致对
SerializedValue
属性的下一次调用返回实际的序列化值

下一个问题是找出为什么在您的案例中,
\u changedsincelasterialized
设置为
false
SettingsPropertyValue
的逻辑表示(您可以在类的
PropertyValue
属性中的Reflector中看到)
\u changedsInclastSerialized
在用户访问设置时设置为true(对于大多数对象类型),因此,例如,仅像这样访问您的设置:MyAppSettings.Default.MySettingObject将更改
\u将从上次序列化的
更改为
true

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

object storingObject = MyAppSettings.Default.MySettingObject;
// Now I will use storingObject to access the setting.
一旦您执行类似操作并继续使用
storingObject
而不是直接访问
MyAppSettings
,您就可以创建这样一种情况,即对象在
\u ChangedSinceLastSerialized
保持
false
的同时发生更改


我希望这会有所帮助。

我实际上放弃了使用
设置属性值的尝试,决定手动将对象序列化为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());
    }
}
//生成参数
Dictionary signalparams=新字典();
//添加参数
foreach(Properties.Settings.Default.Properties中的SettingsProperty属性)
{
if(property.SerializeAs==SettingsSerializeAs.String)
{
添加(property.Name,Properties.Settings.Default[property.Name].ToString());
}
else if(property.SerializeAs==SettingsSerializeAs.Xml)
{
//手动将集合序列化为XML
XmlSerializer serializer=新的XmlSerializer(Properties.Settings.Default[property.Name].GetType());
StringBuilder sb=新的StringBuilder();
XmlWriter=XmlWriter.Create(sb);
serializer.Serialize(writer、Properties.Settings.Default[property.Name]);
writer.Close();
signalparams.Add(property.Name,sb.ToString());
}
}

感谢您的富有洞察力的回答。就目前而言,我并没有像您所展示的那样从设置中检索对象,我只是尝试检索序列化的值,而不需要事先修改设置。可能是
\u ChangedSinceLastSerialized
默认为
false
,即使对象从未序列化。尽管如此,我还是通过手动序列化对象来解决这个问题。