public void GenerateCode(JsonRoot root, TextWriter writer) { CodeCompileUnit result = new CodeCompileUnit(); result.Namespaces.Add(new CodeNamespace()); GenerateType(result.Namespaces[0], root, new List<string>()); CodeDomProvider provider = CodeDomProvider.CreateProvider(this.language); CodeGeneratorOptions options = new CodeGeneratorOptions(); options.BracingStyle = "C"; provider.GenerateCodeFromCompileUnit(result, writer, options); }
private bool CanMergeIntoUserDefinedType(JsonRoot other, out JsonRoot mergedType) { bool sameAsThis = true; mergedType = null; Dictionary<string, JsonRoot> members = new Dictionary<string, JsonRoot>(); foreach (var memberName in this.Members.Keys.Union(other.Members.Keys)) { if (this.Members.ContainsKey(memberName) && other.Members.ContainsKey(memberName)) { JsonRoot member1 = this.Members[memberName]; JsonRoot member2 = other.Members[memberName]; JsonRoot merged; if (!member1.CanMerge(member2, out merged)) { return false; } else { if (merged != member1) { sameAsThis = false; } members.Add(memberName, merged); } } else if (this.Members.ContainsKey(memberName)) { members.Add(memberName, this.Members[memberName]); } else { sameAsThis = false; members.Add(memberName, other.Members[memberName]); } } if (sameAsThis) { mergedType = this; } else { mergedType = new JsonRoot(this.UserDefinedTypeName, this.ArrayRank, members); } return true; }
private bool CanMergeIntoPrimitiveType(JsonRoot other, out JsonRoot mergedType) { if (this.ElementType == other.ElementType) { mergedType = this; return true; } bool isThisNullable = this.IsNullableType(); bool isOtherNullable = other.IsNullableType(); Type thisElementType = this.ElementType != null && this.ElementType.IsGenericType && this.ElementType.GetGenericTypeDefinition() == typeof(Nullable<>) ? this.ElementType.GetGenericArguments()[0] : this.ElementType; Type otherElementType = other.ElementType != null && other.ElementType.IsGenericType && other.ElementType.GetGenericTypeDefinition() == typeof(Nullable<>) ? other.ElementType.GetGenericArguments()[0] : other.ElementType; if (thisElementType == otherElementType) { // one nullable, the other not if (isThisNullable) { mergedType = this; } else { mergedType = other; } return true; } if (thisElementType == null) { if (isOtherNullable || otherElementType == typeof(string)) { mergedType = other; return true; } mergedType = new JsonRoot(typeof(Nullable<>).MakeGenericType(otherElementType), this.ArrayRank); return true; } if (otherElementType == null) { if (isThisNullable || thisElementType == typeof(string)) { mergedType = this; return true; } mergedType = new JsonRoot(typeof(Nullable<>).MakeGenericType(thisElementType), this.ArrayRank); return true; } // Number coercions if (this.ElementType == typeof(int)) { if (other.ElementType == typeof(long) || other.ElementType == typeof(double)) { mergedType = other; if (!mergedType.IsNullableType() && isThisNullable) { mergedType = new JsonRoot(typeof(Nullable<>).MakeGenericType(mergedType.ElementType), mergedType.ArrayRank); } return true; } } else if (this.ElementType == typeof(long)) { if (other.ElementType == typeof(double)) { mergedType = other; if (!mergedType.IsNullableType() && isThisNullable) { mergedType = new JsonRoot(typeof(Nullable<>).MakeGenericType(mergedType.ElementType), mergedType.ArrayRank); } return true; } } mergedType = null; return false; }
private bool CanMergeInto(JsonRoot other, out JsonRoot mergedType) { if (this.IsUserDefinedType) { return this.CanMergeIntoUserDefinedType(other, out mergedType); } else { return this.CanMergeIntoPrimitiveType(other, out mergedType); } }
private bool CanMerge(JsonRoot other, out JsonRoot mergedType) { mergedType = null; if (this.ArrayRank != other.ArrayRank) { return false; } if (this.IsUserDefinedType != other.IsUserDefinedType) { return false; } if (this.CanMergeInto(other, out mergedType)) { return true; } if (other.CanMergeInto(this, out mergedType)) { return true; } return false; }
private static JsonRoot ParseJObjectIntoDataContract(JObject root, string rootTypeName) { Dictionary<string, JsonRoot> fields = new Dictionary<string, JsonRoot>(); foreach (JProperty property in root.Properties()) { JsonRoot fieldType = ParseJsonIntoDataContract(property.Value, property.Name); fields.Add(property.Name, fieldType); } JsonRoot result = new JsonRoot(rootTypeName, 0, fields); foreach (var field in fields.Values) { field.Parent = result; } return result; }
private string GenerateType(CodeNamespace ns, JsonRoot root, List<string> existingTypes) { if (!root.IsUserDefinedType) return null; CodeTypeDeclaration rootType = new CodeTypeDeclaration(GetUniqueDataContractName(root.UserDefinedTypeName, existingTypes)); existingTypes.Add(rootType.Name); rootType.Attributes = MemberAttributes.Public; rootType.IsPartial = true; rootType.IsClass = true; ns.Types.Add(rootType); rootType.Comments.Add( new CodeCommentStatement( string.Format( "Type created for JSON at {0}", string.Join(" --> ", root.GetAncestors())))); AddAttributeDeclaration(rootType, rootType.Name, root.UserDefinedTypeName); AddMembers(ns, rootType, root, existingTypes); return rootType.Name; }
private void AddMembers(CodeNamespace ns, CodeTypeDeclaration typeDecl, JsonRoot jsonRoot, List<string> existingTypes) { foreach (var memberName in jsonRoot.Members.Keys) { string fieldName = EscapeFieldName(memberName); var member = jsonRoot.Members[memberName]; CodeTypeReference fieldType; if (member.IsUserDefinedType) { string fieldTypeName = this.GenerateType(ns, member, existingTypes); fieldType = new CodeTypeReference(fieldTypeName); } else { fieldType = new CodeTypeReference(member.ElementType ?? typeof(object)); } for (int i = 0; i < member.ArrayRank; i++) { fieldType = new CodeTypeReference(fieldType, 1); } // TODO: implement members as properties instead of fields CodeMemberField field = new CodeMemberField(fieldType, fieldName); field.Attributes = MemberAttributes.Public; typeDecl.Members.Add(field); this.AddMemberAttributeDeclaration(field, memberName); } }