110 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C#
		
	
	
			
		
		
	
	
			110 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C#
		
	
	
| #if !NO_RUNTIME
 | |
| using System;
 | |
| using System.Reflection;
 | |
| 
 | |
| namespace ProtoBuf.Meta
 | |
| {
 | |
|     /// <summary>
 | |
|     /// Represents the set of serialization callbacks to be used when serializing/deserializing a type.
 | |
|     /// </summary>
 | |
|     public class CallbackSet
 | |
|     {
 | |
|         private readonly MetaType metaType;
 | |
|         internal CallbackSet(MetaType metaType)
 | |
|         {
 | |
|             this.metaType = metaType ?? throw new ArgumentNullException(nameof(metaType));
 | |
|         }
 | |
| 
 | |
|         internal MethodInfo this[TypeModel.CallbackType callbackType]
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 switch (callbackType)
 | |
|                 {
 | |
|                     case TypeModel.CallbackType.BeforeSerialize: return beforeSerialize;
 | |
|                     case TypeModel.CallbackType.AfterSerialize: return afterSerialize;
 | |
|                     case TypeModel.CallbackType.BeforeDeserialize: return beforeDeserialize;
 | |
|                     case TypeModel.CallbackType.AfterDeserialize: return afterDeserialize;
 | |
|                     default: throw new ArgumentException("Callback type not supported: " + callbackType.ToString(), "callbackType");
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         internal static bool CheckCallbackParameters(TypeModel model, MethodInfo method)
 | |
|         {
 | |
|             ParameterInfo[] args = method.GetParameters();
 | |
|             for (int i = 0; i < args.Length; i++)
 | |
|             {
 | |
|                 Type paramType = args[i].ParameterType;
 | |
|                 if (paramType == model.MapType(typeof(SerializationContext))) { }
 | |
|                 else if (paramType == model.MapType(typeof(System.Type))) { }
 | |
| #if PLAT_BINARYFORMATTER
 | |
|                 else if (paramType == model.MapType(typeof(System.Runtime.Serialization.StreamingContext))) { }
 | |
| #endif
 | |
|                 else return false;
 | |
|             }
 | |
|             return true;
 | |
|         }
 | |
| 
 | |
|         private MethodInfo SanityCheckCallback(TypeModel model, MethodInfo callback)
 | |
|         {
 | |
|             metaType.ThrowIfFrozen();
 | |
|             if (callback == null) return callback; // fine
 | |
|             if (callback.IsStatic) throw new ArgumentException("Callbacks cannot be static", nameof(callback));
 | |
|             if (callback.ReturnType != model.MapType(typeof(void))
 | |
|                 || !CheckCallbackParameters(model, callback))
 | |
|             {
 | |
|                 throw CreateInvalidCallbackSignature(callback);
 | |
|             }
 | |
|             return callback;
 | |
|         }
 | |
| 
 | |
|         internal static Exception CreateInvalidCallbackSignature(MethodInfo method)
 | |
|         {
 | |
|             return new NotSupportedException("Invalid callback signature in " + method.DeclaringType.FullName + "." + method.Name);
 | |
|         }
 | |
| 
 | |
|         private MethodInfo beforeSerialize, afterSerialize, beforeDeserialize, afterDeserialize;
 | |
| 
 | |
|         /// <summary>Called before serializing an instance</summary>
 | |
|         public MethodInfo BeforeSerialize
 | |
|         {
 | |
|             get { return beforeSerialize; }
 | |
|             set { beforeSerialize = SanityCheckCallback(metaType.Model, value); }
 | |
|         }
 | |
| 
 | |
|         /// <summary>Called before deserializing an instance</summary>
 | |
|         public MethodInfo BeforeDeserialize
 | |
|         {
 | |
|             get { return beforeDeserialize; }
 | |
|             set { beforeDeserialize = SanityCheckCallback(metaType.Model, value); }
 | |
|         }
 | |
| 
 | |
|         /// <summary>Called after serializing an instance</summary>
 | |
|         public MethodInfo AfterSerialize
 | |
|         {
 | |
|             get { return afterSerialize; }
 | |
|             set { afterSerialize = SanityCheckCallback(metaType.Model, value); }
 | |
|         }
 | |
| 
 | |
|         /// <summary>Called after deserializing an instance</summary>
 | |
|         public MethodInfo AfterDeserialize
 | |
|         {
 | |
|             get { return afterDeserialize; }
 | |
|             set { afterDeserialize = SanityCheckCallback(metaType.Model, value); }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// True if any callback is set, else False
 | |
|         /// </summary>
 | |
|         public bool NonTrivial
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return beforeSerialize != null || beforeDeserialize != null
 | |
|                     || afterSerialize != null || afterDeserialize != null;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| #endif |