private MessagePackObject CreateTypedMessagePackObject(Type type, object obj, bool first = false)
{
if (first)
{
_nestCount = 0;
}
if (_nestCount > MaxNestCount)
{
throw new InvalidOperationException("nest counter is over the maximum. counter = " + _nestCount);
}
_nestCount++;
using (var d = new DisposeWithAction(() => _nestCount--))
{
if (obj == null)
{
throw new ArgumentException("can't pack a null value. type = " + type.FullName, "type");
}
if (type == typeof(bool)) return new MessagePackObject((bool)obj);
if (type == typeof(byte)) return new MessagePackObject((byte)obj);
if (type == typeof(byte[])) return new MessagePackObject((byte[])obj);
if (type == typeof(double)) return new MessagePackObject((double)obj);
if (type == typeof(float)) return new MessagePackObject((float)obj);
if (type == typeof(int)) return new MessagePackObject((int)obj);
if (type == typeof(long)) return new MessagePackObject((long)obj);
if (type == typeof(sbyte)) return new MessagePackObject((sbyte)obj);
if (type == typeof(short)) return new MessagePackObject((short)obj);
if (type == typeof(string)) return new MessagePackObject((string)obj);
if (type == typeof(uint)) return new MessagePackObject((uint)obj);
if (type == typeof(ulong)) return new MessagePackObject((ulong)obj);
if (type == typeof(ushort)) return new MessagePackObject((ushort)obj);
if (type == typeof(DateTime)) return new MessagePackObject(MessagePackConvert.FromDateTime((DateTime)obj));
if (type == typeof(DateTimeOffset)) return new MessagePackObject(MessagePackConvert.FromDateTimeOffset((DateTimeOffset)obj));
if (type.IsEnum) return new MessagePackObject(obj.ToString());
if (type.IsArray)
{
return new MessagePackObject((obj as object[]).Select(x => CreateTypedMessagePackObject(type.GetElementType(), x)).ToList());
}
if (obj is ExpandoObject || obj is IDictionary<string, object>)
{
var tmp = obj as IDictionary<string, object>;
var dict = tmp.ToDictionary(x => new MessagePackObject(x.Key), x => CreateTypedMessagePackObject(x.Value.GetType(), x.Value));
return new MessagePackObject(new MessagePackObjectDictionary(dict));
}
else if (type.IsValueType)
{
var dict = obj.GetType()
.GetFields(BindingFlags.Public | BindingFlags.Instance)
.ToDictionary(fi => new MessagePackObject(fi.Name), fi => CreateTypedMessagePackObject(fi.FieldType, fi.GetValue(obj)));
return new MessagePackObject(new MessagePackObjectDictionary(dict));
}
else if (type.GetInterfaces().Any(i => i == typeof(System.Collections.IEnumerable)))
{
var list = new List<MessagePackObject>();
foreach (var x in obj as System.Collections.IEnumerable)
{
list.Add(CreateTypedMessagePackObject(x.GetType(), x));
}
return new MessagePackObject(list);
}
else
{
var dict = obj.GetType()
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.ToDictionary(pi => new MessagePackObject(pi.Name), pi => CreateTypedMessagePackObject(pi.PropertyType, pi.GetValue(obj, null)));
return new MessagePackObject(new MessagePackObjectDictionary(dict));
}
}
}