The Labs \ Source Viewer \ SSCLI \ System.Runtime.Serialization \ SerializationEvents

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. /*============================================================
  16. **
  17. ** Class: SerializationEventsCache
  18. **
  19. **
  20. ** Purpose: Caches the various serialization events such as On(De)Seriliz(ed)ing
  21. **
  22. **
  23. ============================================================*/
  24. namespace System.Runtime.Serialization
  25. {
  26.    
  27.     using System;
  28.     using System.Collections;
  29.     using System.Collections.Generic;
  30.     using System.Reflection;
  31.     using System.Reflection.Cache;
  32.     using System.Globalization;
  33.    
  34.     internal class SerializationEvents
  35.     {
  36.         private List<MethodInfo> m_OnSerializingMethods = null;
  37.         private List<MethodInfo> m_OnSerializedMethods = null;
  38.         private List<MethodInfo> m_OnDeserializingMethods = null;
  39.         private List<MethodInfo> m_OnDeserializedMethods = null;
  40.        
  41.         private List<MethodInfo> GetMethodsWithAttribute(Type attribute, Type t)
  42.         {
  43.             List<MethodInfo> mi = new List<MethodInfo>();
  44.             Type baseType = t;
  45.             // Traverse the hierarchy to find all methods with the particular attribute
  46.             while (baseType != null && baseType != typeof(object)) {
  47.                 RuntimeType rt = (RuntimeType)baseType;
  48.                 // Get all methods which are declared on this type, instance and public or nonpublic
  49.                 MethodInfo[] mis = baseType.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
  50.                 #if _DEBUG
  51.                 bool found = false;
  52.                 #endif
  53.                 foreach (MethodInfo m in mis) {
  54.                     // For each method find if attribute is present, the return type is void and the method is not virtual
  55.                     if (m.IsDefined(attribute, false)) {
  56.                         #if _DEBUG
  57.                         BCLDebug.Assert(m.ReturnType == typeof(void) && !m.IsVirtual, "serialization events methods cannot be virtual and need to have void return");
  58.                        
  59.                         ParameterInfo[] paramInfo = m.GetParameters();
  60.                         // Only add it if this method has one parameter of type StreamingContext
  61.                         if (paramInfo.Length == 1 && paramInfo[0].ParameterType == typeof(StreamingContext)) {
  62.                             if (found)
  63.                                 BCLDebug.Assert(false, "Mutliple methods with same serialization attribute");
  64.                             #endif
  65.                             mi.Add(m);
  66.                             #if _DEBUG
  67.                             found = true;
  68.                         }
  69.                         else
  70.                             BCLDebug.Assert(false, "Incorrect serialization event signature");
  71.                         #endif
  72.                     }
  73.                 }
  74.                 #if _DEBUG
  75.                 found = false;
  76.                 #endif
  77.                 baseType = baseType.BaseType;
  78.             }
  79.             mi.Reverse();
  80.             // We should invoke the methods starting from base
  81.             return (mi.Count == 0) ? null : mi;
  82.         }
  83.        
  84.         internal SerializationEvents(Type t)
  85.         {
  86.             // Initialize all events
  87.             m_OnSerializingMethods = GetMethodsWithAttribute(typeof(OnSerializingAttribute), t);
  88.             m_OnSerializedMethods = GetMethodsWithAttribute(typeof(OnSerializedAttribute), t);
  89.             m_OnDeserializingMethods = GetMethodsWithAttribute(typeof(OnDeserializingAttribute), t);
  90.             m_OnDeserializedMethods = GetMethodsWithAttribute(typeof(OnDeserializedAttribute), t);
  91.         }
  92.        
  93.         internal bool HasOnSerializingEvents {
  94.             get { return m_OnSerializingMethods != null || m_OnSerializedMethods != null; }
  95.         }
  96.        
  97.         internal void InvokeOnSerializing(object obj, StreamingContext context)
  98.         {
  99.             BCLDebug.Assert(obj != null, "object should have been initialized");
  100.             // Invoke all OnSerializingMethods
  101.             if (m_OnSerializingMethods != null) {
  102.                 object[] p = new object[] {context};
  103.                 SerializationEventHandler handler = null;
  104.                 foreach (MethodInfo m in m_OnSerializingMethods) {
  105.                     SerializationEventHandler onSerializing = (SerializationEventHandler)Delegate.InternalCreateDelegate(typeof(SerializationEventHandler), obj, m);
  106.                     handler = (SerializationEventHandler)Delegate.Combine(handler, onSerializing);
  107.                 }
  108.                 handler(context);
  109.             }
  110.         }
  111.        
  112.         internal void InvokeOnDeserializing(object obj, StreamingContext context)
  113.         {
  114.             BCLDebug.Assert(obj != null, "object should have been initialized");
  115.             // Invoke all OnDeserializingMethods
  116.             if (m_OnDeserializingMethods != null) {
  117.                 object[] p = new object[] {context};
  118.                 SerializationEventHandler handler = null;
  119.                 foreach (MethodInfo m in m_OnDeserializingMethods) {
  120.                     SerializationEventHandler onDeserializing = (SerializationEventHandler)Delegate.InternalCreateDelegate(typeof(SerializationEventHandler), obj, m);
  121.                     handler = (SerializationEventHandler)Delegate.Combine(handler, onDeserializing);
  122.                 }
  123.                 handler(context);
  124.             }
  125.         }
  126.        
  127.         internal void InvokeOnDeserialized(object obj, StreamingContext context)
  128.         {
  129.             BCLDebug.Assert(obj != null, "object should have been initialized");
  130.             // Invoke all OnDeserializingMethods
  131.             if (m_OnDeserializedMethods != null) {
  132.                 object[] p = new object[] {context};
  133.                 SerializationEventHandler handler = null;
  134.                 foreach (MethodInfo m in m_OnDeserializedMethods) {
  135.                     SerializationEventHandler onDeserialized = (SerializationEventHandler)Delegate.InternalCreateDelegate(typeof(SerializationEventHandler), obj, m);
  136.                     handler = (SerializationEventHandler)Delegate.Combine(handler, onDeserialized);
  137.                 }
  138.                 handler(context);
  139.             }
  140.         }
  141.        
  142.         internal SerializationEventHandler AddOnSerialized(object obj, SerializationEventHandler handler)
  143.         {
  144.             // Add all OnSerialized methods to a delegate
  145.             if (m_OnSerializedMethods != null) {
  146.                 foreach (MethodInfo m in m_OnSerializedMethods) {
  147.                     SerializationEventHandler onSerialized = (SerializationEventHandler)Delegate.InternalCreateDelegate(typeof(SerializationEventHandler), obj, m);
  148.                     handler = (SerializationEventHandler)Delegate.Combine(handler, onSerialized);
  149.                 }
  150.             }
  151.             return handler;
  152.         }
  153.        
  154.         internal SerializationEventHandler AddOnDeserialized(object obj, SerializationEventHandler handler)
  155.         {
  156.             // Add all OnDeserialized methods to a delegate
  157.             if (m_OnDeserializedMethods != null) {
  158.                 foreach (MethodInfo m in m_OnDeserializedMethods) {
  159.                     SerializationEventHandler onDeserialized = (SerializationEventHandler)Delegate.InternalCreateDelegate(typeof(SerializationEventHandler), obj, m);
  160.                     handler = (SerializationEventHandler)Delegate.Combine(handler, onDeserialized);
  161.                 }
  162.             }
  163.             return handler;
  164.         }
  165.     }
  166.    
  167.     static internal class SerializationEventsCache
  168.     {
  169.         private static Hashtable cache = new Hashtable();
  170.        
  171.         static internal SerializationEvents GetSerializationEventsForType(Type t)
  172.         {
  173.             SerializationEvents events;
  174.             if ((events = (SerializationEvents)cache[t]) == null) {
  175.                 events = new SerializationEvents(t);
  176.                 cache[t] = events;
  177.                 // Add this to the cache.
  178.             }
  179.             return events;
  180.            
  181.         }
  182.     }
  183. }

Developer Fusion