internal static T Create <T>(IDefaultData defaultData, ObjectCreationStrategy objectCreationStrategy) { var expectedType = typeof(T); var genericType = expectedType.GetGenericTypeDefinition(); return(expectedType.IsInterface ? (T)GenericInterfaceCollectionTypes.GetValueOrDefault(genericType)?.Invoke(expectedType, defaultData, objectCreationStrategy) : (T)GenericCollectionTypes.GetValueOrDefault(genericType)?.Invoke(expectedType, defaultData, objectCreationStrategy)); }
private static bool TryCreateCollectionTraitsForIEnumerableT( Type source, GenericCollectionTypes genericTypes, CollectionTraitOptions options, MethodInfo getMethod, out CollectionTraits result ) { var elementType = genericTypes.IEnumerableT.GetGenericArguments()[0]; var addMethod = GetAddMethod(source, elementType, options); if (addMethod == null && ((options & CollectionTraitOptions.AllowNonCollectionEnumerableTypes) != 0)) { // This should be non collection object isntead of "unappendable" collection. result = default(CollectionTraits); return(false); } CollectionDetailedKind kind = CollectionDetailedKind.GenericEnumerable; if (genericTypes.IListT != null) { kind = CollectionDetailedKind.GenericList; } #if !NETFX_35 && !UNITY else if (genericTypes.ISetT != null) { kind = CollectionDetailedKind.GenericSet; } #endif // !NETFX_35 && !UNITY else if (genericTypes.ICollectionT != null) { kind = CollectionDetailedKind.GenericCollection; } #if !NETFX_35 && !UNITY && !NETFX_40 && !(SILVERLIGHT && !WINDOWS_PHONE) else if (genericTypes.IReadOnlyListT != null) { kind = CollectionDetailedKind.GenericReadOnlyList; } else if (genericTypes.IReadOnlyCollectionT != null) { kind = CollectionDetailedKind.GenericReadOnlyCollection; } #endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE ) result = new CollectionTraits( kind, elementType, getMethod ?? GetGetEnumeratorMethodFromElementType(source, elementType, options), addMethod, GetCountGetterMethod(source, elementType, options) ); return(true); }
private static bool DetermineCollectionInterfaces( Type type, ref GenericCollectionTypes genericTypes, ref Type idictionary, ref Type ilist, ref Type icollection, ref Type ienumerable ) { if (type.GetIsGenericType()) { var genericTypeDefinition = type.GetGenericTypeDefinition(); if (genericTypeDefinition == typeof(IDictionary <,>)) { if (genericTypes.IDictionaryT != null) { return(false); } genericTypes.IDictionaryT = type; } #if !NETFX_35 && !UNITY && !NETFX_40 && !(SILVERLIGHT && !WINDOWS_PHONE) else if (genericTypeDefinition == typeof(IReadOnlyDictionary <,>)) { if (genericTypes.IReadOnlyDictionaryT != null) { return(false); } genericTypes.IReadOnlyDictionaryT = type; } #endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE ) else if (genericTypeDefinition == typeof(IList <>)) { if (genericTypes.IListT != null) { return(false); } genericTypes.IListT = type; } #if !NETFX_35 && !UNITY && !NETFX_40 && !(SILVERLIGHT && !WINDOWS_PHONE) else if (genericTypeDefinition == typeof(IReadOnlyList <>)) { if (genericTypes.IReadOnlyListT != null) { return(false); } genericTypes.IReadOnlyListT = type; } #endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE ) #if !NETFX_35 && !UNITY else if (genericTypeDefinition == typeof(ISet <>)) { if (genericTypes.ISetT != null) { return(false); } genericTypes.ISetT = type; } #endif // !NETFX_35 && !UNITY else if (genericTypeDefinition == typeof(ICollection <>)) { if (genericTypes.ICollectionT != null) { return(false); } genericTypes.ICollectionT = type; } #if !NETFX_35 && !UNITY && !NETFX_40 && !(SILVERLIGHT && !WINDOWS_PHONE) else if (genericTypeDefinition == typeof(IReadOnlyCollection <>)) { if (genericTypes.IReadOnlyCollectionT != null) { return(false); } genericTypes.IReadOnlyCollectionT = type; } #endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE ) else if (genericTypeDefinition == typeof(IEnumerable <>)) { if (genericTypes.IEnumerableT != null) { return(false); } genericTypes.IEnumerableT = type; } } else { if (type == typeof(IDictionary)) { idictionary = type; } else if (type == typeof(IList)) { ilist = type; } else if (type == typeof(ICollection)) { icollection = type; } else if (type == typeof(IEnumerable)) { ienumerable = type; } } return(true); }
private static bool TryCreateCollectionTraitsForHasGetEnumeratorType( Type source, CollectionTraitOptions options, MethodInfo getEnumerator, out CollectionTraits result ) { if (source.Implements(typeof(IDictionary <,>)) #if !NETFX_35 && !UNITY && !NETFX_40 && !(SILVERLIGHT && !WINDOWS_PHONE) || source.Implements(typeof(IReadOnlyDictionary <,>)) #endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE ) ) { var ienumetaorT = getEnumerator.ReturnType.GetInterfaces() .FirstOrDefault(@interface => @interface.GetIsGenericType() && @interface.GetGenericTypeDefinition() == typeof(IEnumerator <>) ); if (ienumetaorT != null) { var elementType = ienumetaorT.GetGenericArguments()[0]; var elementTypeGenericArguments = elementType.GetGenericArguments(); result = new CollectionTraits( #if !NETFX_35 && !UNITY && !NETFX_40 && !(SILVERLIGHT && !WINDOWS_PHONE) source.Implements(typeof(IDictionary <,>)) ? CollectionDetailedKind.GenericDictionary : CollectionDetailedKind.GenericReadOnlyDictionary, #else CollectionDetailedKind.GenericDictionary, #endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE ) elementType, getEnumerator, GetAddMethod(source, elementTypeGenericArguments[0], elementTypeGenericArguments [1], options), GetCountGetterMethod(source, elementType, options) ); return(true); } } if (source.IsAssignableTo(typeof(IDictionary))) { result = new CollectionTraits( CollectionDetailedKind.NonGenericDictionary, typeof(DictionaryEntry), getEnumerator, GetAddMethod(source, typeof(object), typeof(object), options), GetCountGetterMethod(source, typeof(object), options) ); return(true); } // Block to limit variable scope { var ienumetaorT = IsIEnumeratorT(getEnumerator.ReturnType) ? getEnumerator.ReturnType : getEnumerator.ReturnType.GetInterfaces().FirstOrDefault(IsIEnumeratorT); if (ienumetaorT != null) { // Get the open generic types once Type[] genericInterfaces = source.GetInterfaces() .Where(i => i.GetIsGenericType()) .Select(i => i.GetGenericTypeDefinition()) .ToArray(); var genericTypes = new GenericCollectionTypes(); genericTypes.IEnumerableT = ienumetaorT; genericTypes.ICollectionT = genericInterfaces.FirstOrDefault(i => i == typeof(ICollection <>)); genericTypes.IListT = genericInterfaces.FirstOrDefault(i => i == typeof(IList <>)); #if !NETFX_35 && !UNITY genericTypes.ISetT = genericInterfaces.FirstOrDefault(i => i == typeof(ISet <>)); #endif // !NETFX_35 && !UNITY #if !NETFX_35 && !UNITY && !NETFX_40 && !(SILVERLIGHT && !WINDOWS_PHONE) genericTypes.IReadOnlyCollectionT = genericInterfaces.FirstOrDefault(i => i == typeof(IReadOnlyCollection <>)); genericTypes.IReadOnlyListT = genericInterfaces.FirstOrDefault(i => i == typeof(IReadOnlyList <>)); #endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE ) return(TryCreateCollectionTraitsForIEnumerableT(source, genericTypes, options, getEnumerator, out result)); } } result = default(CollectionTraits); return(false); }
public static CollectionTraits GetCollectionTraits(this Type source, CollectionTraitOptions options, bool allowNonCollectionEnumerableTypes) { #if DEBUG Contract.Assert(!source.GetContainsGenericParameters(), "!source.GetContainsGenericParameters()"); #endif // DEBUG /* * SPEC * If the object has single public method TEnumerator GetEnumerator() ( where TEnumerator implements IEnumerator<TItem>), * then the object is considered as the collection of TItem. * When the object is considered as the collection of TItem, TItem is KeyValuePair<TKey,TValue>, * and the object implements IDictionary<TKey,TValue>, then the object is considered as dictionary of TKey and TValue. * Else, if the object has single public method IEnumerator GetEnumerator(), then the object is considered as the collection of Object. * When it also implements IDictionary, however, it is considered dictionary of Object and Object. * Otherwise, that means it implements multiple collection interface, is following. * First, if the object implements IDictionary<MessagePackObject,MessagePackObject>, then it is considered as MPO dictionary. * Second, if the object implements IEnumerable<MPO>, then it is considered as MPO dictionary. * Third, if the object implement SINGLE IDictionary<TKey,TValue> and multiple IEnumerable<T>, then it is considered as dictionary of TKey and TValue. * Fourth, the object is considered as UNSERIALIZABLE member. This behavior similer to DataContract serialization behavor * (see http://msdn.microsoft.com/en-us/library/aa347850.aspx ). */ if (!source.IsAssignableTo(typeof(IEnumerable))) { return(CollectionTraits.NotCollection); } if (source.IsArray) { return (new CollectionTraits( CollectionDetailedKind.Array, source.GetElementType(), null, // Never used for array. null, // Never used for array. null // Never used for array. )); } // If the type is an interface then a concrete collection has to be // made for it (if the interface is a collection type), therefore, // ignore the check for an add method if (!source.GetIsInterface() && allowNonCollectionEnumerableTypes) { options = options | CollectionTraitOptions.AllowNonCollectionEnumerableTypes; } MethodInfo getEnumerator = source.GetMethod("GetEnumerator", ReflectionAbstractions.EmptyTypes); if (getEnumerator != null && getEnumerator.ReturnType.IsAssignableTo(typeof(IEnumerator))) { // If public 'GetEnumerator' is found, it is primary collection traits. CollectionTraits result; if (TryCreateCollectionTraitsForHasGetEnumeratorType(source, options, getEnumerator, out result)) { return(result); } } GenericCollectionTypes genericTypes = new GenericCollectionTypes(); Type ienumerable = null; Type icollection = null; Type ilist = null; Type idictionary = null; var sourceInterfaces = source.FindInterfaces(FilterCollectionType, null); if (source.GetIsInterface() && FilterCollectionType(source, null)) { var originalSourceInterfaces = sourceInterfaces.ToArray(); var concatenatedSourceInterface = new Type[originalSourceInterfaces.Length + 1]; concatenatedSourceInterface[0] = source; for (int i = 0; i < originalSourceInterfaces.Length; i++) { concatenatedSourceInterface[i + 1] = originalSourceInterfaces[i]; } sourceInterfaces = concatenatedSourceInterface; } foreach (var type in sourceInterfaces) { CollectionTraits result; if (TryCreateGenericCollectionTraits(source, type, options, out result)) { return(result); } if (!DetermineCollectionInterfaces( type, ref genericTypes, ref idictionary, ref ilist, ref icollection, ref ienumerable ) ) { return(CollectionTraits.Unserializable); } } if (genericTypes.IDictionaryT != null) { var genericArguments = genericTypes.IDictionaryT.GetGenericArguments(); var elementType = typeof(KeyValuePair <,>).MakeGenericType(genericArguments); return (new CollectionTraits( CollectionDetailedKind.GenericDictionary, elementType, GetGetEnumeratorMethodFromElementType(source, elementType, options), GetAddMethod(source, genericArguments[0], genericArguments[1], options), GetCountGetterMethod(source, elementType, options) )); } #if !NETFX_35 && !UNITY && !NETFX_40 && !(SILVERLIGHT && !WINDOWS_PHONE) if (genericTypes.IReadOnlyDictionaryT != null) { var elementType = typeof(KeyValuePair <,>).MakeGenericType(genericTypes.IReadOnlyDictionaryT.GetGenericArguments()); return (new CollectionTraits( CollectionDetailedKind.GenericReadOnlyDictionary, elementType, GetGetEnumeratorMethodFromElementType(source, elementType, options), null, // add GetCountGetterMethod(source, elementType, options) )); } #endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE ) if (genericTypes.IEnumerableT != null) { CollectionTraits traits; if (TryCreateCollectionTraitsForIEnumerableT(source, genericTypes, options, null, out traits)) { return(traits); } } if (idictionary != null) { return (new CollectionTraits( CollectionDetailedKind.NonGenericDictionary, typeof(object), GetGetEnumeratorMethodFromEnumerableType(source, idictionary, options), GetAddMethod(source, typeof(object), typeof(object), options), GetCountGetterMethod(source, typeof(object), options) )); } if (ienumerable != null) { var addMethod = GetAddMethod(source, typeof(object), options | CollectionTraitOptions.WithAddMethod); if (addMethod != null || ((options & CollectionTraitOptions.AllowNonCollectionEnumerableTypes) == 0)) { // This should be appendable or unappendable collection return (new CollectionTraits( (ilist != null) ? CollectionDetailedKind.NonGenericList : (icollection != null) ? CollectionDetailedKind.NonGenericCollection : CollectionDetailedKind.NonGenericEnumerable, typeof(object), GetGetEnumeratorMethodFromEnumerableType(source, ienumerable, options), addMethod, GetCountGetterMethod(source, typeof(object), options) )); } } return(CollectionTraits.NotCollection); }
public static CollectionTraits GetCollectionTraits( this Type source, CollectionTraitOptions options, bool allowNonCollectionEnumerableTypes ) { #if DEBUG Contract.Assert( !source.GetContainsGenericParameters(), "!source.GetContainsGenericParameters()" ); #endif // DEBUG /* * SPEC * If the object has single public method TEnumerator GetEnumerator() ( where TEnumerator implements IEnumerator<TItem>), * then the object is considered as the collection of TItem. * When the object is considered as the collection of TItem, TItem is KeyValuePair<TKey,TValue>, * and the object implements IDictionary<TKey,TValue>, then the object is considered as dictionary of TKey and TValue. * Else, if the object has single public method IEnumerator GetEnumerator(), then the object is considered as the collection of Object. * When it also implements IDictionary, however, it is considered dictionary of Object and Object. * Otherwise, that means it implements multiple collection interface, is following. * First, if the object implements IDictionary<MessagePackObject,MessagePackObject>, then it is considered as MPO dictionary. * Second, if the object implements IEnumerable<MPO>, then it is considered as MPO dictionary. * Third, if the object implement SINGLE IDictionary<TKey,TValue> and multiple IEnumerable<T>, then it is considered as dictionary of TKey and TValue. * Fourth, the object is considered as UNSERIALIZABLE member. This behavior similer to DataContract serialization behavor * (see http://msdn.microsoft.com/en-us/library/aa347850.aspx ). */ if ( !source.IsAssignableTo( typeof( IEnumerable ) ) ) { return CollectionTraits.NotCollection; } if ( source.IsArray ) { return new CollectionTraits( CollectionDetailedKind.Array, source.GetElementType(), null, // Never used for array. null, // Never used for array. null // Never used for array. ); } // If the type is an interface then a concrete collection has to be // made for it (if the interface is a collection type), therefore, // ignore the check for an add method if ( !source.GetIsInterface() && allowNonCollectionEnumerableTypes ) { options = options | CollectionTraitOptions.AllowNonCollectionEnumerableTypes; } MethodInfo getEnumerator = source.GetMethod( "GetEnumerator", ReflectionAbstractions.EmptyTypes ); if ( getEnumerator != null && getEnumerator.ReturnType.IsAssignableTo( typeof( IEnumerator ) ) ) { // If public 'GetEnumerator' is found, it is primary collection traits. CollectionTraits result; if ( TryCreateCollectionTraitsForHasGetEnumeratorType( source, options, getEnumerator, out result ) ) { return result; } } GenericCollectionTypes genericTypes = new GenericCollectionTypes(); Type ienumerable = null; Type icollection = null; Type ilist = null; Type idictionary = null; var sourceInterfaces = source.FindInterfaces( FilterCollectionType, null ); if ( source.GetIsInterface() && FilterCollectionType( source, null ) ) { var originalSourceInterfaces = sourceInterfaces.ToArray(); var concatenatedSourceInterface = new Type[ originalSourceInterfaces.Length + 1 ]; concatenatedSourceInterface[ 0 ] = source; for ( int i = 0; i < originalSourceInterfaces.Length; i++ ) { concatenatedSourceInterface[ i + 1 ] = originalSourceInterfaces[ i ]; } sourceInterfaces = concatenatedSourceInterface; } foreach ( var type in sourceInterfaces ) { CollectionTraits result; if ( TryCreateGenericCollectionTraits( source, type, options, out result ) ) { return result; } if ( !DetermineCollectionInterfaces( type, ref genericTypes, ref idictionary, ref ilist, ref icollection, ref ienumerable ) ) { return CollectionTraits.Unserializable; } } if ( genericTypes.IDictionaryT != null ) { var genericArguments = genericTypes.IDictionaryT.GetGenericArguments(); var elementType = typeof( KeyValuePair<,> ).MakeGenericType( genericArguments ); return new CollectionTraits( CollectionDetailedKind.GenericDictionary, elementType, GetGetEnumeratorMethodFromElementType( source, elementType, options ), GetAddMethod( source, genericArguments[ 0 ], genericArguments[ 1 ], options ), GetCountGetterMethod( source, elementType, options ) ); } #if !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE ) if ( genericTypes.IReadOnlyDictionaryT != null ) { var elementType = typeof( KeyValuePair<,> ).MakeGenericType( genericTypes.IReadOnlyDictionaryT.GetGenericArguments() ); return new CollectionTraits( CollectionDetailedKind.GenericReadOnlyDictionary, elementType, GetGetEnumeratorMethodFromElementType( source, elementType, options ), null, // add GetCountGetterMethod( source, elementType, options ) ); } #endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE ) if ( genericTypes.IEnumerableT != null ) { CollectionTraits traits; if ( TryCreateCollectionTraitsForIEnumerableT( source, genericTypes, options, null, out traits ) ) { return traits; } } if ( idictionary != null ) { return new CollectionTraits( CollectionDetailedKind.NonGenericDictionary, typeof( object ), GetGetEnumeratorMethodFromEnumerableType( source, idictionary, options ), GetAddMethod( source, typeof( object ), typeof( object ), options ), GetCountGetterMethod( source, typeof( object ), options ) ); } if ( ienumerable != null ) { var addMethod = GetAddMethod( source, typeof( object ), options | CollectionTraitOptions.WithAddMethod ); if ( addMethod != null || ( ( options & CollectionTraitOptions.AllowNonCollectionEnumerableTypes ) == 0 ) ) { // This should be appendable or unappendable collection return new CollectionTraits( ( ilist != null ) ? CollectionDetailedKind.NonGenericList : ( icollection != null ) ? CollectionDetailedKind.NonGenericCollection : CollectionDetailedKind.NonGenericEnumerable, typeof( object ), GetGetEnumeratorMethodFromEnumerableType( source, ienumerable, options ), addMethod, GetCountGetterMethod( source, typeof( object ), options ) ); } } return CollectionTraits.NotCollection; }
private static bool DetermineCollectionInterfaces( Type type, ref GenericCollectionTypes genericTypes, ref Type idictionary, ref Type ilist, ref Type icollection, ref Type ienumerable ) { if ( type.GetIsGenericType() ) { var genericTypeDefinition = type.GetGenericTypeDefinition(); if ( genericTypeDefinition == typeof( IDictionary<,> ) ) { if ( genericTypes.IDictionaryT != null ) { return false; } genericTypes.IDictionaryT = type; } #if !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE ) else if ( genericTypeDefinition == typeof( IReadOnlyDictionary<,> ) ) { if ( genericTypes.IReadOnlyDictionaryT != null ) { return false; } genericTypes.IReadOnlyDictionaryT = type; } #endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE ) else if ( genericTypeDefinition == typeof( IList<> ) ) { if ( genericTypes.IListT != null ) { return false; } genericTypes.IListT = type; } #if !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE ) else if ( genericTypeDefinition == typeof( IReadOnlyList<> ) ) { if ( genericTypes.IReadOnlyListT != null ) { return false; } genericTypes.IReadOnlyListT = type; } #endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE ) #if !NETFX_35 && !UNITY else if ( genericTypeDefinition == typeof( ISet<> ) ) { if ( genericTypes.ISetT != null ) { return false; } genericTypes.ISetT = type; } #endif // !NETFX_35 && !UNITY else if ( genericTypeDefinition == typeof( ICollection<> ) ) { if ( genericTypes.ICollectionT != null ) { return false; } genericTypes.ICollectionT = type; } #if !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE ) else if ( genericTypeDefinition == typeof( IReadOnlyCollection<> ) ) { if ( genericTypes.IReadOnlyCollectionT != null ) { return false; } genericTypes.IReadOnlyCollectionT = type; } #endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE ) else if ( genericTypeDefinition == typeof( IEnumerable<> ) ) { if ( genericTypes.IEnumerableT != null ) { return false; } genericTypes.IEnumerableT = type; } } else { if ( type == typeof( IDictionary ) ) { idictionary = type; } else if ( type == typeof( IList ) ) { ilist = type; } else if ( type == typeof( ICollection ) ) { icollection = type; } else if ( type == typeof( IEnumerable ) ) { ienumerable = type; } } return true; }
private static bool TryCreateCollectionTraitsForHasGetEnumeratorType( Type source, CollectionTraitOptions options, MethodInfo getEnumerator, out CollectionTraits result ) { if ( source.Implements( typeof( IDictionary<,> ) ) #if !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE ) || source.Implements( typeof( IReadOnlyDictionary<,> ) ) #endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE ) ) { var ienumetaorT = getEnumerator.ReturnType.GetInterfaces() .FirstOrDefault( @interface => @interface.GetIsGenericType() && @interface.GetGenericTypeDefinition() == typeof( IEnumerator<> ) ); if ( ienumetaorT != null ) { var elementType = ienumetaorT.GetGenericArguments()[ 0 ]; var elementTypeGenericArguments = elementType.GetGenericArguments(); result = new CollectionTraits( #if !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE ) source.Implements( typeof( IDictionary<,> ) ) ? CollectionDetailedKind.GenericDictionary : CollectionDetailedKind.GenericReadOnlyDictionary, #else CollectionDetailedKind.GenericDictionary, #endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE ) elementType, getEnumerator, GetAddMethod( source, elementTypeGenericArguments[ 0 ], elementTypeGenericArguments [ 1 ], options ), GetCountGetterMethod( source, elementType, options ) ); return true; } } if ( source.IsAssignableTo( typeof( IDictionary ) ) ) { result = new CollectionTraits( CollectionDetailedKind.NonGenericDictionary, typeof( DictionaryEntry ), getEnumerator, GetAddMethod( source, typeof( object ), typeof( object ), options ), GetCountGetterMethod( source, typeof( object ), options ) ); return true; } // Block to limit variable scope { var ienumetaorT = IsIEnumeratorT( getEnumerator.ReturnType ) ? getEnumerator.ReturnType : getEnumerator.ReturnType.GetInterfaces().FirstOrDefault( IsIEnumeratorT ); if ( ienumetaorT != null ) { // Get the open generic types once Type[] genericInterfaces = source.GetInterfaces() .Where( i => i.GetIsGenericType() ) .Select( i => i.GetGenericTypeDefinition() ) .ToArray(); var genericTypes = new GenericCollectionTypes(); genericTypes.IEnumerableT = ienumetaorT; genericTypes.ICollectionT = genericInterfaces.FirstOrDefault( i => i == typeof(ICollection<>) ); genericTypes.IListT = genericInterfaces.FirstOrDefault( i => i == typeof(IList<>) ); #if !NETFX_35 && !UNITY genericTypes.ISetT = genericInterfaces.FirstOrDefault( i => i == typeof(ISet<>) ); #endif // !NETFX_35 && !UNITY #if !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE ) genericTypes.IReadOnlyCollectionT = genericInterfaces.FirstOrDefault( i => i == typeof(IReadOnlyCollection<>) ); genericTypes.IReadOnlyListT = genericInterfaces.FirstOrDefault( i => i == typeof(IReadOnlyList<>) ); #endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE ) return TryCreateCollectionTraitsForIEnumerableT( source, genericTypes, options, getEnumerator, out result ); } } result = default( CollectionTraits ); return false; }
private static bool TryCreateCollectionTraitsForIEnumerableT( Type source, GenericCollectionTypes genericTypes, CollectionTraitOptions options, MethodInfo getMethod, out CollectionTraits result ) { var elementType = genericTypes.IEnumerableT.GetGenericArguments()[ 0 ]; var addMethod = GetAddMethod( source, elementType, options ); if ( addMethod == null && ( ( options & CollectionTraitOptions.AllowNonCollectionEnumerableTypes ) != 0 ) ) { // This should be non collection object isntead of "unappendable" collection. result = default( CollectionTraits ); return false; } CollectionDetailedKind kind = CollectionDetailedKind.GenericEnumerable; if ( genericTypes.IListT != null ) { kind = CollectionDetailedKind.GenericList; } #if !NETFX_35 && !UNITY else if ( genericTypes.ISetT != null ) { kind = CollectionDetailedKind.GenericSet; } #endif // !NETFX_35 && !UNITY else if ( genericTypes.ICollectionT != null ) { kind = CollectionDetailedKind.GenericCollection; } #if !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE ) else if ( genericTypes.IReadOnlyListT != null ) { kind = CollectionDetailedKind.GenericReadOnlyList; } else if ( genericTypes.IReadOnlyCollectionT != null ) { kind = CollectionDetailedKind.GenericReadOnlyCollection; } #endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE ) result = new CollectionTraits( kind, elementType, getMethod ?? GetGetEnumeratorMethodFromElementType( source, elementType, options ), addMethod, GetCountGetterMethod( source, elementType, options ) ); return true; }
private PropertiesProcessingResult ProcessProperties( TablesStructure tablesStructure, Type type, Type parentType, string parentIdPropertyName, string parentIdPropertyTypeName) { string typeName = type.Name; _excludedPropertiesMap.TryGetValue(typeName, out var excludedProperties); _idPropertiesMap.TryGetValue(typeName, out var idPropertyName); _relationPropertiesMap.TryGetValue(typeName, out var relationPropertyName); var valueProperties = new List <PropertyInfo>(); var oneChildrenProperties = new List <(PropertyInfo, Type)>(); var manyChildrenProperties = new List <(PropertyInfo, Type)>(); string parentTypeName = parentType?.Name; var collector = new TableStructure { TableName = string.IsNullOrWhiteSpace(parentTypeName) ? (string.IsNullOrWhiteSpace(_instanceTag) ? typeName : $"{typeName}_{_instanceTag}") : (string.IsNullOrWhiteSpace(_instanceTag) ? $"{parentTypeName}{typeName}" : $"{parentTypeName}{typeName}_{_instanceTag}"), AzureBlobFolder = typeName.ToLower(), Columns = new List <ColumnInfo>(), }; var topLevelProperties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); PropertyInfo idProperty = null; PropertyInfo relationProperty = null; foreach (var property in topLevelProperties) { if (excludedProperties != null && excludedProperties.Contains(property.Name)) { continue; } var propertyType = property.PropertyType; if ((propertyType.IsClass || propertyType.IsInterface) && propertyType != typeof(string)) { if (propertyType.IsArray) { manyChildrenProperties.Add((property, propertyType.GetElementType())); } else if (propertyType.IsGenericType && GenericCollectionTypes.Any(t => t == propertyType.GetGenericTypeDefinition())) { var genericType = propertyType.GetGenericArguments()[0]; if (genericType.IsClass && genericType != typeof(string)) { manyChildrenProperties.Add((property, propertyType.GetGenericArguments()[0])); } else { string genericTypeName = genericType.IsEnum ? typeof(string).Name : genericType.Name; int ind = propertyType.Name.IndexOf('`'); var propertyTypeName = $"{propertyType.Name.Substring(0, ind + 1)}{genericTypeName}"; collector.Columns.Add( new ColumnInfo { ColumnName = property.Name, ColumnType = propertyTypeName, }); valueProperties.Add(property); } } else { oneChildrenProperties.Add((property, propertyType)); } } else { if (idProperty == null && (property.Name == IdPropertyName || property.Name == idPropertyName)) { idProperty = property; } else { string propertyTypeName = propertyType.Name; if (propertyType.IsGenericType) { var genericType = propertyType.GetGenericArguments()[0]; string genericTypeName = genericType.IsEnum ? typeof(string).Name : genericType.Name; int ind = propertyTypeName.IndexOf('`'); propertyTypeName = $"{propertyTypeName.Substring(0, ind + 1)}{genericTypeName}"; } else if (propertyType.IsEnum) { propertyTypeName = typeof(string).Name; } if (property.Name == relationPropertyName) { relationProperty = property; } collector.Columns.Add( new ColumnInfo { ColumnName = property.Name, ColumnType = propertyTypeName, }); } valueProperties.Add(property); } } if (collector.Columns.Count > 0) { if (parentType != type) { if (parentIdPropertyName != null) { var parentIdPropertyInChild = type.GetProperty(parentIdPropertyName); if (parentIdPropertyInChild == null) { collector.Columns.Insert( 0, new ColumnInfo { ColumnName = parentIdPropertyName, ColumnType = parentIdPropertyTypeName, }); } } else if (valueProperties.Count > 0 && parentType != null && PropertiesMap[parentType].ValueProperties.Count > 0) { throw new InvalidOperationException( $"Type {typeName} must have any identificators that can be used to make relations to its parent type {parentType.Name}"); } } if (idProperty != null) { idPropertyName = parentType != null && parentType != type && PropertiesMap[parentType].OneChildrenProperties.Count > 1 ? idProperty.Name : IdPropertyName; collector.Columns.Insert( 0, new ColumnInfo { ColumnName = idPropertyName, ColumnType = idProperty.PropertyType.Name, }); } tablesStructure.Tables.Add(collector); } if (!PropertiesMap.ContainsKey(type)) { PropertiesMap.Add( type, new TypeData { ValueProperties = valueProperties, OneChildrenProperties = oneChildrenProperties.Select(i => i.Item1).ToList(), ManyChildrenProperties = manyChildrenProperties.Select(i => i.Item1).ToList(), ParentIdPropertyName = parentIdPropertyName, }); } return(new PropertiesProcessingResult { IdProperty = idProperty, RelationProperty = relationProperty, ValueProperties = valueProperties, OneChildrenProperties = oneChildrenProperties, ManyChildrenProperties = manyChildrenProperties.Select(i => i.Item2).ToList(), }); }