/mcs/class/corlib/System.Runtime.Serialization/SerializationCallbacks.cs
C# | 160 lines | 100 code | 29 blank | 31 comment | 15 complexity | 94f40674a274edc5b590c06bfd9e995a MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
- //
- // System.Runtime.Serialization.SerializationCallbacks.cs
- //
- // Author:
- // Robert Jordan (robertj@gmx.net)
- //
- // Copyright (C) 2006 Novell, Inc (http://www.novell.com)
- //
- // Permission is hereby granted, free of charge, to any person obtaining
- // a copy of this software and associated documentation files (the
- // "Software"), to deal in the Software without restriction, including
- // without limitation the rights to use, copy, modify, merge, publish,
- // distribute, sublicense, and/or sell copies of the Software, and to
- // permit persons to whom the Software is furnished to do so, subject to
- // the following conditions:
- //
- // The above copyright notice and this permission notice shall be
- // included in all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- //
- using System;
- using System.Collections;
- using System.Reflection;
-
- namespace System.Runtime.Serialization {
- internal sealed class SerializationCallbacks
- {
- public delegate void CallbackHandler (StreamingContext context);
- readonly ArrayList onSerializingList;
- readonly ArrayList onSerializedList;
- readonly ArrayList onDeserializingList;
- readonly ArrayList onDeserializedList;
- public bool HasSerializingCallbacks {
- get {return onSerializingList != null;}
- }
- public bool HasSerializedCallbacks {
- get {return onSerializedList != null;}
- }
- public bool HasDeserializingCallbacks {
- get {return onDeserializingList != null;}
- }
- public bool HasDeserializedCallbacks {
- get {return onDeserializedList != null;}
- }
- public SerializationCallbacks (Type type)
- {
- onSerializingList = GetMethodsByAttribute (type, typeof (OnSerializingAttribute));
- onSerializedList = GetMethodsByAttribute (type, typeof (OnSerializedAttribute));
- onDeserializingList = GetMethodsByAttribute (type, typeof (OnDeserializingAttribute));
- onDeserializedList = GetMethodsByAttribute (type, typeof (OnDeserializedAttribute));
- }
- const BindingFlags DefaultBindingFlags = BindingFlags.Public | BindingFlags.NonPublic |
- BindingFlags.Instance | BindingFlags.DeclaredOnly;
- static ArrayList GetMethodsByAttribute (Type type, Type attr)
- {
- ArrayList list = new ArrayList ();
- Type t = type;
- while (t != typeof (object)) {
- int count = 0;
- foreach (MethodInfo mi in t.GetMethods (DefaultBindingFlags)) {
- if (mi.IsDefined (attr, false)) {
- list.Add (mi);
- count++;
- }
- }
- // FIXME: MS.NET is checking for this with the verifier at assembly load time.
- if (count > 1)
- throw new TypeLoadException (
- String.Format ("Type '{0}' has more than one method with the following attribute: '{1}'.", type.AssemblyQualifiedName, attr.FullName));
- t = t.BaseType;
- }
- // optimize memory usage
- return list.Count == 0 ? null : list;
- }
- static void Invoke (ArrayList list, object target, StreamingContext context)
- {
- if (list == null)
- return;
- CallbackHandler handler = null;
- // construct a delegate from the specified list
- foreach (MethodInfo mi in list) {
- handler = (CallbackHandler)
- Delegate.Combine (
- Delegate.CreateDelegate (typeof (CallbackHandler), target, mi),
- handler);
- }
- handler (context);
- }
- public void RaiseOnSerializing (object target, StreamingContext contex)
- {
- Invoke (onSerializingList, target, contex);
- }
- public void RaiseOnSerialized (object target, StreamingContext contex)
- {
- Invoke (onSerializedList, target, contex);
- }
- public void RaiseOnDeserializing (object target, StreamingContext contex)
- {
- Invoke (onDeserializingList, target, contex);
- }
- public void RaiseOnDeserialized (object target, StreamingContext contex)
- {
- Invoke (onDeserializedList, target, contex);
- }
- static Hashtable cache = new Hashtable ();
- static object cache_lock = new object ();
-
- public static SerializationCallbacks GetSerializationCallbacks (Type t)
- {
- SerializationCallbacks sc = (SerializationCallbacks) cache [t];
- if (sc != null)
- return sc;
- // Slow path, new entry, we need to copy
- lock (cache_lock){
- sc = (SerializationCallbacks) cache [t];
- if (sc == null) {
- Hashtable copy = (Hashtable) cache.Clone ();
-
- sc = new SerializationCallbacks (t);
- copy [t] = sc;
- cache = copy;
- }
- return sc;
- }
- }
- }
- }