/// <summary> /// Converts the input dictionary into a dictionary of key to serialized string values /// </summary> /// <param name="sessionItems">A dictionary some or all of the Session's keys and values</param> /// <returns>The serialized version of the input dictionary members</returns> public virtual KeyValuePair <RedisValue, RedisValue>[] Serialize( List <KeyValuePair <string, object> > sessionItems) { KeyValuePair <RedisValue, RedisValue>[] serializedItems = new KeyValuePair <RedisValue, RedisValue> [sessionItems.Count]; for (int i = 0; i < sessionItems.Count; i++) { try { serializedItems[i] = new KeyValuePair <RedisValue, RedisValue>( sessionItems[i].Key, this.SerializeOne( sessionItems[i].Key, sessionItems[i].Value)); } catch (Exception e) { if (RedisSerializationConfig.SerializerExceptionLoggingDel != null) { RedisSerializationConfig.SerializerExceptionLoggingDel(e); } } } return(serializedItems); }
/// <summary> /// Deserializes the entire input of JSON-serialized values into a list of key-object pairs. This /// method is not normally used in RedisSessionProvider, here only for debugging purposes. /// </summary> /// <param name="redisHashDataRaw">A dictionary of Redis Hash contents, with key being Redis key /// corresponding to Session property and value being a JSON encoded string with type info /// of the original object</param> /// <returns>A list of key-object pairs of each entry in the input dictionary</returns> public virtual List <KeyValuePair <string, object> > Deserialize(KeyValuePair <RedisValue, RedisValue>[] redisHashDataRaw) { // process: for each key and value in raw data, convert byte[] field to json string and extract its type property // then deserialize that type and add List <KeyValuePair <string, object> > deserializedList = new List <KeyValuePair <string, object> >(); if (redisHashDataRaw != null) { foreach (var keyFieldPair in redisHashDataRaw) { try { object deserializedObj = this.DeserializeOne(keyFieldPair.Value.ToString()); if (deserializedObj != null) { deserializedList.Add(new KeyValuePair <string, object>( keyFieldPair.Key.ToString(), deserializedObj)); } } catch (Exception e) { if (RedisSerializationConfig.SerializerExceptionLoggingDel != null) { RedisSerializationConfig.SerializerExceptionLoggingDel(e); } } } } return(deserializedList); }
/// <summary> /// If the key has been deserialized already, return the current object value we have on hand /// for it. If it has not, then deserialize it from initial Redis input and add it to the base /// collection. /// </summary> /// <param name="key">The desired Session key name</param> /// <returns>The deserialized object at the key, or null if it does not exist.</returns> protected object MemoizedDeserializeGet(string key) { object storedObj = null; if (this.Items.TryGetValue(key, out storedObj)) { if (storedObj is NotYetDeserializedPlaceholderValue) { string serializedData; if (this.SerializedRawData.TryGetValue(key, out serializedData)) { try { var placeholderReference = storedObj; storedObj = this.cereal.DeserializeOne(serializedData); // if we can't deserialize, storedObj will still be the placeholder and in that case it's // as if the DeserializeOne method error'ed, so mark it as failed to deserialize if (storedObj is NotYetDeserializedPlaceholderValue) { storedObj = null; } // Try to update the key to the deserialized object. If it fails, check to make sure that its // not because it was already deserialized in another thread if (!this.Items.TryUpdate(key, storedObj, placeholderReference)) { // the update failed, this could be because the comparison value was different for the // concurrentDictionary, so lets try fetching the value again if (this.Items.TryGetValue(key, out storedObj)) { // if it is not a placeholder, return the re-fetched object from the Items collection if (!(storedObj is NotYetDeserializedPlaceholderValue)) { return(storedObj); } } } } catch (Exception e) { if (RedisSerializationConfig.SerializerExceptionLoggingDel != null) { RedisSerializationConfig.SerializerExceptionLoggingDel(e); } storedObj = null; } } } } return(storedObj); }
/// <summary> /// Deserializes a string containing type and object information back into the original object /// </summary> /// <param name="objRaw">A string containing type info and JSON object data</param> /// <returns>The original object</returns> public virtual object DeserializeOne(string objRaw) { Match fieldTypeMatch = this.typeInfoReg.Match(objRaw); if (fieldTypeMatch.Success) { // if we are deserializing a datatable, use this if (fieldTypeMatch.Groups[1].Value == DataTableTypeSerialized) { DataSet desDtWrapper = new DataSet(); using (StringReader rdr = new StringReader(objRaw.Substring(fieldTypeMatch.Length))) { desDtWrapper.ReadXml(rdr); } return(desDtWrapper.Tables[0]); } // or if we are doing a dataset else if (fieldTypeMatch.Groups[1].Value == DataSetTypeSerialized) { DataSet dsOut = new DataSet(); using (StringReader rdr = new StringReader(objRaw.Substring(fieldTypeMatch.Length))) { dsOut.ReadXml(rdr); } return(dsOut); } // or for most things that are sane, use this else { string typeInfoString = fieldTypeMatch.Groups[1].Value; Type typeData; if (this.TypeInfoShortcutsDsrlz.ContainsKey(typeInfoString)) { typeData = this.TypeInfoShortcutsDsrlz[typeInfoString]; } else if (RedisJSONSerializer.TypeCache.TryGetValue(typeInfoString, out typeData)) { // great, we have it in cache } else { typeData = JsonConvert.DeserializeObject <Type>(typeInfoString); #region tryCacheTypeInfo try { // we should cache it for future use TypeCache.AddOrUpdate( typeInfoString, typeData, (str, existing) => typeData); // replace with our type data if already exists } catch (Exception cacheExc) { RedisSerializationConfig.SerializerExceptionLoggingDel( new TypeCacheException( string.Format( "Unable to cache type info for raw value '{0}' during deserialization", objRaw), cacheExc)); } #endregion } return(JsonConvert.DeserializeObject( objRaw.Substring(fieldTypeMatch.Length), typeData)); } } else { return(null); } }