/// <summary> /// Adds the type to the known types if the type is serializable. /// </summary> /// <param name="typeToAdd">The type to add.</param> /// <param name="serializerTypeInfo">The serializer type info.</param> /// <returns><c>true</c> if the type is serializable; otherwise <c>false</c>.</returns> protected virtual bool AddTypeToKnownTypesIfSerializable(Type typeToAdd, XmlSerializerTypeInfo serializerTypeInfo) { // Collection first, this collection of types is smaller so if we have a hit, we exit sooner if (serializerTypeInfo.IsCollectionAlreadyHandled(typeToAdd)) { return(true); } if (serializerTypeInfo.ContainsKnownType(typeToAdd)) { return(true); } serializerTypeInfo.AddCollectionAsHandled(typeToAdd); // If this is a special collection type (generic), then we need to make sure that if the inner type is // an interface, we do not add it again if already added. // See this issue http://catel.codeplex.com/workitem/7167 if (serializerTypeInfo.IsSpecialCollectionType(typeToAdd)) { // Always ignore return(false); } return(serializerTypeInfo.AddKnownType(typeToAdd)); }
/// <summary> /// Adds the type to the known types if the type is serializable. /// </summary> /// <param name="typeToAdd">The type to add.</param> /// <param name="serializerTypeInfo">The serializer type info.</param> /// <returns><c>true</c> if the type is serializable; otherwise <c>false</c>.</returns> protected virtual bool AddTypeToKnownTypesIfSerializable(Type typeToAdd, XmlSerializerTypeInfo serializerTypeInfo) { // Collection first, this collection of types is smaller so if we have a hit, we exit sooner if (serializerTypeInfo.IsCollectionAlreadyHandled(typeToAdd)) { return(true); } if (serializerTypeInfo.ContainsKnownType(typeToAdd)) { return(true); } serializerTypeInfo.AddCollectionAsHandled(typeToAdd); // If this is a special collection type (generic), then we need to make sure that if the inner type is // an interface, we do not add it again if already added. // See this issue http://catel.codeplex.com/workitem/7167 if (serializerTypeInfo.IsSpecialCollectionType(typeToAdd)) { // Always ignore as a test return(false); // TODO: Also check interfaces // // It might be a base type, loop all // var baseType = typeToAdd; // while (baseType != null) // { // if (baseType.IsGenericTypeEx()) // { // if (baseType.GetGenericArgumentsEx()[0].IsInterfaceEx()) // { // var genericTypeDefinition = baseType.GetGenericTypeDefinitionEx(); // var allPossibleMatchingTypes = (from type in serializerTypeInfo.SpecialGenericCollectionTypes // where type.GetGenericTypeDefinitionEx() == genericTypeDefinition // select type).ToList(); // if (allPossibleMatchingTypes.Count > 0) // { // Log.Debug("Skipping type '{0}' because there already exists such a type which does the same", typeToAdd.GetSafeFullName()); // return false; // } // } // } // baseType = baseType.GetBaseTypeEx(); // } } return(serializerTypeInfo.AddKnownType(typeToAdd)); }
/// <summary> /// Adds the type to the known types if the type is serializable. /// </summary> /// <param name="typeToAdd">The type to add.</param> /// <param name="serializerTypeInfo">The serializer type info.</param> /// <returns><c>true</c> if the type is serializable; otherwise <c>false</c>.</returns> protected virtual bool AddTypeToKnownTypesIfSerializable(Type typeToAdd, XmlSerializerTypeInfo serializerTypeInfo) { // Collection first, this collection of types is smaller so if we have a hit, we exit sooner if (serializerTypeInfo.IsCollectionAlreadyHandled(typeToAdd)) { return true; } if (serializerTypeInfo.ContainsKnownType(typeToAdd)) { return true; } serializerTypeInfo.AddCollectionAsHandled(typeToAdd); // If this is a special collection type (generic), then we need to make sure that if the inner type is // an interface, we do not add it again if already added. // See this issue http://catel.codeplex.com/workitem/7167 if (serializerTypeInfo.IsSpecialCollectionType(typeToAdd)) { // Always ignore return false; } return serializerTypeInfo.AddKnownType(typeToAdd); }
/// <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> /// Adds the type to the known types if the type is serializable. /// </summary> /// <param name="typeToAdd">The type to add.</param> /// <param name="serializerTypeInfo">The serializer type info.</param> /// <returns><c>true</c> if the type is serializable; otherwise <c>false</c>.</returns> protected virtual bool AddTypeToKnownTypesIfSerializable(Type typeToAdd, XmlSerializerTypeInfo serializerTypeInfo) { // Collection first, this collection of types is smaller so if we have a hit, we exit sooner if (serializerTypeInfo.IsCollectionAlreadyHandled(typeToAdd)) { return true; } if (serializerTypeInfo.ContainsKnownType(typeToAdd)) { return true; } serializerTypeInfo.AddCollectionAsHandled(typeToAdd); // If this is a special collection type (generic), then we need to make sure that if the inner type is // an interface, we do not add it again if already added. // See this issue http://catel.codeplex.com/workitem/7167 if (serializerTypeInfo.IsSpecialCollectionType(typeToAdd)) { // Always ignore as a test return false; // TODO: Also check interfaces // // It might be a base type, loop all // var baseType = typeToAdd; // while (baseType != null) // { // if (baseType.IsGenericTypeEx()) // { // if (baseType.GetGenericArgumentsEx()[0].IsInterfaceEx()) // { // var genericTypeDefinition = baseType.GetGenericTypeDefinitionEx(); // var allPossibleMatchingTypes = (from type in serializerTypeInfo.SpecialGenericCollectionTypes // where type.GetGenericTypeDefinitionEx() == genericTypeDefinition // select type).ToList(); // if (allPossibleMatchingTypes.Count > 0) // { // Log.Debug("Skipping type '{0}' because there already exists such a type which does the same", typeToAdd.GetSafeFullName()); // return false; // } // } // } // baseType = baseType.GetBaseTypeEx(); // } } return serializerTypeInfo.AddKnownType(typeToAdd); }
/// <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); } } } }