我前面有一个非常抽象问题。
我有一个类型为Dictionary<string, object>
的公共属性的类,该词典的工作是保存自定义用户设置及其值。
对设置没有任何限制,但通常它们类似于:
“亮度”,100
“连接,“ TCP”
因此,当我实例化此类时,其字典属性将由设置名称及其对应的值填充。
问题在于获取值。
因为值可以是整数,字符串等,所以它们以object
的形式存储在字典中,但是我需要将它们作为具体类型进行检索。
虽然我可以使用dict["Brightness"].GetType()
来查找类型或使用模式匹配,但是在找出要使用的方法返回类型时遇到了麻烦。
我认为,也许我可以为每种类型使用单独的“结果”属性,然后根据值的类型将相应的值分配给正确的属性,例如,如果“亮度”为100,则有一个方法测试“亮度”值的类型,并在看到它为int时执行类似的操作
int resultInt;
resultInt = (int)dict["Brightness"];
但是有些东西告诉我这很丑,而且有更好的方法。
此外,这不是线程安全的。
有关该计划目的的其他信息:
该程序的想法是基本上能够存储用于不同系统的大量设置及其值。它们始终处于键-值关系中,键是唯一的,值可以是任何值。它们可以是字符串,整数,浮点数,十进制等。程序的目的是通过某种方式进行用户自定义。
我的意思是-用户输入要存储的设置。他输入的内容将成为程序将使用的可能设置的完整列表。然后,他为自己拥有的每个系统或“设备”输入这些设置的值。因此,例如,他说“我有一台电脑和一部智能手机”。在程序中输入设置“亮度”和“ CPU”。现在,程序知道他配置的所有系统都将具有这两个设置,并且它们可能具有不同的值。
因此用户可以说“我希望智能手机的屏幕亮度为80%”。因此,他输入了与他的智能手机相对应的整数“ 80”作为“亮度”的值。同样,他可以为家用计算机输入其他值。
最底线是我永远都不知道需要存储什么类型。
答案 0 :(得分:4)
已更新:根据评论和您的澄清:如果您事先不知道代码类型,则无法编写代码类型安全的代码。没有用。
因此,您必须继续使用反射或您自己的方式来注册类型元数据(包含有关其类型的一些有用信息的枚举或类)。
您可以使用上文所述的自己的元数据来构建UI,在特定情况下进行数据验证和所需的转换。
古老而又不太相关::如果您知道编译时的类型,则可以使用泛型使其看起来更加精简:
public T GetValueOrDefault<T>(string key)
{
if (this.dictionary.TryGetValue(key, out object o))
{
return (T)(object)o;
}
return default(T);
}
可以肯定的是,您必须检查您的设计是否合理,但是我现在无法根据您的书面文字判断。
答案 1 :(得分:1)
您可以使用格式反序列化器(例如JSON / XML)读取输入并将其反序列化为给定的结构。
在您的情况下,您将定义一个类,其中包含您希望此输入文件提供的特定字段。 (此示例使用的是JSON,但是原理相同,无论符号格式如何)
public class Settings {
public int Brightness { get; set; }
public string Connection { get; set; }
}
然后您将像这样反序列化
var settings = JsonConvert.DeserializeObject<Settings>(fileInput)
解串器知道类型,因为您已经定义了它。 (请注意,不必为要创建的类型而存在每个字段。)
答案 2 :(得分:0)
但是有些东西告诉我这很丑,而且有更好的方法。
我完全同意您的假设。
似乎您实际上对实际类型有一些了解,但是只想在一个地方对这些信息进行反序列化即可。假设这种具有单个数据结构表示完全不相关的东西是一个坏主意,因为最终您会遇到一些奇怪的转换和类型检查解决方案的噩梦。特别是,您可以轻松编写在运行时失败的代码:
var a = (int)dict["Connection"];
相反,您应该具有表示这些信息的静态类型的数据类型。创建一个具有所有这些属性的类,并使用一些序列化程序库,例如Newtonsofts JSON.Net将这些属性反序列化为该数据结构。
class Settings
{
public int Brightness { get; set; }
public string Connection { get; set; }
}
现在,您可以轻松地反序列化您的设置:
var setting = JsonConvert.DeserializeObject<Settings>(myJson)
并且具有完全确定性的行为:
var b = setting.Brightness; // no casting to int neccessary
答案 3 :(得分:-1)
如果您在编译时不知道字典中的类型,可以使用dynamic
标记(重做Patrick的示例):
public dynamic GetValueOrDefault(string key)
{
if (this.dictionary.TryGetValue(key, out object o))
{
return o;
}
return null;
}
用例:
int val;
val = dict.GetValueOrDefault("Brightness");