【问题标题】:Reversing the save method in the Open method反转 Open 方法中的保存方法
【发布时间】:2012-06-12 13:25:50
【问题描述】:

对编程相当陌生。我只是想不通如何让它反向工作。我有一个保存方法和一个打开方法。 保存:

IDictionary<string, IDictionary<string, object>> pluginStates = new Dictionary<string, IDictionary<string, object>>();
signaller.RaiseSaveRequest(pluginStates); <--goes out and gets packed plugins

//loop through plugins to get values and types
//holds all of the plugin arrays
Dictionary<string, object> dictProjectState = new Dictionary<string, object>();

foreach (KeyValuePair<string,IDictionary<string,object>> plugin in pluginStates)
{ 
    //holds jsonRepresented values
    Dictionary<string, object> dictJsonRep = new Dictionary<string, object>(); 
    //holds object types
    Dictionary<string, object> dictObjRep = new Dictionary<string, object>(); 
    object[] arrayDictHolder = new object[2];  //holds all of the dictionaries
    string pluginKey = plugin.Key;
    IDictionary<string, object> pluginValue = new Dictionary<string, object>(); 
    pluginValue = plugin.Value;

    foreach (KeyValuePair<string, object> element in pluginValue)
    {
        string jsonRepresentation = JsonConvert.SerializeObject(element);
        object objType = element.Value.GetType().ToString();
        dictJsonRep.Add(element.Key, jsonRepresentation);
        dictObjRep.Add(element.Key, objType);
    }
    arrayDictHolder[0] = dictJsonRep;
    arrayDictHolder[1] = dictObjRep;
    dictProjectState.Add(pluginKey, arrayDictHolder);
}

JsonSerializer serializer = new JsonSerializer();
using (StreamWriter sw = new StreamWriter(strPathName))
using (JsonWriter writer = new JsonTextWriter(sw))
{
     serializer.Serialize(writer, dictProjectState);
}

因此,当有人保存时,事件处理程序会发出并获取每个插件的 packedState,并将其添加到字典 pluginStates。然后,我遍历 pluginStates 中的每个插件,将值的键和 json 字符串版本添加到 1 个字典,将键、对象类型添加到另一个字典,将这两个字典添加到数组中,然后打包一个包含pluginKey 和每个插件的数组。推理:在反序列化时,我遇到了从 JArray 到类型 DataTable 以及字典中的其他类型的问题,这些类型在打开时被传递回插件以解压。我试图弄清楚如何扭转这一点,以便当用户打开项目时,我有 dictProjectState 并且需要通过代码将它一直带回以最终得到 1 个包含插件的字典。我如何在公开场合镜像这个保存? 谢谢!

【问题讨论】:

  • 请注意:您不应该将pluginValue 初始化为新字典,因为您将在下一行将其分配给plugin.Value。您可以将这两行合并为一行:IDictionary&lt;string, object&gt; pluginValue = plugin.Value;

标签: c# arrays serialization dictionary json.net


【解决方案1】:

我相信当你在 open 函数中反序列化时,你应该得到一个可以强制转换为 Dictionary&lt;string, object&gt; 的对象。

这个字典的键是你最终字典中插件的名称(yoru save 方法中的pluginKey)。这些值应该是object[] arrayDictHolder 对象。您可以将它们转换为 object[],然后获取其中的两个值(保存函数中的 dictJsonRep 和 dictObjRep)。

一旦这些值都被转换为Dictionary&lt;string, object&gt;(),您可以遍历其中一个中的 KeyValuePairs,并使用这些对中的键来获取另一个字典中的值存储。

代码将类似于以下内容:

var pluginStates = new Dictionary<string, IDictionary<string, object>>();

var dictProjectState = jsonSerializer.Deserialize(reader) as Dictionary<string, object>;

foreach(var projectStatePair in dictProjectState)
{
    string pluginKey = projectStatePair.Key;
    var pluginValues = new Dictionary<string, object>();
    object[] arrayDictHolder = projectStatePair.Value as object[];
    var dictJsonRep = arrayDictHolder[0] as Dictionary<string, object>;
    var dictObjRep =  arrayDictHolder[1] as Dictionary<string, object>;
    foreach(var JsonRepPair in dictJsonRep)
    {
        string jsonRepresentation = JsonRepPair.Value;
        // We know both dictionaries have the same keys, so
        // get the objType for this JsonRepresentation
        object objType = dictObjRep[JsonRepPair.Key];
        // Since you're serializing objType to a string, you'll need
        // to get the actual Type before calling DeserializeObject.
        Type jsonType = System.Type.GetType(objType as string);
        object value = JsonConvert.DeserializeObject( jsonRepresentation, jsonType );
        pluginValues.Add( JsonRepPair.Key );
    }
    pluginStates.Add( pluginKey, pluginValues );
}

注意:您当前在保存功能中将 objType 设置为 element.Value.GetType().ToString();。您需要更新 save() 以将其设置为 element.Value.GetType(); 或在尝试反序列化之前将类型字符串转换回实际类型。

注意:我对 Json 库不是很熟悉。上面的代码专注于从反序列化的结果中创建你的 pluginStates 字典。您将需要处理 JsonSerializer 的创建,并确保在反序列化它们后关闭所有流。您可能还需要调整实际的反序列化调用以获得所需的结果。

更新:添加了 objType 到实际 System.Type 对象的转换。

【讨论】:

  • 非常感谢!没有意识到我可以添加一个数组 [i] 作为字典..太棒了!我收到 nullReference 错误。 Object[] arrayDictHolder 在将 projectStatePair.Values as object[] 放入其中后为空。将鼠标悬停在右侧的值上时显示该值,但左侧为空。想知道它是否因为值是: {[ {"Project Name":"{\"Key\":\"ProjectName\",\"Value\":\"test1.vbpx\"}" }, { "ProjectName" : "System.String" }]} 由于 json。也许需要对 projectStatePair 做些什么来去除多余的字符??
  • Json 绝对有可能将事物序列化为不同的类型。您可能希望更改原始字典以实际保存强类型,而不是对象(例如将 pluginValue 更改为 Dictionary&lt;string, object[]&gt; 类型。
  • 所以,我已经进入了 dictJsonRep 的循环。我有:'foreach(dictJsonRep 中的 var 对){string strVariableKey = pair.Key;对象 jsonRepr = pair.Value;对象 objType = dictObjRep[pair.Key];对象变量值 = pluginValues.Add(strVariableKey, objType); } pluginStates.Add(pluginKey, pluginValues);'我想让 variableValue = jsonRep 的类型设置为 objType.?
  • 当你在保存功能时,你还在调用object objType = element.Value.GetType().ToString();吗?如果是这样,您可能希望放弃对 ToString() 的调用,或将 objType 设置为 System.Type.GetType(dictObjRep[pair.Key])。然后确保在反序列化时将其转换回类型。
  • objType = dictObjRep[pair.Key];包含当前的系统类型。我确实删除了保存中的 ToString() 。如何在循环中将 jsonRepr 对象转换为 objType 类型?将 jsonRepr 中的值设置为当前为 int objType 的类型。我不能使用 objType 作为类型,因为它是一个变量,所以我不知道如何在循环中进行强制转换。
猜你喜欢
  • 2011-02-24
  • 2021-12-18
  • 2011-06-25
  • 2020-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多