我在我的Web应用程序中使用自定义会话提供程序,它继承了SessionStateStoreProviderBase并覆盖了方法。用于从会话获取数据的方法具有 SessionStateStoreData 的返回类型。
目前正在使用二进制序列化来序列化和反序列化数据。我想使用 json序列化而不是二进制但不确定如何将会话数据(json序列化后的字符串类型)转换为SessionStateStoreData类型。 SessionStateStoreData类型的构造函数使用SessionStateItemCollection类型对象,该对象可以从 sessionstateitemcollection 的反序列化方法获取,该方法仅将二进制流作为输入。
var ms = _serializedSessionData == null
? new MemoryStream()
: new MemoryStream(_serializedSessionData);
var sessionItems = new SessionStateItemCollection();
if (ms.Length > 0)
{
var reader = new BinaryReader(ms);
sessionItems = SessionStateItemCollection.Deserialize(reader);
}
return new SessionStateStoreData(sessionItems,
SessionStateUtility.GetSessionStaticObjects(context),
_timeout);
我附加了用于二进制反序列化的代码。如何为json序列化对象做同样的事情?
答案 0 :(得分:3)
SessionStateItemCollection
非常接近Dictionary<string, object>
,因此您可以将其序列化。但是,您需要考虑null
密钥的可能性。 null
允许SessionStateItemCollection
密钥,但Dictionary<string, object>
会在空密钥上引发异常。
由于SessionStateItemCollection
中的值是无类型的,因此您还需要一个支持序列化任意类型的类型信息的JSON序列化程序。 Json.NET可以做到这一点。 JavaScriptSerializer
也可以。 DataContractJsonSerializer
可能不,因为您必须提前知道所有可能的类型,并将其作为已知类型传递给constructor。
对于答案的其余部分,我假设您选择了Json.NET。
首先,为序列化定义以下中间类:
public class StringDictionaryWrapper
{
public StringDictionaryWrapper()
{
Items = new Dictionary<string, object>();
}
// Holds the value of the item with a null key, if any.
[JsonProperty(ItemTypeNameHandling = TypeNameHandling.Auto, DefaultValueHandling = DefaultValueHandling.Ignore)]
public object NullItem { get; set; }
[JsonProperty(ItemTypeNameHandling = TypeNameHandling.Auto)]
public Dictionary<string, object> Items { get; set; }
}
然后,要将SessionStateItemCollection
序列化为json字符串,请执行:
var dict = new StringDictionaryWrapper { Items = sessionItems.Keys.OfType<string>().ToDictionary(key => key, key => sessionItems[key]), NullItem = sessionItems[null] };
var json = JsonConvert.SerializeObject(dict, Formatting.Indented);
JSON看起来像:
{ "NullItem": 1123, "Items": { "foo": { "$type": "Question30640792.SomeClass, Tile", "SomeProperty": "foo2" }, "TestClass": { "$type": "Question30640792.TestClass, Tile", "A": 101, "B": 102 } } }
要从json字符串反序列化,请执行:
var sessionItems = new SessionStateItemCollection();
var dict = JsonConvert.DeserializeObject<StringDictionaryWrapper>(json);
if (dict != null && dict.NullItem != null)
sessionItems[null] = dict.NullItem;
if (dict != null && dict.Items != null)
foreach (var pair in dict.Items)
sessionItems[pair.Key] = pair.Value;
请注意,这将同时反序列化所有会话状态项集合,而内置二进制序列化使用on-demand deserialization for performance reasons。因此,您可能会看到性能受损。此外,由于Dictionary<TKey, TValue>
是无序的,因此会话项可能不会按原来的顺序返回。如果这是一个问题,您可能需要为会话项集合创建类似custom proxy wrapper的内容。
最后,在使用TypeNameHandling
时,请注意Newtonsoft docs中的这一注意事项:
当您的应用程序从外部源反序列化JSON时,应谨慎使用TypeNameHandling。使用非None以外的值进行反序列化时,应使用自定义SerializationBinder验证传入类型。
有关可能需要执行此操作的讨论,请参阅 TypeNameHandling caution in Newtonsoft Json 。