2010-04-07 Jb Evain <jbevain@novell.com>
[mcs.git] / class / corlib / System.Runtime.Serialization / SerializationCallbacks.cs
blob49fbb1270a182e59e237c5fd1275166a0575d776
1 //
2 // System.Runtime.Serialization.SerializationCallbacks.cs
3 //
4 // Author:
5 // Robert Jordan (robertj@gmx.net)
6 //
7 // Copyright (C) 2006 Novell, Inc (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 using System;
30 using System.Collections;
31 using System.Reflection;
33 namespace System.Runtime.Serialization {
35 internal sealed class SerializationCallbacks
37 public delegate void CallbackHandler (StreamingContext context);
39 readonly ArrayList onSerializingList;
40 readonly ArrayList onSerializedList;
41 readonly ArrayList onDeserializingList;
42 readonly ArrayList onDeserializedList;
44 public bool HasSerializingCallbacks {
45 get {return onSerializingList != null;}
48 public bool HasSerializedCallbacks {
49 get {return onSerializedList != null;}
52 public bool HasDeserializingCallbacks {
53 get {return onDeserializingList != null;}
56 public bool HasDeserializedCallbacks {
57 get {return onDeserializedList != null;}
60 public SerializationCallbacks (Type type)
62 onSerializingList = GetMethodsByAttribute (type, typeof (OnSerializingAttribute));
63 onSerializedList = GetMethodsByAttribute (type, typeof (OnSerializedAttribute));
64 onDeserializingList = GetMethodsByAttribute (type, typeof (OnDeserializingAttribute));
65 onDeserializedList = GetMethodsByAttribute (type, typeof (OnDeserializedAttribute));
68 const BindingFlags DefaultBindingFlags = BindingFlags.Public | BindingFlags.NonPublic |
69 BindingFlags.Instance | BindingFlags.DeclaredOnly;
72 static ArrayList GetMethodsByAttribute (Type type, Type attr)
74 ArrayList list = new ArrayList ();
76 Type t = type;
77 while (t != typeof (object)) {
78 int count = 0;
80 foreach (MethodInfo mi in t.GetMethods (DefaultBindingFlags)) {
81 if (mi.IsDefined (attr, false)) {
82 list.Add (mi);
83 count++;
87 // FIXME: MS.NET is checking for this with the verifier at assembly load time.
88 if (count > 1)
89 throw new TypeLoadException (
90 String.Format ("Type '{0}' has more than one method with the following attribute: '{1}'.", type.AssemblyQualifiedName, attr.FullName));
92 t = t.BaseType;
95 // optimize memory usage
96 return list.Count == 0 ? null : list;
99 static void Invoke (ArrayList list, object target, StreamingContext context)
101 if (list == null)
102 return;
104 CallbackHandler handler = null;
106 // construct a delegate from the specified list
107 foreach (MethodInfo mi in list) {
108 handler = (CallbackHandler)
109 Delegate.Combine (
110 Delegate.CreateDelegate (typeof (CallbackHandler), target, mi),
111 handler);
114 handler (context);
117 public void RaiseOnSerializing (object target, StreamingContext contex)
119 Invoke (onSerializingList, target, contex);
122 public void RaiseOnSerialized (object target, StreamingContext contex)
124 Invoke (onSerializedList, target, contex);
127 public void RaiseOnDeserializing (object target, StreamingContext contex)
129 Invoke (onDeserializingList, target, contex);
132 public void RaiseOnDeserialized (object target, StreamingContext contex)
134 Invoke (onDeserializedList, target, contex);
137 static Hashtable cache = new Hashtable ();
138 static object cache_lock = new object ();
140 public static SerializationCallbacks GetSerializationCallbacks (Type t)
142 SerializationCallbacks sc = (SerializationCallbacks) cache [t];
143 if (sc != null)
144 return sc;
146 // Slow path, new entry, we need to copy
147 lock (cache_lock){
148 sc = (SerializationCallbacks) cache [t];
149 if (sc == null) {
150 Hashtable copy = (Hashtable) cache.Clone ();
152 sc = new SerializationCallbacks (t);
153 copy [t] = sc;
154 cache = copy;
156 return sc;