C# DAO to DTO tool class
thought
DAO (Data Access Object) data access object is the object we transfer when doing structured database access. Through this object we can establish a mapping relationship with the tables in the database
DTO (Data Transfer Object) is the object we pass when exchanging data with the front end
Why do we need to set these two objects?
- For data security
If we directly pass the DAO data, we may strip away the entire database. For example, if a user’s data, including the user’s ID, user account, password, etc., is passed directly to the front end, the user’s password may be Once captured by the packet capture software, the user account may be stolen later. In order to prevent this situation, we directly replace the data from the backend - In addition to DTO, we will even set up an intermediate model when exchanging certain data with the database on some backends instead of using DAO directly. Because some database tables have too many fields, when we conduct business There may not be so many fields used, so some truncation will be performed
Convert ideas
Since we need to convert here, properties of both basic types and reference types can be converted, so I thought of using reflection
Steps:
- Get all public properties of the source object
- Create a dictionary, the Key value of the dictionary is the name of the public attribute of the source object, and the value of the dictionary is the value of the public attribute of the source object
- Create an object of the target class and obtain all public attributes of the target class
- Get the value of the source object attribute based on the target attribute name, and set the value of the target attribute
code implementation
source type
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Model.Entity
{
public class User
{
public int UserId { get; set; }
// QQ mailbox
public string QQEmail { get; set; }
// Nick name
public string Nickname { get; set; }
// password
public string Password { get; set; }
//User status 0: means online 1: means offline 2: means in battle, -1: means login is prohibited
public int Status { get; set; }
// Whether it is an administrator 0: No 1: Yes
public bool IsAdmin { get; set; }
//User's avatar
public string AvatarUrl { get; set; }
//Number of games won
public int WinNumber { get; set; }
//Number of failed games
public int LoseNumber { get; set; }
//The number of draws
public int DrawNumber { get; set; }
//ranking
public int RankNumber { get; set; }
//Creation time
public DateTime CreateTime { get; set; }
// Change the time
public DateTime UpdateTime { get; set; }
}
}
target type
namespace gobangBack.DTO
{
public record UserDTO
{
public int UserId { get; set; }
// QQ mailbox
public string QQEmail { get; set; }
// Nick name
public string Nickname { get; set; }
//User status 0: means online 1: means offline 2: means in battle, -1: means login is prohibited
public int Status { get; set; }
// Whether it is an administrator 0: No 1: Yes
public bool IsAdmin { get; set; }
//User's avatar
public string AvatarUrl { get; set; }
//Number of games won
public int WinNumber { get; set; }
//Number of failed games
public int LoseNumber { get; set; }
//The number of draws
public int DrawNumber { get; set; }
//ranking
public int RankNumber { get; set; }
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Tool
{
// Convert parameter Param to Target type
public static class TypeExtract
{
///
/// Convert the corresponding type to the type we want to convert
///
///
///
public static T TransformToTargetBased(E source,Type target,bool ignoreNull=false) where T:new()
{
// 1. Obtain all public attributes of the source class
PropertyInfo[] sourceInfos = source.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
// 2. Convert it into a dictionary with Key: attribute name, Value: attribute value
Dictionary sourceDictionary = new Dictionary();
foreach (PropertyInfo sourceInfo in sourceInfos)
{
sourceDictionary[sourceInfo.Name] = sourceInfo.GetValue(source);
}
// 3. Get all the properties of our target type
T targetObj = new T();
PropertyInfo[] targetInfos = targetObj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
// 4. Reprint the value of the source object to the target object
foreach (PropertyInfo targetInfo in targetInfos) {
// 5. Determine whether to ignore null values
if(ignoreNull)
{
// 6. If the null value is ignored, omit it if the value is null.
if(sourceDictionary[targetInfo.Name] != null)
{
targetInfo.SetValue(targetObj, sourceDictionary[targetInfo.Name]);
}
continue;
}
else
{
// 7.1. First determine whether the target's class attribute name is in our dictionary, and only assign the value if it is.
if(sourceDictionary.ContainsKey(targetInfo.Name))
targetInfo.SetValue(targetObj, sourceDictionary[targetInfo.Name]);
}
}
return targetObj;
}
}
}
Finally I will write another Api to test it
[HttpGet]
public UserDTO Get() {
User user = context.Users.Where(u => u.UserId == 1).Single();
UserDTO usreDto = TypeExtract.TransformToTargetBased(user,new UserDTO().GetType());
return usreDto;
}
Haha, successful. I have tested this tool class. Not only the basic types can be converted, but the attributes inside can also be converted if they are reference types. If you have a better method, I hope you can share it, thank you!