1+ #region copyright
2+ // -----------------------------------------------------------------------
3+ // <copyright file="ExceptionSerializerFactory.cs" company="Akka.NET Team">
4+ // Copyright (C) 2015-2016 AsynkronIT <https://github.com/AsynkronIT>
5+ // Copyright (C) 2016-2016 Akka.NET Team <https://github.com/akkadotnet>
6+ // </copyright>
7+ // -----------------------------------------------------------------------
8+ #endregion
9+
10+ using System ;
11+ using System . Collections ;
12+ using System . Collections . Concurrent ;
13+ using System . Reflection ;
14+ using System . Runtime . Serialization ;
15+ using Hyperion . Extensions ;
16+ using Hyperion . ValueSerializers ;
17+
18+ namespace Hyperion . SerializerFactories
19+ {
20+ internal sealed class AggregateExceptionSerializerFactory : ValueSerializerFactory
21+ {
22+ private static readonly TypeInfo ExceptionTypeInfo = typeof ( Exception ) . GetTypeInfo ( ) ;
23+ private static readonly TypeInfo AggregateExceptionTypeInfo = typeof ( AggregateException ) . GetTypeInfo ( ) ;
24+ private readonly FieldInfo _className ;
25+ private readonly FieldInfo _innerException ;
26+ private readonly FieldInfo _stackTraceString ;
27+ private readonly FieldInfo _remoteStackTraceString ;
28+ private readonly FieldInfo _message ;
29+ private readonly FieldInfo _innerExceptions ;
30+
31+ public AggregateExceptionSerializerFactory ( )
32+ {
33+ _className = ExceptionTypeInfo . GetField ( "_className" , BindingFlagsEx . All ) ;
34+ _innerException = ExceptionTypeInfo . GetField ( "_innerException" , BindingFlagsEx . All ) ;
35+ _message = AggregateExceptionTypeInfo . GetField ( "_message" , BindingFlagsEx . All ) ;
36+ _remoteStackTraceString = ExceptionTypeInfo . GetField ( "_remoteStackTraceString" , BindingFlagsEx . All ) ;
37+ _stackTraceString = ExceptionTypeInfo . GetField ( "_stackTraceString" , BindingFlagsEx . All ) ;
38+ _innerExceptions = AggregateExceptionTypeInfo . GetField ( "m_innerExceptions" , BindingFlagsEx . All ) ;
39+ }
40+
41+ public override bool CanSerialize ( Serializer serializer , Type type ) =>
42+ #if NETSTANDARD16
43+ false ;
44+ #else
45+ AggregateExceptionTypeInfo . IsAssignableFrom ( type . GetTypeInfo ( ) ) ;
46+ #endif
47+
48+ public override bool CanDeserialize ( Serializer serializer , Type type ) => CanSerialize ( serializer , type ) ;
49+
50+ #if NETSTANDARD16
51+ // Workaround for CoreCLR where FormatterServices.GetUninitializedObject is not public
52+ private static readonly Func < Type , object > GetUninitializedObject =
53+ ( Func < Type , object > )
54+ typeof ( string ) . GetTypeInfo ( ) . Assembly . GetType ( "System.Runtime.Serialization.FormatterServices" )
55+ . GetMethod ( "GetUninitializedObject" , BindingFlags . NonPublic | BindingFlags . Public | BindingFlags . Static )
56+ . CreateDelegate ( typeof ( Func < Type , object > ) ) ;
57+ #else
58+ private static readonly Func < Type , object > GetUninitializedObject = System . Runtime . Serialization . FormatterServices . GetUninitializedObject ;
59+ #endif
60+
61+ public override ValueSerializer BuildSerializer ( Serializer serializer , Type type ,
62+ ConcurrentDictionary < Type , ValueSerializer > typeMapping )
63+ {
64+ #if ! NETSTANDARD1_6
65+ var exceptionSerializer = new ObjectSerializer ( type ) ;
66+ exceptionSerializer . Initialize ( ( stream , session ) =>
67+ {
68+ var info = new SerializationInfo ( type , new FormatterConverter ( ) ) ;
69+
70+ info . AddValue ( "ClassName" , stream . ReadString ( session ) , typeof ( string ) ) ;
71+ info . AddValue ( "Message" , stream . ReadString ( session ) , typeof ( string ) ) ;
72+ info . AddValue ( "Data" , stream . ReadObject ( session ) , typeof ( IDictionary ) ) ;
73+ info . AddValue ( "InnerException" , stream . ReadObject ( session ) , typeof ( Exception ) ) ;
74+ info . AddValue ( "HelpURL" , stream . ReadString ( session ) , typeof ( string ) ) ;
75+ info . AddValue ( "StackTraceString" , stream . ReadString ( session ) , typeof ( string ) ) ;
76+ info . AddValue ( "RemoteStackTraceString" , stream . ReadString ( session ) , typeof ( string ) ) ;
77+ info . AddValue ( "RemoteStackIndex" , stream . ReadInt32 ( session ) , typeof ( int ) ) ;
78+ info . AddValue ( "ExceptionMethod" , stream . ReadString ( session ) , typeof ( string ) ) ;
79+ info . AddValue ( "HResult" , stream . ReadInt32 ( session ) ) ;
80+ info . AddValue ( "Source" , stream . ReadString ( session ) , typeof ( string ) ) ;
81+ info . AddValue ( "InnerExceptions" , stream . ReadObject ( session ) , typeof ( Exception [ ] ) ) ;
82+
83+ return Activator . CreateInstance ( type , BindingFlags . NonPublic | BindingFlags . CreateInstance | BindingFlags . Instance , null , new object [ ] { info , new StreamingContext ( ) } , null ) ;
84+ } , ( stream , exception , session ) =>
85+ {
86+ var info = new SerializationInfo ( type , new FormatterConverter ( ) ) ;
87+ var context = new StreamingContext ( ) ;
88+ ( ( AggregateException ) exception ) . GetObjectData ( info , context ) ;
89+
90+ var className = info . GetString ( "ClassName" ) ;
91+ var message = info . GetString ( "Message" ) ;
92+ var data = info . GetValue ( "Data" , typeof ( IDictionary ) ) ;
93+ var innerException = info . GetValue ( "InnerException" , typeof ( Exception ) ) ;
94+ var helpUrl = info . GetString ( "HelpURL" ) ;
95+ var stackTraceString = info . GetString ( "StackTraceString" ) ;
96+ var remoteStackTraceString = info . GetString ( "RemoteStackTraceString" ) ;
97+ var remoteStackIndex = info . GetInt32 ( "RemoteStackIndex" ) ;
98+ var exceptionMethod = info . GetString ( "ExceptionMethod" ) ;
99+ var hResult = info . GetInt32 ( "HResult" ) ;
100+ var source = info . GetString ( "Source" ) ;
101+ var innerExceptions = ( Exception [ ] ) info . GetValue ( "InnerExceptions" , typeof ( Exception [ ] ) ) ;
102+
103+ StringSerializer . WriteValueImpl ( stream , className , session ) ;
104+ StringSerializer . WriteValueImpl ( stream , message , session ) ;
105+ stream . WriteObjectWithManifest ( data , session ) ;
106+ stream . WriteObjectWithManifest ( innerException , session ) ;
107+ StringSerializer . WriteValueImpl ( stream , helpUrl , session ) ;
108+ StringSerializer . WriteValueImpl ( stream , stackTraceString , session ) ;
109+ StringSerializer . WriteValueImpl ( stream , remoteStackTraceString , session ) ;
110+ Int32Serializer . WriteValueImpl ( stream , remoteStackIndex , session ) ;
111+ StringSerializer . WriteValueImpl ( stream , exceptionMethod , session ) ;
112+ Int32Serializer . WriteValueImpl ( stream , hResult , session ) ;
113+ StringSerializer . WriteValueImpl ( stream , source , session ) ;
114+ stream . WriteObjectWithManifest ( innerExceptions , session ) ;
115+ } ) ;
116+ if ( serializer . Options . KnownTypesDict . TryGetValue ( type , out var index ) )
117+ {
118+ var wrapper = new KnownTypeObjectSerializer ( exceptionSerializer , index ) ;
119+ typeMapping . TryAdd ( type , wrapper ) ;
120+ }
121+ else
122+ typeMapping . TryAdd ( type , exceptionSerializer ) ;
123+ return exceptionSerializer ;
124+ #else
125+ return null ;
126+ #endif
127+ }
128+ }
129+ }
0 commit comments