private void GenerateDictionaryCode(ILCodeVariable dictionary, Type elementType) { var enumerateCode = new ILEnumerateCode(dictionary, (il, it) => { GenerateEnumerateContentCode(new InstancePropertyILCodeVariable(it, elementType.GetProperty("Key")), LevelType.DictionaryKey); GenerateEnumerateContentCode(new InstancePropertyILCodeVariable(it, elementType.GetProperty("Value")), LevelType.DictionaryValue); }); _il.Generate(enumerateCode); }
private void GenerateEnumerateContentCode(ILCodeParameter valueParam, LevelType level) { var type = valueParam.ParameterType; var extType = _il.TypeCache.Extend(type); var visitArgs = GetContentVisitArgs(extType, level); if (extType.IsValueOrNullableOfValue()) { _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorVisitValue[type], valueParam.AsNullable(), visitArgs); } else if (extType.Class == TypeClass.Dictionary) { var container = extType.Container.AsDictionary(); var elementType = container.ElementType; var dictionaryType = container.DictionaryInterfaceType; var dictionaryLocal = _il.DeclareLocal("dictionary", dictionaryType); _il.Snippets.SetVariable(dictionaryLocal, valueParam.Cast(dictionaryType)); _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorVisit, dictionaryLocal, visitArgs); var part = new ILEnumerateCode(dictionaryLocal, (il, it) => { GenerateEnumerateContentCode(new InstancePropertyILCodeVariable(it, elementType.GetProperty("Key")), LevelType.DictionaryKey); GenerateEnumerateContentCode(new InstancePropertyILCodeVariable(it, elementType.GetProperty("Value")), LevelType.DictionaryValue); }); _il.Generate(part); _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorLeave, dictionaryLocal, visitArgs); } else if (extType.Class == TypeClass.Collection) { var container = extType.Container.AsCollection(); var collectionType = type.IsArray && extType.Container.AsArray().Ranks > 1 ? type : container.CollectionInterfaceType; var collectionLocal = _il.DeclareLocal("collection", collectionType); _il.Snippets.SetVariable(collectionLocal, valueParam.Cast(collectionType)); _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorVisit, collectionLocal, visitArgs); GenerateEnumerateCollectionContentCode(extType, collectionLocal); _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorLeave, collectionLocal, visitArgs); } else { _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorVisit, valueParam, visitArgs); GenerateChildCall(valueParam); _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorLeave, valueParam, visitArgs); } }
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); } }