gpt4 book ai didi

.net - 如何在用户设置中存储 HashTable?

转载 作者:行者123 更新时间:2023-12-04 17:05:39 27 4
gpt4 key购买 nike

在 .NET 中,您可以选择一个哈希表作为用户设置的类型。但是,当我以这种方式保存并检索它时,它似乎根本没有保存它。

Hashtable t = new Hashtable();
t.Add(1,"Foo");
t.Add(2,"Bar");
Properties.Settings.Default.Setting = t;
Properties.Settings.Default.Save();

if(Properties.Settings.Default.Setting != null)
foreach (DictionaryEntry entry in Properties.Settings.Default.Setting)
{
MessageBox.Show(entry.Key + " " + entry.Value);
}

当我可以在 Visual Studio 中明确选择该类型时,为什么不在用户设置中对其进行序列化?我会理解是否是未列出的类型(例如字典)的情况,但列出了 Hashtable。我该如何解决这个问题?
这个顺序的简单性和效率对我来说是最重要的。

非常感谢,
凯夫

更新:

@Joao,非常感谢二进制解决方案。我觉得它很有趣,它很干净。将其序列化为二进制文件的一个缺点可能是您无法再手动更改用户设置文件中的任何内容。但我认为无论如何都很少这样做,所以这是一个很好的解决方案。

我正在考虑使用不同的方法在用户范围内创建字符串类型的“XMLSetting”字段,并使用此代码将值作为序列化为哈希表的 XMl 文件进行存储和检索。但我确信这不是最好的方法,除了我在下面做的事情之外,有没有人知道在用户设置中将哈希表/字典序列化为 xml 的更好方法?
if(string.IsNullOrEmpty(Properties.Settings.Default.XMLSetting))
{
Console.WriteLine("Usersettings is empty. Initializing XML file...");
XmlDocument doc = new XmlDocument();
XmlElement hashtable = doc.CreateElement("HashTable");
doc.AppendChild(hashtable);

GenerateValues(doc, hashtable, "1", "Foo");
GenerateValues(doc, hashtable, "2", "Bar");

Properties.Settings.Default.XMLSetting = doc.OuterXml;
Properties.Settings.Default.Save();
}
else
{
Console.WriteLine("Retrieving existing user settings...");
XmlDocument doc = new XmlDocument();
doc.LoadXml(Properties.Settings.Default.XMLSetting);

Hashtable hashtable = new Hashtable();

foreach (XmlNode entry in doc.DocumentElement.ChildNodes)
{
hashtable.Add(int.Parse(entry.FirstChild.InnerText), entry.FirstChild.NextSibling.InnerText);
}

foreach (DictionaryEntry entry in hashtable)
{
Console.WriteLine(entry.Key + " " + entry.Value);
}
}

private static void GenerateValues(XmlDocument doc, XmlElement hashtable, string skey, string svalue)
{
XmlElement entry = doc.CreateElement("entry");
XmlElement key = doc.CreateElement("Key");
XmlElement value = doc.CreateElement("Value");
entry.AppendChild(key);
entry.AppendChild(value);

key.AppendChild(doc.CreateTextNode(skey));
value.AppendChild(doc.CreateTextNode(svalue));

hashtable.AppendChild(entry);
}

最佳答案

Hashtable 不支持序列化到 XML 也不支持序列化到一个简单的字符串。当您使用 Settings.settings 文件和关联的自动生成的类时,这是两个可用的序列化选项。

但是,如果您自己创 build 置类并管理 App.Config 部分,则可以使用二进制序列化来持久化 Hastable。

请参阅以下示例。这是一个包含以下文件的控制台应用程序:

应用配置

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup
name="userSettings"
type="System.Configuration.UserSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section
name="ConsoleApplication1.MyCustomSettings"
type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
allowExeDefinition="MachineToLocalUser"
requirePermission="false" />
</sectionGroup>
</configSections>
<userSettings>
<ConsoleApplication1.MyCustomSettings>
<setting name="MyHashtable" serializeAs="Binary">
<value></value>
</setting>
<setting name="MyBackColor" serializeAs="String">
<value>Silver</value>
</setting>
</ConsoleApplication1.MyCustomSettings>
</userSettings>
</configuration>

