Survivalcraft API 1.8.2.3 v1.8.2.3
Survivalcraft 2.4
载入中...
搜索中...
未找到
Archive.cs
浏览该文件的文档.
1using System.Reflection;
2using System.Runtime.CompilerServices;
3
5 public class Archive {
6 protected delegate void ReadDelegateGeneric<T>(InputArchive archive, ref T value);
7
8 protected delegate void WriteDelegateGeneric<T>(OutputArchive archive, T value);
9
10 public delegate void ReadDelegate(InputArchive archive, ref object value);
11
12 public delegate void WriteDelegate(OutputArchive archive, object value);
13
14 protected class SerializeData<T> : SerializeData {
15#pragma warning disable CS0649 // 从未对字段赋值,字段将一直保持其默认值
17
19#pragma warning restore CS0649 // 从未对字段赋值,字段将一直保持其默认值
20
21 internal SerializeData() : base(typeof(T)) { }
22 }
23
24 public class SerializeData {
25 public bool IsValueType;
26
27 public Type Type { get; set; }
28
30
32
33 public ConstructorInfo Constructor;
34
36
38
39 public bool UseObjectInfo;
40
42
43 public bool IsSerializable => Read != null;
44
45 public SerializeData(Type type) {
46 Type = type;
47 IsValueType = type.GetTypeInfo().IsValueType;
48 UseObjectInfo = !type.GetTypeInfo().IsValueType && type != typeof(string);
50 }
51
52 public SerializeData(bool useObjectInfo, AutoConstructMode autoConstruct) {
53 UseObjectInfo = useObjectInfo;
54 AutoConstruct = autoConstruct;
55 }
56
57 public void VerifySerializable() {
58 if (!IsSerializable) {
59 throw new InvalidOperationException(
60 $"Type {Type.FullName} is not serializable. Type must have an associated ISerializer<T> or implement ISerializable."
61 );
62 }
63 }
64
65 public void MergeOptionsFrom(SerializeData serializeData) {
66 UseObjectInfo = serializeData.UseObjectInfo;
67 AutoConstruct = serializeData.AutoConstruct;
68 }
69
70 public SerializeData Clone() => (SerializeData)MemberwiseClone();
71
72 public object CreateInstance() {
76 }
77 if (Constructor != null
78 && Constructor.DeclaringType == Type) {
79 return Activator.CreateInstance(Type, true);
80 }
81 object uninitializedObject = RuntimeHelpers.GetUninitializedObject(Type);
82 if (Constructor != null) {
83 Constructor.Invoke(uninitializedObject, null);
84 }
85 return uninitializedObject;
86 }
87
88 public ConstructorInfo FindConstructor(Type type) {
89 ConstructorInfo constructor = type.GetConstructor(
90 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
91 null,
92 Type.EmptyTypes,
93 []
94 );
95 if (constructor == null
96 && type.BaseType != null) {
97 return FindConstructor(type.BaseType);
98 }
99 return constructor;
100 }
101 }
102
103 static HashSet<Assembly> m_scannedAssemblies = [];
104
105 static Dictionary<Type, SerializeData> m_serializeDataByType = [];
106
107 static Dictionary<Type, SerializeData> m_pendingOptionsByType = [];
108
109 static Dictionary<Type, TypeInfo> m_genericSerializersByType = [];
110
111 public object Context;
112
113 public int Version { get; set; }
114
115 public bool UseObjectInfos { get; set; } = true;
116
117 protected Archive(int version, object context) {
118 Version = version;
119 Context = context;
120 }
121
122 protected void Reset(int version, object context) {
123 Version = version;
124 Context = context;
125 }
126
127 public virtual void Dispose() { }
128
129 public static bool IsTypeSerializable(Type type) => GetSerializeData(type, true).Read != null;
130
131 public static void SetTypeSerializationOptions(Type type, bool useObjectInfo, AutoConstructMode autoConstruct) {
132 lock (m_serializeDataByType) {
133 SerializeData serializeData = new(useObjectInfo, autoConstruct);
134 if (m_serializeDataByType.TryGetValue(type, out SerializeData value)) {
135 value.MergeOptionsFrom(serializeData);
136 }
137 else {
138 m_pendingOptionsByType[type] = serializeData;
139 }
140 }
141 }
142
143 public static object CreateInstance(Type type) => GetSerializeData(type, true).CreateInstance();
144
145 /*protected static SerializeData GetSerializeData(Type type, bool allowEmptySerializer)
146 {
147 lock (m_serializeDataByType)
148 {
149 if (!m_serializeDataByType.TryGetValue(type, out SerializeData value))
150 {
151 if (type.GetTypeInfo().ImplementedInterfaces.Contains(typeof(ISerializable)))
152 {
153 value = CreateSerializeDataForSerializable(type);
154 AddSerializeData(value);
155 }
156 else
157 {
158 ScanAssembliesForSerializers();
159 if (!m_serializeDataByType.TryGetValue(type, out value))
160 {
161 if (type.IsArray)
162 {
163 if (m_genericSerializersByType.TryGetValue(typeof(Array), out TypeInfo value2))
164 {
165 value = CreateSerializeDataForSerializer(value2.MakeGenericType(type.GetElementType()).GetTypeInfo(), type, typeof(Array));
166 AddSerializeData(value);
167 }
168 }
169 else if (type.GetTypeInfo().IsGenericType)
170 {
171 Type genericTypeDefinition = type.GetGenericTypeDefinition();
172 if (m_genericSerializersByType.TryGetValue(genericTypeDefinition, out TypeInfo value3))
173 {
174 value = CreateSerializeDataForSerializer(value3.MakeGenericType(type.GenericTypeArguments).GetTypeInfo(), type, type);
175 AddSerializeData(value);
176 }
177 }
178#if ANDROID
179 else if (type.GetTypeInfo().BaseType != null && IsTypeSerializable(type.GetTypeInfo().BaseType))
180 {
181 value = GetSerializeData(type.GetTypeInfo().BaseType, allowEmptySerializer: true).Clone();
182 value.Type = type;
183 value.AutoConstructObject = true;
184 }
185#else
186 else if (type.BaseType != null && IsTypeSerializable(type.BaseType))
187 {
188 value = GetSerializeData(type.BaseType, allowEmptySerializer: true).Clone();
189 value.Type = type;
190 value.AutoConstructObject = true;
191 }
192#endif
193 }
194 if (value == null)
195 {
196 value = CreateEmptySerializeData(type);
197 AddSerializeData(value);
198 }
199 }
200 }
201 return !allowEmptySerializer && value.Read == null
202 ? throw new InvalidOperationException($"ISerializer suitable for type \"{type.FullName}\" not found in any loaded assembly.")
203 : value;
204 }
205 }*/
206 protected static SerializeData GetSerializeData(Type type, bool allowEmptySerializer) {
207 lock (m_serializeDataByType) {
208 if (!m_serializeDataByType.TryGetValue(type, out SerializeData value)) {
210 if (!m_serializeDataByType.TryGetValue(type, out value)) {
211 value = CreateSerializeData(type);
212 AddSerializeData(value);
213 }
214 }
215 if (allowEmptySerializer || value.Read != null) {
216 return value;
217 }
218 throw new InvalidOperationException($"ISerializer suitable for type \"{type.FullName}\" not found in any loaded assembly.");
219 }
220 }
221
223 foreach (Assembly item in TypeCache.LoadedAssemblies.Where(a => !TypeCache.IsKnownSystemAssembly(a))) {
224 if (!m_scannedAssemblies.Contains(item)) {
225 foreach (TypeInfo definedType in item.DefinedTypes) {
226 foreach (Type implementedInterface in definedType.ImplementedInterfaces) {
227 if (implementedInterface.IsConstructedGenericType
228 && implementedInterface.GetGenericTypeDefinition() == typeof(ISerializer<>)) {
229 Type type = implementedInterface.GenericTypeArguments[0];
230 if (type.IsGenericParameter) {
231 continue;
232 }
233 if (!definedType.IsGenericType
234 || !definedType.IsGenericTypeDefinition) {
235 if (!m_serializeDataByType.ContainsKey(type)) {
236 SerializeData serializeData = CreateSerializeDataForSerializer(definedType, type);
237 if (serializeData != null) {
238 AddSerializeData(serializeData);
239 }
240 }
241 }
242 else if (type.GetTypeInfo().BaseType != typeof(Array)
243 && type != typeof(Array)
244 && !type.GetTypeInfo().IsEnum) {
245 m_genericSerializersByType.Add(type.GetGenericTypeDefinition(), definedType);
246 }
247 }
248 }
249 }
250 m_scannedAssemblies.Add(item);
251 }
252 }
253 }
254
256 if (type.GetTypeInfo().ImplementedInterfaces.Contains(typeof(ISerializable))) {
258 }
259 if (type.IsArray) {
260 return CreateSerializeDataForSerializer(typeof(ArraySerializer<>).MakeGenericType(type.GetElementType()).GetTypeInfo(), type);
261 }
262 if (type.GetTypeInfo().IsEnum) {
263 Type enumUnderlyingType = type.GetEnumUnderlyingType();
264 if (enumUnderlyingType == typeof(int)
265 || enumUnderlyingType == typeof(uint)) {
266 return CreateSerializeDataForSerializer(typeof(Enum32Serializer<>).MakeGenericType(type).GetTypeInfo(), type);
267 }
268 if (enumUnderlyingType == typeof(long)
269 || enumUnderlyingType == typeof(ulong)) {
270 return CreateSerializeDataForSerializer(typeof(Enum64Serializer<>).MakeGenericType(type).GetTypeInfo(), type);
271 }
272 throw new InvalidOperationException("Unsupported underlying enum type.");
273 }
274 if (type.GetTypeInfo().IsGenericType) {
275 Type genericTypeDefinition = type.GetGenericTypeDefinition();
276 if (m_genericSerializersByType.TryGetValue(genericTypeDefinition, out TypeInfo value)) {
277 return CreateSerializeDataForSerializer(value.MakeGenericType(type.GenericTypeArguments).GetTypeInfo(), type);
278 }
279 }
280 if (type.GetTypeInfo().BaseType != null
281 && IsTypeSerializable(type.GetTypeInfo().BaseType)) {
282 SerializeData serializeData = GetSerializeData(type.GetTypeInfo().BaseType, true).Clone();
283 serializeData.Type = type;
284 if (serializeData.AutoConstruct == AutoConstructMode.NotSet) {
285 serializeData.AutoConstruct = AutoConstructMode.Yes;
286 }
287 serializeData.ConstructorSearched = false;
288 return serializeData;
289 }
290 return new SerializeData(type);
291 }
292
294 SerializeData obj = (SerializeData)typeof(Archive).GetTypeInfo()
295 .GetDeclaredMethod("CreateSerializeDataForSerializableHelper")
296 .MakeGenericMethod(type)
297 .Invoke(null, []);
298 ApplySerializationOptionsAttribute(obj, type.GetTypeInfo());
299 return obj;
300 }
301
302 static SerializeData CreateSerializeDataForSerializer(TypeInfo serializerType, Type type) {
303 MethodInfo methodInfo = serializerType.AsType()
304 .GetRuntimeMethods()
305 .FirstOrDefault(
306 delegate(MethodInfo m) {
307 if (m.Name != "Serialize") {
308 return false;
309 }
310 ParameterInfo[] parameters2 = m.GetParameters();
311 return parameters2.Length == 2
312 && parameters2[0].ParameterType == typeof(InputArchive)
313 && parameters2[1].ParameterType == type.MakeByRefType();
314 }
315 );
316 MethodInfo methodInfo2 = serializerType.AsType()
317 .GetRuntimeMethods()
318 .FirstOrDefault(
319 delegate(MethodInfo m) {
320 if (m.Name != "Serialize") {
321 return false;
322 }
323 ParameterInfo[] parameters = m.GetParameters();
324 return parameters.Length == 2 && parameters[0].ParameterType == typeof(OutputArchive) && parameters[1].ParameterType == type;
325 }
326 );
327 if (methodInfo != null
328 && methodInfo2 != null) {
329 object obj = Activator.CreateInstance(serializerType.AsType());
330 Type type2 = typeof(ReadDelegateGeneric<>).MakeGenericType(type);
331 Type type3 = typeof(WriteDelegateGeneric<>).MakeGenericType(type);
332 Delegate @delegate = methodInfo.CreateDelegate(type2, obj);
333 Delegate delegate2 = methodInfo2.CreateDelegate(type3, obj);
334 return (SerializeData)typeof(Archive).GetTypeInfo()
335 .GetDeclaredMethod("CreateSerializeDataForSerializerHelper")
336 .MakeGenericMethod(type)
337 .Invoke(null, [@delegate, delegate2]);
338 }
339 throw new InvalidOperationException($"Serialization methods not found in {serializerType.Name}");
340 }
341
343 SerializeData<T> serializeData = new SerializeData<T>();
344 serializeData.ReadGeneric = delegate(InputArchive archive, ref T value) { value.Serialize(archive); };
345 serializeData.WriteGeneric = delegate(OutputArchive archive, T value) { value.Serialize(archive); };
346 if (serializeData.IsValueType) {
347 serializeData.Read = delegate(InputArchive archive, ref object value) {
348 T val = (T)value;
349 val.Serialize(archive);
350 value = val;
351 };
352 }
353 else {
354 serializeData.Read = delegate(InputArchive archive, ref object value) { ((T)value).Serialize(archive); };
355 }
356 serializeData.Write = delegate(OutputArchive archive, object value) { ((T)value).Serialize(archive); };
357 serializeData.AutoConstruct = AutoConstructMode.Yes;
358 return serializeData;
359 }
360
361 private static SerializeData CreateSerializeDataForSerializerHelper<T>(Delegate readDelegate, Delegate writeDelegate) {
362 ReadDelegateGeneric<T> readDelegateGeneric = (ReadDelegateGeneric<T>)readDelegate;
363 WriteDelegateGeneric<T> writeDelegateGeneric = (WriteDelegateGeneric<T>)writeDelegate;
364 return new SerializeData<T> {
365 ReadGeneric = (ReadDelegateGeneric<T>)readDelegate,
366 WriteGeneric = (WriteDelegateGeneric<T>)writeDelegate,
367 Read = delegate(InputArchive archive, ref object value) {
368 T value2 = ((value != null) ? ((T)value) : default(T));
369 readDelegateGeneric(archive, ref value2);
370 value = value2;
371 },
372 Write = delegate(OutputArchive archive, object value) { writeDelegateGeneric(archive, (T)value); }
373 };
374 }
375
376 static void ApplySerializationOptionsAttribute(SerializeData serializeData, TypeInfo attributeTarget) {
377 SerializationOptionsAttribute serializationOptionsAttribute =
378 (SerializationOptionsAttribute)attributeTarget.GetCustomAttribute(typeof(SerializationOptionsAttribute));
379 if (serializationOptionsAttribute != null) {
380 serializeData.UseObjectInfo = serializationOptionsAttribute.UseObjectInfo;
381 serializeData.AutoConstruct = serializationOptionsAttribute.AutoConstruct;
382 }
383 }
384
385 static void AddSerializeData(SerializeData serializeData) {
386 if (m_pendingOptionsByType.TryGetValue(serializeData.Type, out SerializeData value)) {
387 serializeData.MergeOptionsFrom(value);
388 }
389 m_serializeDataByType.Add(serializeData.Type, serializeData);
390 }
391 }
392}
ConstructorInfo FindConstructor(Type type)
void MergeOptionsFrom(SerializeData serializeData)
SerializeData(bool useObjectInfo, AutoConstructMode autoConstruct)
static SerializeData GetSerializeData(Type type, bool allowEmptySerializer)
static Dictionary< Type, SerializeData > m_pendingOptionsByType
static SerializeData CreateSerializeDataForSerializer(TypeInfo serializerType, Type type)
static object CreateInstance(Type type)
delegate void WriteDelegateGeneric< T >(OutputArchive archive, T value)
void Reset(int version, object context)
static SerializeData CreateSerializeDataForSerializableHelper< T >()
static SerializeData CreateSerializeDataForSerializable(Type type)
static HashSet< Assembly > m_scannedAssemblies
delegate void WriteDelegate(OutputArchive archive, object value)
static SerializeData CreateSerializeDataForSerializerHelper< T >(Delegate readDelegate, Delegate writeDelegate)
delegate void ReadDelegate(InputArchive archive, ref object value)
static Dictionary< Type, SerializeData > m_serializeDataByType
static void ApplySerializationOptionsAttribute(SerializeData serializeData, TypeInfo attributeTarget)
static void SetTypeSerializationOptions(Type type, bool useObjectInfo, AutoConstructMode autoConstruct)
static void ScanAssembliesForSerializers()
static void AddSerializeData(SerializeData serializeData)
delegate void ReadDelegateGeneric< T >(InputArchive archive, ref T value)
static SerializeData CreateSerializeData(Type type)
static Dictionary< Type, TypeInfo > m_genericSerializersByType
static bool IsTypeSerializable(Type type)
Archive(int version, object context)
static bool IsKnownSystemAssembly(Assembly assembly)
static ReadOnlyList< Assembly > LoadedAssemblies