/// <summary> /// read data from DTO back to POCO. /// NOTE: does not manage array / enumerations as yet /// </summary> /// <param name="code"></param> private void GenerateReadFromDTO(StringBuilder code) { code.IndentLine(2, $"public static {_poco.Name} ReadFromDTO({_poco.Name} target, {_poco.Name}DTO source)"); code.IndentLine(2, "{"); foreach (Tuple <MemberInfo, MemberInfo> item in _members) { MemberInfo member = item.Item1; Type memberType = GetDataType(member); MemberInfo sibling = item.Item2; if (memberType.IsArray && memberType != typeof(string)) { Type elementType = memberType.GetElementType(); if (elementType != null) { // use TX for exported type to deep copy if (ExportedTypes.Contains(elementType)) { code.IndentLine(3, $"target.{member.Name} = source.{ConflateType(sibling)}{member.Name}.Select({elementType}TX.WriteToDTO).ToArray(),"); } else { code.IndentLine(3, $"target.{member.Name} = source.{ConflateType(sibling)}{member.Name}.Select().ToArray(),"); } } } else if (!memberType.IsArray && memberType != typeof(string) && typeof(IEnumerable).IsAssignableFrom(memberType)) { code.IndentLine(3, $"Read{member.Name}FromDTO(target.{ConflateType(sibling)}{member.Name}, source.{member.Name});"); } else if (ExportedTypes.Contains(memberType)) { code.IndentLine(3, $"{memberType.Name}TX.ReadFromDTO(target.{ConflateType(sibling)}{member.Name}, source.{member.Name});"); } else { code.IndentLine(3, $"target.{ConflateType(sibling)}{member.Name} = source.{member.Name};"); } } code.IndentLine(3, "return target;"); code.IndentLine(2, "}"); code.AppendLine(); // write methods to copy colections foreach (Tuple <MemberInfo, MemberInfo> item in _members) { MemberInfo member = item.Item1; Type memberType = GetDataType(member); if (!memberType.IsArray && memberType != typeof(string) && typeof(IEnumerable).IsAssignableFrom(memberType)) { GenerateCopyCollection(code, member); } } }
/// <summary> /// convert existing class reference to equiv DTO for non conflated members /// </summary> /// <param name="type"></param> /// <returns></returns> private string ConvertToDTOType(Type type) { if (ExportedTypes.Contains(type)) { return(type.Name + "DTO"); } return(CleanTypeName(type)); }
/// <summary> /// convert c# type to TS /// </summary> /// <param name="type"></param> /// <returns></returns> private string ConvertToTsType(Type type) { while (true) { if (type != null && type.IsPrimitive) { if (type == typeof(bool)) { return("boolean"); } return(type == typeof(char) ? "string" : "number"); } if (type == typeof(decimal)) { return("number"); } if (type == typeof(string)) { return("string"); } if (type != null && type.IsArray) { Type at = type.GetElementType(); return(ConvertToTsType(at) + "[]"); } if (typeof(IEnumerable).IsAssignableFrom(type)) { if (type != null) { Type collectionType = type.GetGenericArguments()[0]; // all my enumerables are typed, so there is a generic argument return(ConvertToTsType(collectionType) + "[]"); } } if (type != null && Nullable.GetUnderlyingType(type) != null) { type = Nullable.GetUnderlyingType(type); continue; } if (type != null && type.IsEnum) { return("number"); } if (type != null) { return(ExportedTypes.Contains(type) ? type.Name : "any"); } } }
/// <summary> /// read through members and build a list, conflating as appropriate /// </summary> /// <param name="target"></param> /// <param name="sibling"></param> private void AnalyseFields(Type target, MemberInfo sibling) { // scan through properties and fields of target type // if this is the main class then do not check for existing fields foreach (MemberInfo member in GetMembers(target)) { // do we already have this field (or is it part of parent // and we are going to deal with it later)? if (sibling != null && _existingMembers.Any(mi => mi.Name == member.Name)) { Log.AppendLine($" field '{member.Name}' ignored as it already exists;"); continue; } // ReSharper disable once SwitchStatementMissingSomeCases (we are not interested in other member types) switch (member.MemberType) { case MemberTypes.Field: // short cut field FieldInfo fieldInfo = (FieldInfo)member; // see if this is a sibling object if (ExportedTypes.Contains(fieldInfo.FieldType) && IsConflated(member)) { AnalyseFields(fieldInfo.FieldType, member); continue; } break; case MemberTypes.Property: // short cut field PropertyInfo propertyInfo = (PropertyInfo)member; // see if this is a sibling object if (ExportedTypes.Contains(propertyInfo.PropertyType) && IsConflated(member)) { AnalyseFields(propertyInfo.PropertyType, member); continue; } break; default: continue; } _members.Add(new Tuple <MemberInfo, MemberInfo>(member, sibling)); } }
/// <summary> /// copy data from POCO to new DTO and manage conflation /// </summary> /// <param name="code"></param> private void GenerateWriteToDTO(StringBuilder code) { code.IndentLine(2, $"public static {_poco.Name}DTO WriteToDTO({_poco.Name} source)"); code.IndentLine(2, "{"); code.IndentLine(3, $"return new {_poco.Name}DTO"); code.IndentLine(4, "{"); foreach (Tuple <MemberInfo, MemberInfo> item in _members) { MemberInfo member = item.Item1; Type memberType = GetDataType(member); MemberInfo sibling = item.Item2; if (memberType.IsArray) { Type elementType = memberType.GetElementType(); if (elementType != null) { // use TX for exported type to deep copy if (ExportedTypes.Contains(elementType)) { code.IndentLine(5, $"{member.Name} = source.{ConflateType(sibling)}{member.Name}.Select({elementType}TX.WriteToDTO).ToArray(),"); } else { code.IndentLine(5, $"{member.Name} = source.{ConflateType(sibling)}{member.Name}.Select().ToArray(),"); } continue; } } if (memberType != typeof(string) && typeof(IEnumerable).IsAssignableFrom(memberType)) { // use TX for exported type to deep copy MemberInfo elementType = memberType.GetGenericArguments()[0]; if (ExportedTypes.Contains(elementType)) { code.IndentLine(5, $"{member.Name} = source.{ConflateType(sibling)}{member.Name}.Select({elementType.Name}TX.WriteToDTO).ToArray(),"); } else { code.IndentLine(5, $"{member.Name} = source.{ConflateType(sibling)}{member.Name}.Select().ToArray()"); } continue; } if (ExportedTypes.Contains(memberType)) { code.IndentLine(5, $"{member.Name} = {ConflateType(sibling)}{member.Name}TX.WriteToDTO(source.{member.Name}),"); } else { code.IndentLine(5, $"{member.Name} = source.{ConflateType(sibling)}{member.Name},"); } } code.IndentLine(4, "};"); code.IndentLine(2, "}"); code.AppendLine(""); }