/// <summary> /// Responsible for deciding how to encode/decode a given data-type; maybe /// not the most elegant solution, but it is simple and quick. /// </summary> private static Property <T> CreateProperty <T>(Type type, ref DataFormat format, MemberSerializationOptions options) { if (type.IsEnum) { if (format != DataFormat.Default && Attribute.IsDefined(type, typeof(FlagsAttribute))) { type = Enum.GetUnderlyingType(type); } else { format = DataFormat.TwosComplement; return(PropertyUtil <T> .CreateTypedProperty("CreatePropertyEnum", type)); } } if (type == typeof(int)) { switch (format) { case DataFormat.Default: case DataFormat.TwosComplement: format = DataFormat.TwosComplement; return(new PropertyInt32Variant <T>()); case DataFormat.ZigZag: return(new PropertyInt32ZigZag <T>()); case DataFormat.FixedSize: return(new PropertyInt32Fixed <T>()); } } if (type == typeof(short)) { switch (format) { case DataFormat.Default: case DataFormat.TwosComplement: format = DataFormat.TwosComplement; return(new PropertyInt16Variant <T>()); case DataFormat.ZigZag: return(new PropertyInt16ZigZag <T>()); } } if (type == typeof(long)) { switch (format) { case DataFormat.Default: case DataFormat.TwosComplement: format = DataFormat.TwosComplement; return(new PropertyInt64Variant <T>()); case DataFormat.ZigZag: return(new PropertyInt64ZigZag <T>()); case DataFormat.FixedSize: return(new PropertyInt64Fixed <T>()); } } if (type == typeof(uint)) { switch (format) { case DataFormat.Default: case DataFormat.TwosComplement: format = DataFormat.TwosComplement; return(new PropertyUInt32Variant <T>()); case DataFormat.FixedSize: return(new PropertyUInt32Fixed <T>()); } } if (type == typeof(ulong)) { switch (format) { case DataFormat.Default: case DataFormat.TwosComplement: format = DataFormat.TwosComplement; return(new PropertyUInt64Variant <T>()); case DataFormat.FixedSize: return(new PropertyUInt64Fixed <T>()); } } if (type == typeof(ushort)) { switch (format) { case DataFormat.Default: case DataFormat.TwosComplement: format = DataFormat.TwosComplement; return(new PropertyUInt16Variant <T>()); } } if (type == typeof(byte[])) { format = DataFormat.Default; return(new PropertyBlob <T>()); } if (type == typeof(byte)) { format = DataFormat.TwosComplement; return(new PropertyByte <T>()); } if (type == typeof(sbyte)) { format = DataFormat.ZigZag; return(new PropertySByte <T>()); } if (type == typeof(char)) { format = DataFormat.TwosComplement; return(new PropertyChar <T>()); } if (type == typeof(bool)) { format = DataFormat.TwosComplement; return(new PropertyBoolean <T>()); } if (type == typeof(string)) { format = DataFormat.Default; return(new PropertyString <T>()); } if (type == typeof(float)) { format = DataFormat.FixedSize; return(new PropertySingle <T>()); } if (type == typeof(double)) { format = DataFormat.FixedSize; return(new PropertyDouble <T>()); } if (type == typeof(Uri)) { format = DataFormat.Default; return(new PropertyUri <T>()); } if (type == typeof(Guid)) { switch (format) { case DataFormat.Group: return(new PropertyGuidGroup <T>()); case DataFormat.Default: return(new PropertyGuidString <T>()); } } if (type == typeof(TimeSpan)) { switch (format) { case DataFormat.Group: return(new PropertyTimeSpanGroup <T>()); case DataFormat.Default: return(new PropertyTimeSpanString <T>()); case DataFormat.FixedSize: return(new PropertyTimeSpanFixed <T>()); } } if (type == typeof(DateTime)) { switch (format) { case DataFormat.Group: return(new PropertyDateTimeGroup <T>()); case DataFormat.Default: return(new PropertyDateTimeString <T>()); case DataFormat.FixedSize: return(new PropertyDateTimeFixed <T>()); } } if (type == typeof(decimal)) { switch (format) { case DataFormat.Group: return(new PropertyDecimalGroup <T>()); case DataFormat.Default: return(new PropertyDecimalString <T>()); } } if (Serializer.IsEntityType(type)) { Type baseType = type; while (Serializer.IsEntityType(baseType.BaseType)) { baseType = baseType.BaseType; } switch (format) { case DataFormat.Default: return(PropertyUtil <T> .CreateTypedProperty("CreatePropertyMessageString", type, baseType, baseType)); case DataFormat.Group: return(PropertyUtil <T> .CreateTypedProperty("CreatePropertyMessageGroup", type, baseType, baseType)); } } if (type.IsValueType && type.IsGenericType && type.GetGenericTypeDefinition() == typeof(KeyValuePair <,>)) { return(PropertyUtil <T> .CreateTypedProperty("CreatePropertyPairString", type.GetGenericArguments())); } bool isEnumerableOnly; Type listItemType = GetListType(type, out isEnumerableOnly); if (type.IsArray) { // verify that we can handle it if (type.GetArrayRank() != 1) { throw new NotSupportedException("Only 1-dimensional arrays can be used; consider an array/list of a class-type instead"); } } if (listItemType != null && listItemType != typeof(byte[])) { bool dummy; if (GetListType(listItemType, out dummy) != null) { throw new NotSupportedException("Nested (jagged) arrays/lists are not supported (except for byte[]); consider an array/list of a class-type with an inner array/list instead"); } } if (type == typeof(byte[])) { // want to treat byte[] as a special case listItemType = null; } if (type.IsArray && listItemType != null) // second check is for byte[] { return(PropertyUtil <T> .CreateTypedProperty( (PropertyFactory.HasOption(options, MemberSerializationOptions.Packed) ? "CreatePropertyPackedArray" : "CreatePropertyArray"), listItemType)); } if (listItemType != null) { if (isEnumerableOnly) { if (GetAddMethod(type, listItemType) != null) { return(PropertyUtil <T> .CreateTypedProperty( (PropertyFactory.HasOption(options, MemberSerializationOptions.Packed) ? "CreatePropertyPackedEnumerable" : "CreatePropertyEnumerable"), type, listItemType)); } } else { return(PropertyUtil <T> .CreateTypedProperty( (PropertyFactory.HasOption(options, MemberSerializationOptions.Packed) ? "CreatePropertyPackedList" : "CreatePropertyList"), type, listItemType)); } } Type nullType = Nullable.GetUnderlyingType(type); if (nullType != null) { return(PropertyUtil <T> .CreateTypedProperty("CreatePropertyNullable", nullType)); } if (format == DataFormat.Default && GetParseMethod(type) != null) { return(PropertyUtil <T> .CreateTypedProperty("CreatePropertyParseable", type)); } throw Serializer.ThrowNoEncoder(format, type); }