1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace UnityEngine.Serialization
{
#if !UNITY_WINRT
/// <summary>
/// Serialization support for <see cref="List{T}" /> and <see cref="Dictionary{TKey,TValue}" /> that doesn't rely on reflection
/// of private members in order to be useable under the CoreCLR security model (WebPlayer).
/// </summary>
public class UnitySurrogateSelector : ISurrogateSelector
{
public ISerializationSurrogate GetSurrogate(Type type, StreamingContext context, out ISurrogateSelector selector)
{
if (type.IsGenericType)
{
var genericTypeDefinition = type.GetGenericTypeDefinition();
if (genericTypeDefinition == typeof(List<>))
{
selector = this;
return ListSerializationSurrogate.Default;
}
if (genericTypeDefinition == typeof(Dictionary<,>))
{
selector = this;
var dictSurrogateType = typeof(DictionarySerializationSurrogate<,>).MakeGenericType(type.GetGenericArguments());
return (ISerializationSurrogate) Activator.CreateInstance(dictSurrogateType);
}
}
selector = null;
return null;
}
public void ChainSelector(ISurrogateSelector selector)
{
throw new NotImplementedException();
}
public ISurrogateSelector GetNextSelector()
{
throw new NotImplementedException();
}
}
/// <summary>
/// Serialization support for <see cref="List{T}" /> that doesn't rely on reflection of private members.
/// </summary>
class ListSerializationSurrogate : ISerializationSurrogate
{
public static readonly ISerializationSurrogate Default = new ListSerializationSurrogate();
public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
{
var list = (IList)obj;
info.AddValue("_size", list.Count);
info.AddValue("_items", ArrayFromGenericList(list));
info.AddValue("_version", 0); // required for compatibility with platform deserialization
}
public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
{
var list = (IList)Activator.CreateInstance(obj.GetType());
var size = info.GetInt32("_size");
if (size == 0)
return list;
var items = ((IEnumerable)info.GetValue("_items", typeof(IEnumerable))).GetEnumerator();
for (var i = 0; i < size; ++i)
{
if (!items.MoveNext())
throw new InvalidOperationException();
list.Add(items.Current);
}
return list;
}
private static Array ArrayFromGenericList(IList list)
{
var items = Array.CreateInstance(list.GetType().GetGenericArguments()[0], list.Count);
list.CopyTo(items, 0);
return items;
}
}
/// <summary>
/// Serialization support for <see cref="Dictionary{TKey,TValue}" /> that doesn't rely on non public members.
/// </summary>
class DictionarySerializationSurrogate<TKey, TValue> : ISerializationSurrogate
{
public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
{
var dictionary = ((Dictionary<TKey, TValue>)obj);
dictionary.GetObjectData(info, context);
}
public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
{
var comparer = (IEqualityComparer<TKey>)info.GetValue("Comparer", typeof(IEqualityComparer<TKey>));
var dictionary = new Dictionary<TKey, TValue>(comparer);
if (info.MemberCount > 3) // KeyValuePairs might not be present if the dictionary was empty
{
var keyValuePairs =
(KeyValuePair<TKey, TValue>[]) info.GetValue("KeyValuePairs", typeof(KeyValuePair<TKey, TValue>[]));
if (keyValuePairs != null)
foreach (var kvp in keyValuePairs)
dictionary.Add(kvp.Key, kvp.Value);
}
return dictionary;
}
}
#endif
}
|