File: serializationeventscache.cs

package info (click to toggle)
mono 6.8.0.105%2Bdfsg-3.3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,284,512 kB
  • sloc: cs: 11,172,132; xml: 2,850,069; ansic: 671,653; cpp: 122,091; perl: 59,366; javascript: 30,841; asm: 22,168; makefile: 20,093; sh: 15,020; python: 4,827; pascal: 925; sql: 859; sed: 16; php: 1
file content (214 lines) | stat: -rw-r--r-- 8,761 bytes parent folder | download | duplicates (6)
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
// ==++==
// 
//   Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// ==--==
/*============================================================
**
** Class: SerializationEventsCache
**
**
** Purpose: Caches the various serialization events such as On(De)Seriliz(ed)ing
**
**
============================================================*/

namespace System.Runtime.Serialization {

using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Globalization;
using System.Diagnostics.Contracts;

    internal class SerializationEvents
    {
        private List<MethodInfo> m_OnSerializingMethods = null;
        private List<MethodInfo> m_OnSerializedMethods = null;
        private List<MethodInfo> m_OnDeserializingMethods = null;
        private List<MethodInfo> m_OnDeserializedMethods = null;

        private List<MethodInfo> GetMethodsWithAttribute(Type attribute, Type t)
        {
            List<MethodInfo> mi = new List<MethodInfo>();
            Type baseType = t;
            // Traverse the hierarchy to find all methods with the particular attribute
            while (baseType != null && baseType != typeof(Object))
            {
#if !MONO
                RuntimeType rt = (RuntimeType)baseType;
#endif
                // Get all methods which are declared on this type, instance and public or nonpublic
                MethodInfo[] mis = baseType.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
#if _DEBUG                
                bool found = false;
#endif
                foreach(MethodInfo m in mis)
                {
                    // For each method find if attribute is present, the return type is void and the method is not virtual
                    if (m.IsDefined(attribute, false))
                    {
#if _DEBUG
                        Contract.Assert(m.ReturnType == typeof(void) && !m.IsVirtual, "serialization events methods cannot be virtual and need to have void return");
                            
                        ParameterInfo[] paramInfo = m.GetParameters();
                        // Only add it if this method has one parameter of type StreamingContext
                        if (paramInfo.Length == 1 && paramInfo[0].ParameterType == typeof(StreamingContext))
                        {
                            if (found)
                                Contract.Assert(false, "Mutliple methods with same serialization attribute");
#endif                            
                            mi.Add(m);
#if _DEBUG
                            found = true;
                        }
                        else
                            Contract.Assert(false, "Incorrect serialization event signature");
#endif                        
                    }
                }
#if _DEBUG
                found = false;
#endif
                baseType = baseType.BaseType;
            }
            mi.Reverse();  // We should invoke the methods starting from base

            return (mi.Count == 0) ? null : mi;
        }

        internal SerializationEvents(Type t)
        {
            // Initialize all events
            m_OnSerializingMethods = GetMethodsWithAttribute(typeof(OnSerializingAttribute), t);
            m_OnSerializedMethods = GetMethodsWithAttribute(typeof(OnSerializedAttribute), t);
            m_OnDeserializingMethods = GetMethodsWithAttribute(typeof(OnDeserializingAttribute), t);
            m_OnDeserializedMethods = GetMethodsWithAttribute(typeof(OnDeserializedAttribute), t);
        }

        internal bool HasOnSerializingEvents
        {
            get { return m_OnSerializingMethods != null || m_OnSerializedMethods != null; }
        }

