2014-07-08 12:58:53 +00:00
|
|
|
|
#if !NO_RUNTIME
|
|
|
|
|
using System;
|
|
|
|
|
#if FEAT_IKVM
|
|
|
|
|
using Type = IKVM.Reflection.Type;
|
|
|
|
|
using IKVM.Reflection;
|
|
|
|
|
#else
|
|
|
|
|
using System.Reflection;
|
2015-04-21 18:27:52 +00:00
|
|
|
|
|
2014-07-08 12:58:53 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
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;
|
2015-04-21 18:27:52 +00:00
|
|
|
|
|
2014-07-08 12:58:53 +00:00
|
|
|
|
internal CallbackSet(MetaType metaType)
|
|
|
|
|
{
|
|
|
|
|
if (metaType == null) throw new ArgumentNullException("metaType");
|
|
|
|
|
this.metaType = metaType;
|
|
|
|
|
}
|
2015-04-21 18:27:52 +00:00
|
|
|
|
|
2014-07-08 12:58:53 +00:00
|
|
|
|
internal MethodInfo this[TypeModel.CallbackType callbackType]
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
switch (callbackType)
|
|
|
|
|
{
|
2015-04-21 18:27:52 +00:00
|
|
|
|
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");
|
2014-07-08 12:58:53 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-04-21 18:27:52 +00:00
|
|
|
|
|
2014-07-08 12:58:53 +00:00
|
|
|
|
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;
|
2015-04-21 18:27:52 +00:00
|
|
|
|
if (paramType == model.MapType(typeof (SerializationContext)))
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
else if (paramType == model.MapType(typeof (System.Type)))
|
|
|
|
|
{
|
|
|
|
|
}
|
2014-07-08 12:58:53 +00:00
|
|
|
|
#if PLAT_BINARYFORMATTER
|
|
|
|
|
else if(paramType == model.MapType(typeof(System.Runtime.Serialization.StreamingContext))) {}
|
|
|
|
|
#endif
|
|
|
|
|
else return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2015-04-21 18:27:52 +00:00
|
|
|
|
|
2014-07-08 12:58:53 +00:00
|
|
|
|
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", "callback");
|
2015-04-21 18:27:52 +00:00
|
|
|
|
if (callback.ReturnType != model.MapType(typeof (void))
|
2014-07-08 12:58:53 +00:00
|
|
|
|
|| !CheckCallbackParameters(model, callback))
|
|
|
|
|
{
|
|
|
|
|
throw CreateInvalidCallbackSignature(callback);
|
|
|
|
|
}
|
|
|
|
|
return callback;
|
|
|
|
|
}
|
2015-04-21 18:27:52 +00:00
|
|
|
|
|
2014-07-08 12:58:53 +00:00
|
|
|
|
internal static Exception CreateInvalidCallbackSignature(MethodInfo method)
|
|
|
|
|
{
|
2015-04-21 18:27:52 +00:00
|
|
|
|
return
|
|
|
|
|
new NotSupportedException("Invalid callback signature in " + method.DeclaringType.FullName + "." +
|
|
|
|
|
method.Name);
|
2014-07-08 12:58:53 +00:00
|
|
|
|
}
|
2015-04-21 18:27:52 +00:00
|
|
|
|
|
2014-07-08 12:58:53 +00:00
|
|
|
|
private MethodInfo beforeSerialize, afterSerialize, beforeDeserialize, afterDeserialize;
|
2015-04-21 18:27:52 +00:00
|
|
|
|
|
2014-07-08 12:58:53 +00:00
|
|
|
|
/// <summary>Called before serializing an instance</summary>
|
|
|
|
|
public MethodInfo BeforeSerialize
|
|
|
|
|
{
|
|
|
|
|
get { return beforeSerialize; }
|
|
|
|
|
set { beforeSerialize = SanityCheckCallback(metaType.Model, value); }
|
|
|
|
|
}
|
2015-04-21 18:27:52 +00:00
|
|
|
|
|
2014-07-08 12:58:53 +00:00
|
|
|
|
/// <summary>Called before deserializing an instance</summary>
|
|
|
|
|
public MethodInfo BeforeDeserialize
|
|
|
|
|
{
|
|
|
|
|
get { return beforeDeserialize; }
|
|
|
|
|
set { beforeDeserialize = SanityCheckCallback(metaType.Model, value); }
|
|
|
|
|
}
|
2015-04-21 18:27:52 +00:00
|
|
|
|
|
2014-07-08 12:58:53 +00:00
|
|
|
|
/// <summary>Called after serializing an instance</summary>
|
|
|
|
|
public MethodInfo AfterSerialize
|
|
|
|
|
{
|
|
|
|
|
get { return afterSerialize; }
|
|
|
|
|
set { afterSerialize = SanityCheckCallback(metaType.Model, value); }
|
|
|
|
|
}
|
2015-04-21 18:27:52 +00:00
|
|
|
|
|
2014-07-08 12:58:53 +00:00
|
|
|
|
/// <summary>Called after deserializing an instance</summary>
|
|
|
|
|
public MethodInfo AfterDeserialize
|
|
|
|
|
{
|
|
|
|
|
get { return afterDeserialize; }
|
|
|
|
|
set { afterDeserialize = SanityCheckCallback(metaType.Model, value); }
|
|
|
|
|
}
|
2015-04-21 18:27:52 +00:00
|
|
|
|
|
2014-07-08 12:58:53 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// True if any callback is set, else False
|
|
|
|
|
/// </summary>
|
|
|
|
|
public bool NonTrivial
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return beforeSerialize != null || beforeDeserialize != null
|
2015-04-21 18:27:52 +00:00
|
|
|
|
|| afterSerialize != null || afterDeserialize != null;
|
2014-07-08 12:58:53 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-04-21 18:27:52 +00:00
|
|
|
|
|
2014-07-08 12:58:53 +00:00
|
|
|
|
#endif
|