手动创建的自定义设置类:
public class MyCustomSettings : ApplicationSettingsBase
{
private static MyCustomSettings defaultInstance = (
(MyCustomSettings)
(ApplicationSettingsBase.Synchronized(new MyCustomSettings())));

public static MyCustomSettings Default
{
get { return defaultInstance; }
}

[UserScopedSettingAttribute()]
[DebuggerNonUserCodeAttribute()]
[DefaultSettingValueAttribute("Silver")]
public Color MyBackColor
{
get { return ((Color)(this["MyBackColor"])); }
set { this["MyBackColor"] = value; }
}

[UserScopedSettingAttribute()]
[DebuggerNonUserCodeAttribute()]
[SettingsSerializeAs(SettingsSerializeAs.Binary)]
public Hashtable MyHashtable
{
get { return ((Hashtable)(this["MyHashtable"])); }
set { this["MyHashtable"] = value; }
}
}

程序.cs
class Program
{
static void Main(string[] args)
{
// For the first time no Hastable will exist.
// Create one with the default values
if (MyCustomSettings.Default.MyHashtable == null)
{
Console.WriteLine("Initializing Hashtable...");

MyCustomSettings.Default.MyHashtable = new Hashtable();

MyCustomSettings.Default.MyHashtable.Add(1, "foo");
MyCustomSettings.Default.MyHashtable.Add(2, "bar");

MyCustomSettings.Default.Save();
}

foreach (DictionaryEntry entry in MyCustomSettings.Default.MyHashtable)
{
Console.WriteLine(entry.Key + ": " + entry.Value);
}

Console.ReadKey();
}
}

更新:
如果您想要数据的人类可读表示,您使用的方法似乎是合理的。尽管如此,您也可以尝试不同的方法,更好地封装转换为字符串 (XML) 和从字符串 (XML) 的逻辑。

这种方法允许您使用 IDE 对 Settings.settings 文件的支持,无需生成自定义设置类或与 App.config 混淆。

你只需要实现一个自定义类来保存你的数据,在我的例子中,我将从一个 StringDictionary 继承这个类,并实现一个 TypeConverter设置系统将用于以字符串格式保存数据。
[TypeConverter(typeof(StringDictionaryTypeConverter))]
public class MyStringDictionary : StringDictionary
{
}

public class StringDictionaryTypeConverter : TypeConverter
{
public override bool CanConvertFrom(
ITypeDescriptorContext context,
Type sourceType)
{
if (sourceType.Equals(typeof(string)))
{
return true;
}

return base.CanConvertFrom(context, sourceType);
}

public override bool CanConvertTo(
ITypeDescriptorContext context,
Type destinationType)
{
if (destinationType.Equals(typeof(string)))
{
return true;
}

return base.CanConvertTo(context, destinationType);
}

public override object ConvertFrom(
ITypeDescriptorContext context,
CultureInfo culture,
object value)
{
if (value is string)
{
MyStringDictionary sd = new MyStringDictionary();

XDocument xs = XDocument.Load(new StringReader(value as string));

foreach (var item in xs.Descendants("entry"))
{
sd.Add(item.Element("key").Value, item.Element("value").Value);
}

return sd;
}

return base.ConvertFrom(context, culture, value);
}

public override object ConvertTo(
ITypeDescriptorContext context,
CultureInfo culture,
object value,
Type destinationType)
{
if (destinationType.Equals(typeof(string)))
{
MyStringDictionary sd = value as MyStringDictionary;

StringBuilder sb = new StringBuilder();

sb.Append("<entries>");
foreach (DictionaryEntry item in sd)
{
sb.AppendFormat(
"<entry><key>{0}</key><value>{1}</value></entry>",
item.Key,
item.Value);
}
sb.Append("</entries>");

return sb.ToString();
}

return base.ConvertTo(context, culture, value, destinationType);
}
}

现在您只需要使用 MyStringDictionary 类作为设置的数据类型。由于 Visual Studio 未在用户设置的可用数据类型中显示用户类,您需要执行一次性解决方法,包括使用 XML 编辑器(右键单击并打开宽度)打开 Settings.settings 文件并手动指定用户设置的类型为 MyStringDictionary 的全名。

希望这可以帮助。

关于.net - 如何在用户设置中存储 HashTable?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1775246/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com