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;
}
}
}
|