private void GenerateEnumerateCollectionContentCode(ExtendedType target, ILCodeParameter collectionParameter) { ArrayContainerTypeInfo arrayTypeInfo; if (target.TryGetArrayTypeInfo(out arrayTypeInfo) && arrayTypeInfo.Ranks > 1) { if (arrayTypeInfo.Ranks > 3) throw new NotSupportedException("The serialization engine is limited to 3 ranks in arrays"); _il.Snippets.ForLoop(0, new CallMethodILCode(collectionParameter, Members.ArrayGetLength, 0), 1, r0 => { _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorVisit, collectionParameter, Members.VisitArgsCollectionInCollection); _il.Snippets.ForLoop(0, new CallMethodILCode(collectionParameter, Members.ArrayGetLength, 1), 1, r1 => { if (arrayTypeInfo.Ranks > 2) { _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorVisit, collectionParameter, Members.VisitArgsCollectionInCollection); _il.Snippets.ForLoop(0, new CallMethodILCode(collectionParameter, Members.ArrayGetLength, 1), 1, r2 => GenerateEnumerateContentCode( new CallMethodILCode(collectionParameter, target.Ref.GetMethod("Get"), r0, r1, r2), LevelType.CollectionItem)); _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorLeave, collectionParameter, Members.VisitArgsCollectionInCollection); } else { GenerateEnumerateContentCode(new CallMethodILCode(collectionParameter, target.Ref.GetMethod("Get"), r0, r1), LevelType.CollectionItem); } }); _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorLeave, collectionParameter, Members.VisitArgsCollectionInCollection); }); } else { var part = new ILEnumerateCode(collectionParameter, (il, it) => GenerateEnumerateContentCode(it, LevelType.CollectionItem)); _il.Generate(part); } }
public CollectionMembers(ExtendedType collectionType) { ArrayContainerTypeInfo arrayTypeInfo; if (collectionType.TryGetArrayTypeInfo(out arrayTypeInfo)) { if (arrayTypeInfo.Ranks > 3) throw new NotSupportedException("The serialization engine is limited to 3 ranks in arrays"); if (arrayTypeInfo.Ranks == 3) { var baseType = typeof (ICollection<>); ElementType = baseType.MakeGenericType(baseType.MakeGenericType(arrayTypeInfo.ElementType)); ToArray = typeof (ArrayProvider).GetMethod("To3DArray").MakeGenericMethod(arrayTypeInfo.ElementType); } else if (arrayTypeInfo.Ranks == 2) { ElementType = typeof (ICollection<>).MakeGenericType(arrayTypeInfo.ElementType); ToArray = typeof(ArrayProvider).GetMethod("To2DArray").MakeGenericMethod(arrayTypeInfo.ElementType); } else { ElementType = arrayTypeInfo.ElementType; ToArray = typeof(ArrayProvider).GetMethod("ToArray").MakeGenericMethod(arrayTypeInfo.ElementType); } } else { ElementType = collectionType.Container.AsCollection().ElementType; } ElementTypeExt = ElementType.Extend(); VariableType = typeof (ICollection<>).MakeGenericType(ElementType); Add = VariableType.GetMethod("Add", new[] { ElementType }); var instanceType = collectionType.Ref.IsInterface || collectionType.Ref.IsArray ? typeof(List<>).MakeGenericType(ElementType) : collectionType.Ref; Constructor = instanceType.GetConstructor(Type.EmptyTypes); if (Constructor == null) throw InvalidGraphException.NoParameterLessConstructor(collectionType.Ref); }
public static void Resolve(Type type, string path, Action<PropertyInfo, ExtendedType> action) { var propertyNames = path.Split('.'); var containerType = type; foreach (var propertyName in propertyNames) { var property = containerType.GetProperty(propertyName); var extendedPropertyType = new ExtendedType(property.PropertyType); containerType = extendedPropertyType.Class == TypeClass.Collection ? extendedPropertyType.Container.AsCollection().ElementType : property.PropertyType; action(property, extendedPropertyType); } }
public DictionaryMembers(ExtendedType dictionaryType) { var container = dictionaryType.Container.AsDictionary(); KeyType = container.KeyType; ValueType = container.ValueType; ElementType = container.ElementType; VariableType = typeof (IDictionary<,>).MakeGenericType(KeyType, ValueType); Add = VariableType.GetMethod("Add", new[] {KeyType, ValueType}); var instanceType = dictionaryType.Ref.IsInterface ? typeof (Dictionary<,>).MakeGenericType(KeyType, ValueType) : dictionaryType.Ref; Constructor = instanceType.GetConstructor(Type.EmptyTypes); if (Constructor == null) throw InvalidGraphException.NoParameterLessConstructor(dictionaryType.Ref); }
public static bool TryGetComplexTypes(ExtendedType type, out Type[] types) { if (type.Class == TypeClass.Complex) { types = new[] { type.Ref }; return true; } if (type.Class == TypeClass.Nullable) { var elementType = type.Container.AsNullable().ElementType.Extend(); return TryGetComplexTypes(elementType, out types); } if (type.Class == TypeClass.Dictionary) { var container = type.Container.AsDictionary(); Type[] keyTypes; var hasKeyTypes = TryGetComplexTypes(container.KeyType.Extend(), out keyTypes); Type[] valueTypes; var hasValueTypes = TryGetComplexTypes(container.ValueType.Extend(), out valueTypes); if (!hasKeyTypes && !hasValueTypes) { types = null; return false; } if (hasKeyTypes && hasValueTypes) types = keyTypes.Concat(valueTypes).ToArray(); else if (hasKeyTypes) types = keyTypes; else types = valueTypes; return true; } if (type.Class == TypeClass.Collection) { var elementType = type.Container.AsCollection().ElementType.Extend(); return TryGetComplexTypes(elementType, out types); } types = null; return false; }
private ILCodeParameter GenerateCollectionContent(ExtendedType target, string refName) { var collectionMembers = new CollectionMembers(target); var isValueType = collectionMembers.ElementType.IsValueType; var collectionLocal = _il.DeclareLocal("collection", collectionMembers.VariableType); _il.Construct(collectionMembers.Constructor); _il.Cast(collectionMembers.VariableType); _il.Var.Set(collectionLocal); var valueLocal = DeclareCollectionItemLocal("cv", collectionMembers.ElementType); ; if (collectionMembers.ElementTypeExt.IsValueOrNullableOfValue()) { _il.Snippets.WhileLoop(il => { // While condition _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorTryVisitValue[collectionMembers.ElementType], Members.VisitArgsCollectionItem, valueLocal); var valueNotFoundLabel = _il.DefineLabel(); _il.TransferLongIfFalse(valueNotFoundLabel); if (isValueType) { _il.Snippets.InvokeMethod(valueLocal, Members.Nullable[collectionMembers.ElementType].GetHasValue); } else { _il.Snippets.AreEqual(valueLocal, ILCodeParameter.Null); _il.Negate(); } var isNullLabel = _il.DefineLabel(); _il.TransferLong(isNullLabel); _il.MarkLabel(valueNotFoundLabel); _il.LoadValue(0); _il.MarkLabel(isNullLabel); }, il => { _il.Var.Load(collectionLocal); GenerateLoadParamValueCode(valueLocal); _il.CallVirt(collectionMembers.Add); }); } else if (collectionMembers.ElementTypeExt.Class == TypeClass.Dictionary) { _il.Snippets.WhileLoop(il => { // Condition var callTryVisit = new CallMethodILCode(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsDictionaryInCollection); _il.Snippets.AreEqual(callTryVisit, (int)ValueState.Found); }, il => { var contentParam = GenerateDictionaryEnumerateCode(collectionMembers.ElementType, refName); _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsDictionaryInCollection); _il.Snippets.InvokeMethod(collectionLocal, collectionMembers.Add, contentParam); }); } else if (collectionMembers.ElementTypeExt.Class == TypeClass.Collection) { _il.Snippets.WhileLoop(il => { // Condition var callTryVisit = new CallMethodILCode(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsCollectionInCollection); _il.Snippets.AreEqual(callTryVisit, (int)ValueState.Found); }, il => { var contentParam = GenerateCollectionContent(collectionMembers.ElementTypeExt, refName); _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsCollectionInCollection); _il.Snippets.InvokeMethod(collectionLocal, collectionMembers.Add, contentParam); }); } else { _il.Snippets.WhileLoop(il => { var callTryVisit = new CallMethodILCode(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsCollectionItem); _il.Snippets.AreEqual(callTryVisit, (int)ValueState.Found); }, il => { GenerateCreateAndChildCallCode(valueLocal); _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsCollectionItem); _il.Snippets.InvokeMethod(collectionLocal, collectionMembers.Add, valueLocal); }); } if (target.Ref.IsArray) return new CallMethodILCode(collectionMembers.ToArray, collectionLocal); return collectionLocal; }
private TypeReflectionContext(Type type) { _type = type; _extended = type.Extend(); _properties = new Lazy<IList<PropertyReflectionContext>>(() => ParseProperties(type)); }
private ILCodeParameter GetContentVisitArgs(ExtendedType type, LevelType level) { if (!type.IsValueOrNullableOfValue()) { if (type.Class == TypeClass.Dictionary) { if (level == LevelType.DictionaryKey) return Members.VisitArgsDictionaryInDictionaryKey; if (level == LevelType.DictionaryValue) return Members.VisitArgsDictionaryInDictionaryValue; return Members.VisitArgsDictionaryInCollection; } if (type.Class == TypeClass.Collection) { if (level == LevelType.DictionaryKey) return Members.VisitArgsCollectionInDictionaryKey; if (level == LevelType.DictionaryValue) return Members.VisitArgsCollectionInDictionaryValue; return Members.VisitArgsCollectionInCollection; } } if (level == LevelType.DictionaryKey) return Members.VisitArgsDictionaryKey; if (level == LevelType.DictionaryValue) return Members.VisitArgsDictionaryValue; return Members.VisitArgsCollectionItem; }
public SerializableProperty(PropertyInfo @ref, SerializationMetadata metadata) { _ref = @ref; _metadata = metadata; _ext = _ref.PropertyType.Extend(); }