/// <summary> /// Determines whether the type should be handled. /// </summary> /// <param name="type">The type.</param> /// <param name="serializerTypeInfo">The serializer type info.</param> /// <returns><c>true</c> if the type should be handled; otherwise, <c>false</c>.</returns> protected virtual bool ShouldTypeBeIgnored(Type type, XmlSerializerTypeInfo serializerTypeInfo) { if (type == null) { return(true); } // Note, although resharper says this isn't possible, it might be var fullName = type.GetSafeFullName(); if (string.IsNullOrWhiteSpace(fullName)) { serializerTypeInfo.AddTypeAsHandled(type); return(true); } // Ignore non-generic .NET if (!type.IsGenericTypeEx() && type.GetSafeFullName().StartsWith("System.")) { // Log.Debug("Non-generic .NET system type, can be ignored"); serializerTypeInfo.AddTypeAsHandled(type); return(true); } if (type.IsCOMObjectEx()) { serializerTypeInfo.AddTypeAsHandled(type); return(true); } return(serializerTypeInfo.ContainsKnownType(type) || serializerTypeInfo.IsTypeAlreadyHandled(type) || serializerTypeInfo.IsCollectionAlreadyHandled(type)); }
private void AddTypeMembers(Type type, XmlSerializerTypeInfo serializerTypeInfo) { var typesToCheck = new List <Type>(); var isModelBase = (type == typeof(ModelBase)) || typeof(ModelBase).IsAssignableFromEx(type); if (isModelBase) { // No need to check members, they will be serialized by ModelBase //var catelTypeInfo = PropertyDataManager.Default.GetCatelTypeInfo(type); //var modelBaseProperties = catelTypeInfo.GetCatelProperties(); //foreach (var modelBaseProperty in modelBaseProperties) //{ // typesToCheck.Add(modelBaseProperty.Value.Type); //} } else { bool allowNonPublicReflection = AllowNonPublicReflection(type); // Fields var fields = type.GetFieldsEx(BindingFlagsHelper.GetFinalBindingFlags(false, false, allowNonPublicReflection)); foreach (var field in fields) { typesToCheck.Add(field.FieldType); } // Properties var properties = type.GetPropertiesEx(BindingFlagsHelper.GetFinalBindingFlags(false, false, allowNonPublicReflection)); foreach (var property in properties) { typesToCheck.Add(property.PropertyType); } } foreach (var typeToCheck in typesToCheck) { if (serializerTypeInfo.IsTypeAlreadyHandled(typeToCheck)) { continue; } if (!IsTypeSerializable(typeToCheck, serializerTypeInfo)) { serializerTypeInfo.AddTypeAsHandled(typeToCheck); continue; } var propertyTypeFullName = typeToCheck.GetSafeFullName(); if (propertyTypeFullName == null) { serializerTypeInfo.AddTypeAsHandled(typeToCheck); continue; } GetKnownTypes(typeToCheck, serializerTypeInfo); } }
private void AddTypeMembers(Type type, XmlSerializerTypeInfo serializerTypeInfo) { var isModelBase = (type == typeof(ModelBase)) || typeof(ModelBase).IsAssignableFromEx(type); if (isModelBase) { var catelTypeInfo = PropertyDataManager.Default.GetCatelTypeInfo(type); var modelBaseProperties = catelTypeInfo.GetCatelProperties(); foreach (var modelBaseProperty in modelBaseProperties) { var propertyType = modelBaseProperty.Value.Type; if (propertyType.FullName != null) { GetKnownTypes(propertyType, serializerTypeInfo); } else { serializerTypeInfo.AddTypeAsHandled(propertyType); } } } else { bool allowNonPublicReflection = AllowNonPublicReflection(type); // Fields var fields = type.GetFieldsEx(BindingFlagsHelper.GetFinalBindingFlags(false, false, allowNonPublicReflection)); foreach (var field in fields) { var fieldType = field.FieldType; if (fieldType.FullName != null) { GetKnownTypes(fieldType, serializerTypeInfo); } else { serializerTypeInfo.AddTypeAsHandled(fieldType); } } // Properties var properties = type.GetPropertiesEx(BindingFlagsHelper.GetFinalBindingFlags(false, false, allowNonPublicReflection)); foreach (var property in properties) { var propertyType = property.PropertyType; if (propertyType.FullName != null) { GetKnownTypes(propertyType, serializerTypeInfo); } else { serializerTypeInfo.AddTypeAsHandled(propertyType); } } } }
/// <summary> /// Determines whether the type should be handled. /// </summary> /// <param name="type">The type.</param> /// <param name="serializerTypeInfo">The serializer type info.</param> /// <returns><c>true</c> if the type should be handled; otherwise, <c>false</c>.</returns> protected virtual bool ShouldTypeBeIgnored(Type type, XmlSerializerTypeInfo serializerTypeInfo) { if (type == null) { return(true); } // Never include generic type definitions, otherwise we will get this: // Error while getting known types for Type 'Catel.Tests.Data.PropertyDataManagerFacts+SupportsGenericClasses+GenericClass`1[T]'. The type must not be an open or partial generic class. if (type.IsGenericTypeDefinitionEx()) { return(true); } // Note, although resharper says this isn't possible, it might be var fullName = type.GetSafeFullName(false); if (string.IsNullOrWhiteSpace(fullName)) { serializerTypeInfo.AddTypeAsHandled(type); return(true); } // Ignore non-generic .NET if (!type.IsGenericTypeEx() && fullName.StartsWith("System.")) { // Log.Debug("Non-generic .NET system type, can be ignored"); serializerTypeInfo.AddTypeAsHandled(type); return(true); } if (type.IsCOMObjectEx()) { serializerTypeInfo.AddTypeAsHandled(type); return(true); } return(serializerTypeInfo.ContainsKnownType(type) || serializerTypeInfo.IsTypeAlreadyHandled(type) || serializerTypeInfo.IsCollectionAlreadyHandled(type)); }
/// <summary> /// Determines whether the type should be handled. /// </summary> /// <param name="type">The type.</param> /// <param name="serializerTypeInfo">The serializer type info.</param> /// <returns><c>true</c> if the type should be handled; otherwise, <c>false</c>.</returns> protected virtual bool ShouldTypeBeIgnored(Type type, XmlSerializerTypeInfo serializerTypeInfo) { if (type == null) { return true; } // Never include generic type definitions, otherwise we will get this: // Error while getting known types for Type 'Catel.Test.Data.PropertyDataManagerFacts+SupportsGenericClasses+GenericClass`1[T]'. The type must not be an open or partial generic class. if (type.IsGenericTypeDefinitionEx()) { return true; } // Note, although resharper says this isn't possible, it might be var fullName = type.GetSafeFullName(); if (string.IsNullOrWhiteSpace(fullName)) { serializerTypeInfo.AddTypeAsHandled(type); return true; } // Ignore non-generic .NET if (!type.IsGenericTypeEx() && fullName.StartsWith("System.")) { // Log.Debug("Non-generic .NET system type, can be ignored"); serializerTypeInfo.AddTypeAsHandled(type); return true; } if (type.IsCOMObjectEx()) { serializerTypeInfo.AddTypeAsHandled(type); return true; } return serializerTypeInfo.ContainsKnownType(type) || serializerTypeInfo.IsTypeAlreadyHandled(type) || serializerTypeInfo.IsCollectionAlreadyHandled(type); }
private void AddTypeMembers(Type type, XmlSerializerTypeInfo serializerTypeInfo) { var typesToCheck = new List<Type>(); var isModelBase = type.IsModelBase(); if (isModelBase) { // No need to check members, they will be serialized by ModelBase //var catelTypeInfo = PropertyDataManager.Default.GetCatelTypeInfo(type); //var modelBaseProperties = catelTypeInfo.GetCatelProperties(); //foreach (var modelBaseProperty in modelBaseProperties) //{ // typesToCheck.Add(modelBaseProperty.Value.Type); //} } else { var allowNonPublicReflection = AllowNonPublicReflection(type); // Fields var fields = type.GetFieldsEx(BindingFlagsHelper.GetFinalBindingFlags(false, false, allowNonPublicReflection)); foreach (var field in fields) { typesToCheck.Add(field.FieldType); } // Properties var properties = type.GetPropertiesEx(BindingFlagsHelper.GetFinalBindingFlags(false, false, allowNonPublicReflection)); foreach (var property in properties) { typesToCheck.Add(property.PropertyType); } } foreach (var typeToCheck in typesToCheck) { if (serializerTypeInfo.IsTypeAlreadyHandled(typeToCheck)) { continue; } if (!IsTypeSerializable(typeToCheck, serializerTypeInfo)) { serializerTypeInfo.AddTypeAsHandled(typeToCheck); continue; } var propertyTypeFullName = typeToCheck.GetSafeFullName(); if (propertyTypeFullName == null) { serializerTypeInfo.AddTypeAsHandled(typeToCheck); continue; } GetKnownTypes(typeToCheck, serializerTypeInfo); } }
/// <summary> /// Gets the known types inside the specific type. /// </summary> /// <param name="type">The type.</param> /// <param name="serializerTypeInfo">The serializer type info.</param> /// <param name="resolveAbstractClassesAndInterfaces">if set to <c>true</c> [resolve abstract classes and interfaces].</param> /// <returns>Array of <see cref="Type" /> that are found in the object type.</returns> protected virtual void GetKnownTypes(Type type, XmlSerializerTypeInfo serializerTypeInfo, bool resolveAbstractClassesAndInterfaces = true) { if (ShouldTypeBeIgnored(type, serializerTypeInfo)) { return; } #if ENABLE_DETAILED_LOGGING Log.Debug("Getting known types for '{0}'", type.GetSafeFullName()); #endif GetKnownTypesForItems(type, serializerTypeInfo); // If this is an interface or abstract, we need to retieve all items that might possible implement or derive var isInterface = type.IsInterfaceEx(); var isAbstract = type.IsAbstractEx(); if (isInterface || isAbstract) { if (!serializerTypeInfo.IsTypeAlreadyHandled(type) && resolveAbstractClassesAndInterfaces) { // Interfaces / abstract classes are not a type, and in fact a LOT of types can be added (in fact every object implementing // the interface). For serialization, this is not a problem (we know the exact type), but for deserialization this IS an // issue because we should expect EVERY type that implements the type in the whole AppDomain. // This is huge performance hit, but it's the cost for dynamic easy on-the-fly serialization in WPF and Silverlight. Luckily // we already implemented caching. // Don't check this type again in children checks serializerTypeInfo.AddTypeAsHandled(type); #if ENABLE_DETAILED_LOGGING Log.Debug("Type is an interface / abstract class, checking all types implementing / deriving"); #endif if (isInterface) { var typesImplementingInterface = TypeCache.GetTypesImplementingInterface(type); foreach (var typeImplementingInterface in typesImplementingInterface) { if (typeImplementingInterface != type) { GetKnownTypes(typeImplementingInterface, serializerTypeInfo); } } } if (isAbstract) { var typesDerivingFromClass = TypeCache.GetTypes(type.IsAssignableFromEx); foreach (var typeDerivingFromClass in typesDerivingFromClass) { if (typeDerivingFromClass != type) { GetKnownTypes(typeDerivingFromClass, serializerTypeInfo); } } } #if ENABLE_DETAILED_LOGGING Log.Debug("Finished checking all types implementing / deriving"); #endif } // The interface itself is ignored return; } if (serializerTypeInfo.IsSpecialCollectionType(type) && !type.IsInterfaceEx()) { #if ENABLE_DETAILED_LOGGING Log.Debug("Type is a special collection type, adding it to the array of known types"); #endif AddTypeToKnownTypesIfSerializable(type, serializerTypeInfo); } // Fix generics if (type.GetSafeFullName().StartsWith("System.")) { var genericArguments = type.GetGenericArgumentsEx(); foreach (var genericArgument in genericArguments) { #if ENABLE_DETAILED_LOGGING Log.Debug("Retrieving known types for generic argument '{0}' of '{1}'", genericArgument.GetSafeFullName(), type.GetSafeFullName()); #endif GetKnownTypes(genericArgument, serializerTypeInfo); } return; } if (!AddTypeToKnownTypesIfSerializable(type, serializerTypeInfo)) { serializerTypeInfo.AddTypeAsHandled(type); } AddTypeMembers(type, serializerTypeInfo); // If this isn't the base type, check that as well var baseType = type.GetBaseTypeEx(); if (baseType != null) { #if ENABLE_DETAILED_LOGGING Log.Debug("Checking base type of '{0}' for known types", type.GetSafeFullName()); #endif if (baseType.FullName != null) { GetKnownTypes(baseType, serializerTypeInfo); } else { serializerTypeInfo.AddTypeAsHandled(baseType); } } // Last but not least, check if the type is decorated with KnownTypeAttributes var knowTypesByAttributes = GetKnownTypesViaAttributes(type); if (knowTypesByAttributes.Length > 0) { #if ENABLE_DETAILED_LOGGING Log.Debug("Found {0} additional known types for type '{1}'", knowTypesByAttributes.Length, type.GetSafeFullName()); #endif foreach (var knownTypeByAttribute in knowTypesByAttributes) { var attributeType = knownTypeByAttribute; var attributeTypeFullName = attributeType.GetSafeFullName(); if (attributeTypeFullName != null) { GetKnownTypes(knownTypeByAttribute, serializerTypeInfo); } else { serializerTypeInfo.AddTypeAsHandled(attributeType); } } } }
/// <summary> /// Determines whether the type should be handled. /// </summary> /// <param name="type">The type.</param> /// <param name="serializerTypeInfo">The serializer type info.</param> /// <returns><c>true</c> if the type should be handled; otherwise, <c>false</c>.</returns> protected virtual bool ShouldTypeBeIgnored(Type type, XmlSerializerTypeInfo serializerTypeInfo) { if (type == null) { return true; } // Note, although resharper says this isn't possible, it might be if (type.FullName == null) { serializerTypeInfo.AddTypeAsHandled(type); return true; } // Ignore non-generic .NET if (!type.IsGenericTypeEx() && type.GetSafeFullName().StartsWith("System.")) { // Log.Debug("Non-generic .NET system type, can be ignored"); serializerTypeInfo.AddTypeAsHandled(type); return true; } return serializerTypeInfo.ContainsKnownType(type) || serializerTypeInfo.IsTypeAlreadyHandled(type); }
private void AddTypeMembers(Type type, XmlSerializerTypeInfo serializerTypeInfo) { var isModelBase = (type == typeof(ModelBase)) || typeof(ModelBase).IsAssignableFromEx(type); if (isModelBase) { var catelTypeInfo = PropertyDataManager.Default.GetCatelTypeInfo(type); var modelBaseProperties = catelTypeInfo.GetCatelProperties(); foreach (var modelBaseProperty in modelBaseProperties) { var propertyType = modelBaseProperty.Value.Type; if (propertyType.FullName != null) { GetKnownTypes(propertyType, serializerTypeInfo); } else { serializerTypeInfo.AddTypeAsHandled(propertyType); } } } else { bool allowNonPublicReflection = AllowNonPublicReflection(type); // Fields var fields = type.GetFieldsEx(BindingFlagsHelper.GetFinalBindingFlags(false, false, allowNonPublicReflection)); foreach (var field in fields) { var fieldType = field.FieldType; if (fieldType.FullName != null) { GetKnownTypes(fieldType, serializerTypeInfo); } else { serializerTypeInfo.AddTypeAsHandled(fieldType); } } // Properties var properties = type.GetPropertiesEx(BindingFlagsHelper.GetFinalBindingFlags(false, false, allowNonPublicReflection)); foreach (var property in properties) { var propertyType = property.PropertyType; if (propertyType.FullName != null) { GetKnownTypes(propertyType, serializerTypeInfo); } else { serializerTypeInfo.AddTypeAsHandled(propertyType); } } } }
/// <summary> /// Gets the known types inside the specific type. /// </summary> /// <param name="type">The type.</param> /// <param name="serializerTypeInfo">The serializer type info.</param> /// <returns>Array of <see cref="Type"/> that are found in the object type.</returns> protected virtual void GetKnownTypes(Type type, XmlSerializerTypeInfo serializerTypeInfo) { if (ShouldTypeBeIgnored(type, serializerTypeInfo)) { return; } Log.Debug("Getting known types for '{0}'", type.GetSafeFullName()); // If this is an interface, HOUSTON, WE HAVE A PROBLEM if (type.IsInterfaceEx()) { if (!serializerTypeInfo.IsTypeAlreadyHandled(type)) { Log.Debug("Type is an interface, checking all types deriving from this interface"); // Don't check this interface again in children checks serializerTypeInfo.AddTypeAsHandled(type); // Interfaces are not a type, and in fact a LOT of types can be added (in fact every object implementing the interface). For // serialization, this is not a problem (we know the exact type), but for deserialization this IS an issue because we should // expect EVERY type that implements the type in the whole AppDomain. // This is huge performance hit, but it's the cost for dynamic easy on-the-fly serialization in WPF and Silverlight. Luckily // we already implemented caching. var typesDerivingFromInterface = TypeCache.GetTypes(t => t.ImplementsInterfaceEx(type)); foreach (var typeDerivingFromInterface in typesDerivingFromInterface) { if (typeDerivingFromInterface != type) { GetKnownTypes(typeDerivingFromInterface, serializerTypeInfo); } } Log.Debug("Finished checking all types deriving from this interface"); } // The interface itself is ignored return; } if (serializerTypeInfo.IsSpecialCollectionType(type) && !type.IsInterfaceEx()) { Log.Debug("Type is a special collection type, adding it to the array of known types"); AddTypeToKnownTypesIfSerializable(type, serializerTypeInfo); } // Fix generics if (type.GetSafeFullName().StartsWith("System.")) { var genericArguments = type.GetGenericArgumentsEx(); foreach (var genericArgument in genericArguments) { Log.Debug("Retrieving known types for generic argument '{0}' of '{1}'", genericArgument.GetSafeFullName(), type.GetSafeFullName()); GetKnownTypes(genericArgument, serializerTypeInfo); } return; } if (!AddTypeToKnownTypesIfSerializable(type, serializerTypeInfo)) { serializerTypeInfo.AddTypeAsHandled(type); } AddTypeMembers(type, serializerTypeInfo); // If this isn't the base type, check that as well var baseType = type.GetBaseTypeEx(); if (baseType != null) { Log.Debug("Checking base type of '{0}' for known types", type.GetSafeFullName()); if (baseType.FullName != null) { GetKnownTypes(baseType, serializerTypeInfo); } else { serializerTypeInfo.AddTypeAsHandled(baseType); } } // Last but not least, check if the type is decorated with KnownTypeAttributes var knowTypesByAttributes = GetKnownTypesViaAttributes(type); if (knowTypesByAttributes.Length > 0) { Log.Debug("Found {0} additional known types for type '{1}'", knowTypesByAttributes.Length, type.GetSafeFullName()); foreach (var knownTypeByAttribute in knowTypesByAttributes) { var attributeType = knownTypeByAttribute; if (attributeType.FullName != null) { GetKnownTypes(knownTypeByAttribute, serializerTypeInfo); } else { serializerTypeInfo.AddTypeAsHandled(attributeType); } } } }
/// <summary> /// Gets the known types inside the specific type. /// </summary> /// <param name="type">The type.</param> /// <param name="serializerTypeInfo">The serializer type info.</param> /// <returns>Array of <see cref="Type"/> that are found in the object type.</returns> protected virtual void GetKnownTypes(Type type, XmlSerializerTypeInfo serializerTypeInfo) { if (ShouldTypeBeIgnored(type, serializerTypeInfo)) { return; } Log.Debug("Getting known types for '{0}'", type.GetSafeFullName()); GetKnownTypesForItems(type, serializerTypeInfo); // If this is an interface or abstract, we need to retieve all items that might possible implement or derive bool isInterface = type.IsInterfaceEx(); bool isAbstract = type.IsAbstractEx(); if (isInterface || isAbstract) { if (!serializerTypeInfo.IsTypeAlreadyHandled(type)) { // Interfaces / abstract classes are not a type, and in fact a LOT of types can be added (in fact every object implementing // the interface). For serialization, this is not a problem (we know the exact type), but for deserialization this IS an // issue because we should expect EVERY type that implements the type in the whole AppDomain. // This is huge performance hit, but it's the cost for dynamic easy on-the-fly serialization in WPF and Silverlight. Luckily // we already implemented caching. // Don't check this type again in children checks serializerTypeInfo.AddTypeAsHandled(type); Log.Debug("Type is an interface / abstract class, checking all types implementing / deriving"); if (isInterface) { var typesImplementingInterface = TypeCache.GetTypesImplementingInterface(type); //var typesImplementingInterface = TypeCache.GetTypes(t => t.ImplementsInterfaceEx(type)); foreach (var typeImplementingInterface in typesImplementingInterface) { if (typeImplementingInterface != type) { GetKnownTypes(typeImplementingInterface, serializerTypeInfo); } } } if (isAbstract) { var typesDerivingFromClass = TypeCache.GetTypes(type.IsAssignableFromEx); foreach (var typeDerivingFromClass in typesDerivingFromClass) { if (typeDerivingFromClass != type) { GetKnownTypes(typeDerivingFromClass, serializerTypeInfo); } } } Log.Debug("Finished checking all types implementing / deriving"); } // The interface itself is ignored return; } if (serializerTypeInfo.IsSpecialCollectionType(type) && !type.IsInterfaceEx()) { Log.Debug("Type is a special collection type, adding it to the array of known types"); AddTypeToKnownTypesIfSerializable(type, serializerTypeInfo); } // Fix generics if (type.GetSafeFullName().StartsWith("System.")) { var genericArguments = type.GetGenericArgumentsEx(); foreach (var genericArgument in genericArguments) { Log.Debug("Retrieving known types for generic argument '{0}' of '{1}'", genericArgument.GetSafeFullName(), type.GetSafeFullName()); GetKnownTypes(genericArgument, serializerTypeInfo); } return; } if (!AddTypeToKnownTypesIfSerializable(type, serializerTypeInfo)) { serializerTypeInfo.AddTypeAsHandled(type); } AddTypeMembers(type, serializerTypeInfo); // If this isn't the base type, check that as well var baseType = type.GetBaseTypeEx(); if (baseType != null) { Log.Debug("Checking base type of '{0}' for known types", type.GetSafeFullName()); if (baseType.FullName != null) { GetKnownTypes(baseType, serializerTypeInfo); } else { serializerTypeInfo.AddTypeAsHandled(baseType); } } // Last but not least, check if the type is decorated with KnownTypeAttributes var knowTypesByAttributes = GetKnownTypesViaAttributes(type); if (knowTypesByAttributes.Length > 0) { Log.Debug("Found {0} additional known types for type '{1}'", knowTypesByAttributes.Length, type.GetSafeFullName()); foreach (var knownTypeByAttribute in knowTypesByAttributes) { var attributeType = knownTypeByAttribute; var attributeTypeFullName = attributeType.GetSafeFullName(); if (attributeTypeFullName != null) { GetKnownTypes(knownTypeByAttribute, serializerTypeInfo); } else { serializerTypeInfo.AddTypeAsHandled(attributeType); } } } }