public static DataType BuildDataType(Type type, Func<Type, MemberInfo, int> membersOrder = null) { if (DataType.IsPrimitiveType(type) || type.IsEnum || type == typeof(Guid) || type.IsKeyValuePair() || type.IsArray || type.IsList() || type.IsDictionary() || type.IsNullable()) return BuildDataType(type, membersOrder, new HashSet<Type>()); List<DataType> slots = new List<DataType>(); foreach (var member in GetPublicMembers(type, membersOrder)) slots.Add(BuildDataType(member.GetPropertyOrFieldType(), membersOrder, new HashSet<Type>())); return DataType.Slots(slots.ToArray()); }
private static bool CheckIfIsImmutable(Type type, List<Type> checkedTypes) { bool result; if (ImmutableCheckedTypes.TryGetValue(type, out result)) { return result; } if (type.IsNullable()) { var underlyingType = Nullable.GetUnderlyingType(type); result = CheckIfIsImmutable(underlyingType, checkedTypes); } else if (type == typeof(bool)) { result = true; } else if (type.IsEnum) { result = true; } else if (type.IsArray) { result = false; } else if (type.IsDelegate()) { result = true; } else if (type.IsImmutableList() || type.IsImmutableArray() || type.IsImmutableHashSet()) { var itemType = type.GetItemType(); result = CheckIfIsImmutable(itemType, checkedTypes); } else if (type.IsKeyValuePair()) { var genericArguments = type.GetGenericArguments(); result = CheckIfIsImmutable(genericArguments[0], checkedTypes) && CheckIfIsImmutable(genericArguments[1], checkedTypes); } else if (CanBeImmutable(type)) { result = HasImmutableMembers(type, checkedTypes); } else { result = false; } ImmutableCheckedTypes.TryAdd(type, result); return result; }
public static bool IsAllPrimitive(Type type, Func<Type, MemberInfo, int> membersOrder = null) { if (DataType.IsPrimitiveType(type)) return true; if (type.IsArray || type.IsList() || type.IsDictionary() || type.IsKeyValuePair() || type.IsNullable() || type == typeof(Guid)) return false; foreach (var member in GetPublicMembers(type, membersOrder)) { if (!DataType.IsPrimitiveType(member.GetPropertyOrFieldType())) return false; } return true; }
private static DataType BuildDataType(Type type, Func<Type, MemberInfo, int> membersOrder, HashSet<Type> cycleCheck) { if (DataType.IsPrimitiveType(type)) return DataType.FromPrimitiveType(type); if (type.IsEnum) return DataType.FromPrimitiveType(type.GetEnumUnderlyingType()); if (type == typeof(Guid)) return DataType.ByteArray; if (type.IsKeyValuePair()) { return DataType.Slots( BuildDataType(type.GetGenericArguments()[0], membersOrder, cycleCheck), BuildDataType(type.GetGenericArguments()[1], membersOrder, cycleCheck)); } if (type.IsArray) return DataType.Array(BuildDataType(type.GetElementType(), membersOrder, cycleCheck)); if (type.IsList()) return DataType.List(BuildDataType(type.GetGenericArguments()[0], membersOrder, cycleCheck)); if (type.IsDictionary()) { return DataType.Dictionary( BuildDataType(type.GetGenericArguments()[0], membersOrder, cycleCheck), BuildDataType(type.GetGenericArguments()[1], membersOrder, cycleCheck)); } if (type.IsNullable()) return DataType.Slots(BuildDataType(type.GetGenericArguments()[0], membersOrder, cycleCheck)); List<DataType> slots = new List<DataType>(); foreach (var member in GetPublicMembers(type, membersOrder)) { var memberType = member.GetPropertyOrFieldType(); if (cycleCheck.Contains(memberType)) throw new NotSupportedException(String.Format("Type {0} has cycle declaration.", memberType)); cycleCheck.Add(memberType); DataType slot = BuildDataType(memberType, membersOrder, cycleCheck); cycleCheck.Remove(memberType); slots.Add(slot); } if (slots.Count == 0) throw new NotSupportedException(String.Format("{0} do not contains public read/writer properties and fields", type)); return DataType.Slots(slots.ToArray()); }
private static bool InternalIsAnonymousType(Type type, Func<Type, MemberInfo, int> membersOrder = null) { if (DataType.IsPrimitiveType(type)) return true; if (type.IsEnum || type == typeof(Guid)) return false; if (type.IsNullable()) return false; if (type.IsKeyValuePair()) return false; if (type.IsArray) return InternalIsAnonymousType(type.GetElementType(), membersOrder); if (type.IsList()) return InternalIsAnonymousType(type.GetGenericArguments()[0], membersOrder); if (type.IsDictionary()) return InternalIsAnonymousType(type.GetGenericArguments()[0], membersOrder) && InternalIsAnonymousType(type.GetGenericArguments()[1], membersOrder); if (type.IsInheritInterface(typeof(ISlots))) { foreach (var slotType in GetPublicMembers(type, membersOrder)) { if (!InternalIsAnonymousType(slotType.GetPropertyOrFieldType(), membersOrder)) return false; } } if ((type.IsClass || type.IsStruct()) && !type.IsInheritInterface(typeof(ISlots))) return false; return true; }
/// <summary> /// Gets the serialization information about the type members. /// This information is used for creation of the corresponding schema nodes. /// </summary> /// <param name="type">The type, members of which should be serialized.</param> /// <returns> /// Serialization information about the fields/properties. /// </returns> /// <exception cref="System.ArgumentNullException">The type argument is null.</exception> public override MemberSerializationInfo[] ResolveMembers(Type type) { if (type == null) { throw new ArgumentNullException("type"); } if (type.IsKeyValuePair()) { var keyValueProperties = type.GetAllProperties(); return keyValueProperties .Select(p => new MemberSerializationInfo { Name = p.Name, MemberInfo = p, Nullable = false }) .ToArray(); } var fields = type.GetAllFields(); var properties = type.GetAllProperties(); var dataMemberProperties = properties .Where(p => p.GetDataMemberAttribute() != null); var serializedProperties = TypeExtensions.RemoveDuplicates(dataMemberProperties); TypeExtensions.CheckPropertyGetters(serializedProperties); var members = fields .Concat<MemberInfo>(serializedProperties) .Select(m => new { Member = m, Attribute = m.GetCustomAttributes(false).OfType<DataMemberAttribute>().SingleOrDefault(), Nullable = m.GetCustomAttributes(false).OfType<NullableSchemaAttribute>().Any() }); var result = members.Where(m => m.Attribute != null) .Select(m => new MemberSerializationInfo { Name = m.Attribute.Name ?? m.Member.Name, MemberInfo = m.Member, Nullable = m.Nullable }); if (this.useAlphabeticalOrder) { result = result.OrderBy(p => p.Name); } return result.ToArray(); }
internal static TypeErrorsBuilder CheckRequiresReferenceHandling( this TypeErrorsBuilder typeErrors, Type type, MemberSettings settings, Func<Type, bool> requiresReferenceHandling) { if (settings.ReferenceHandling == ReferenceHandling.Throw) { if (typeof(IEnumerable).IsAssignableFrom(type)) { if (type.Implements(typeof(IDictionary<,>))) { var arguments = type.GetGenericArguments(); if (arguments.Length != 2 || requiresReferenceHandling(arguments[0]) || requiresReferenceHandling(arguments[1])) { typeErrors = typeErrors.CreateIfNull(type) .Add(RequiresReferenceHandling.Enumerable); } } else if (requiresReferenceHandling(type.GetItemType())) { typeErrors = typeErrors.CreateIfNull(type) .Add(RequiresReferenceHandling.Enumerable); } } else if (type.IsKeyValuePair()) { var arguments = type.GetGenericArguments(); if (requiresReferenceHandling(arguments[0]) || requiresReferenceHandling(arguments[1])) { typeErrors = typeErrors.CreateIfNull(type) .Add(RequiresReferenceHandling.ComplexType); } } else if (requiresReferenceHandling(type)) { typeErrors = typeErrors.CreateIfNull(type) .Add(RequiresReferenceHandling.ComplexType); } } return typeErrors; }