        [System.Security.SecuritySafeCritical]
        internal void InvokeOnSerializing(Object obj, StreamingContext context)
        {
            Contract.Assert(obj != null, "object should have been initialized");
            // Invoke all OnSerializingMethods
            if (m_OnSerializingMethods != null)
            {
#if !MONO
                Object[] p = new Object[] {context};
#endif
                SerializationEventHandler handler = null;
                foreach(MethodInfo m in m_OnSerializingMethods)
                {
                    SerializationEventHandler onSerializing =
                        (SerializationEventHandler)Delegate.CreateDelegateNoSecurityCheck((RuntimeType)typeof(SerializationEventHandler), obj, m);
                    handler = (SerializationEventHandler)Delegate.Combine(handler, onSerializing);
                }
                handler(context);
            }
        }

        [System.Security.SecuritySafeCritical]
        internal void InvokeOnDeserializing(Object obj, StreamingContext context)
        {
            Contract.Assert(obj != null, "object should have been initialized");
            // Invoke all OnDeserializingMethods
            if (m_OnDeserializingMethods != null)
            {
#if !MONO
                Object[] p = new Object[] {context};
#endif
                SerializationEventHandler handler = null;
                foreach(MethodInfo m in m_OnDeserializingMethods)
                {
                    SerializationEventHandler onDeserializing =
                        (SerializationEventHandler)Delegate.CreateDelegateNoSecurityCheck((RuntimeType)typeof(SerializationEventHandler), obj, m);
                    handler = (SerializationEventHandler)Delegate.Combine(handler, onDeserializing);
                }
                handler(context);
            }
        }

        [System.Security.SecuritySafeCritical]
        internal void InvokeOnDeserialized(Object obj, StreamingContext context)
        {
            Contract.Assert(obj != null, "object should have been initialized");
            // Invoke all OnDeserializingMethods
            if (m_OnDeserializedMethods != null)
            {
#if !MONO
                Object[] p = new Object[] {context};
#endif
                SerializationEventHandler handler = null;
                foreach(MethodInfo m in m_OnDeserializedMethods)
                {
                    SerializationEventHandler onDeserialized =
                        (SerializationEventHandler)Delegate.CreateDelegateNoSecurityCheck((RuntimeType)typeof(SerializationEventHandler), obj, m);
                    handler = (SerializationEventHandler)Delegate.Combine(handler, onDeserialized);
                }
                handler(context);
            }
        }

        [System.Security.SecurityCritical]
        internal SerializationEventHandler AddOnSerialized(Object obj, SerializationEventHandler handler)
        {
            // Add all OnSerialized methods to a delegate
            if (m_OnSerializedMethods != null)
            {
                foreach(MethodInfo m in m_OnSerializedMethods)
                {
                    SerializationEventHandler onSerialized =
                        (SerializationEventHandler)Delegate.CreateDelegateNoSecurityCheck((RuntimeType)typeof(SerializationEventHandler), obj, m);
                    handler = (SerializationEventHandler)Delegate.Combine(handler, onSerialized);
                }
            }
            return handler;
        }

        [System.Security.SecurityCritical]
        internal SerializationEventHandler AddOnDeserialized(Object obj, SerializationEventHandler handler)
        {
            // Add all OnDeserialized methods to a delegate
            if (m_OnDeserializedMethods != null)
            {
                foreach(MethodInfo m in m_OnDeserializedMethods)
                {
                    SerializationEventHandler onDeserialized =
                        (SerializationEventHandler)Delegate.CreateDelegateNoSecurityCheck((RuntimeType)typeof(SerializationEventHandler), obj, m);
                    handler = (SerializationEventHandler)Delegate.Combine(handler, onDeserialized);
                }
            }
            return handler;
        }
    }

    internal static class SerializationEventsCache
    {
        private static Hashtable cache = new Hashtable();

        internal static SerializationEvents GetSerializationEventsForType(Type t)
        {
            SerializationEvents events;
            if ((events = (SerializationEvents)cache[t]) == null)
            {
                lock(cache.SyncRoot)
                {
                    if ((events = (SerializationEvents)cache[t]) == null)
                    {
                        events = new SerializationEvents(t);
                        cache[t] = events; // Add this to the cache.
                    }
                }
            }
            return events;

        }
    }
}