我正在ApplicationSettings
内存储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());
}
}
字符串设置添加正常,但当它到达StringCollection
时,它(正确)评估该属性具有SerializeAs == SettingsSerializeAs.Xml
。但是,SerializedValue
为空,因此ToString()
会抛出异常。
奇怪的是,在运行调试器时,SerializedValue
为空,直到我尝试在本地窗口中查看value
变量的属性。此时,SerializedValue
包含StringCollection
的正确XML序列化格式,程序继续正常。
为什么会这样?
答案 0 :(得分:2)
问题可能源于SerializedValue
是一个实现类似的属性:
public object SerializedValue
{
get
{
if (this._ChangedSinceLastSerialized)
return CalculateSerializedData();
else
return _cachedData;
}
}
在我看来,在你的情况下,当你第一次访问SettingPropertyValue时,你会得到_cachedData,然后,通过调试器查看value
,你会导致_ChangedSinceLastSerialized
成为true
{1}}导致下一次调用SerializedValue
属性返回实际的序列化值。
接下来的问题是找出案例中_ChangedSinceLastSerialized
设置为false
的原因。 SettingsPropertyValue
的逻辑说(你可以在类的PropertyValue
属性中的Reflector中看到它)当用户访问设置时_ChangedSinceLastSerialized
被设置为true(在大多数对象的情况下)例如,仅仅访问您的设置:MyAppSettings.Default.MySettingObject会将_ChangedSinceLastSerialized
更改为true
。
如果您的代码与此类似,可能会发生什么:
object storingObject = MyAppSettings.Default.MySettingObject;
// Now I will use storingObject to access the setting.
一旦你做了类似的事情并继续使用storingObject
而不是直接访问MyAppSettings
,你就可以创建一种情况,当_ChangedSinceLastSerialized
保持false
时,对象会发生变化。< / p>
我希望这很有帮助。
答案 1 :(得分:0)
我实际上放弃了尝试使用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());
}
}