ASP.NET Core-自动映射

1.安装NuGet包AutoMapper

2.建立示例Entity、Dto

Entity

 public class User 
 {
     public long Id { get; set; }
     /// <summary>
     /// 账号
     /// </summary>
     public string UserName { get; set; }

     /// <summary>
     /// 名字
     /// </summary>
     public string Name { get; set; }

     public string Password { get; set; }

     /// <summary>
     /// 用户是否锁定
     /// </summary>
     public bool IsLockoutEnabled { get; set; }

     public string PhoneNumber { get; set; }

 }

Dto

 public class UserDto
 {
     public string UserName { get; set; }

     /// <summary>
     /// 名字
     /// </summary>
     public string Name { get; set; }

     public string Password { get; set; }

     /// <summary>
     /// 用户是否锁定
     /// </summary>
     [PropertyMapper(SourceName = "IsLockoutEnabled")]
     public bool IsLock { get; set; }

     public string PhoneNumber { get; set; }
 }

 

3.配置映射关系-AutoMapperMappingProfile

/// <summary>
/// 这里的 Profile作用是Program中services.AddAutoMapper时它会自动找到所有继承了Profile的类然后进行配置
/// </summary>
public class AutoMapperMappingProfile:Profile
{
    public AutoMapperMappingProfile() {
        CreateMap<User, UserDto>().ReverseMap();//ReverseMap双向映射
    }

}

注:默认是字段同名自动映射,若字段不同名则需要设定映射规则

 

4.Program.cs中注入映射服务

builder.Services.AddAutoMapper(typeof(AutoMapperMappingProfile));

 

5.使用

[ApiController]
[Route("[controller]")]
public class UserController(IUserService userService,IMapper mapper) : ControllerBase
{
    
    [HttpGet("GetSingleUserInfo")]
    public async Task<UserDto> GetSingleUserInfo(string account)
    {
        var info= await userService.GetSingleUserInfo(account);
        return mapper.Map<UserDto>(info);
    }
}

 

映射配置改进

针对以上的映射来说,每次有新的映射关系都需要到AutoMapperMappingProfile配置文件中配置,这种方式操作起来显得繁琐,还可能会遗忘,为了方便操作,做了以下改进,让每一个映射关系自动加入到配置中

1.建立特性PropertyMapperAttribute

 /// <summary>
 /// ValidOn 规定特性可被使用的范围它是枚举器 AttributeTargets的值的组合。默认值是 AttributeTargets.All表示在所有元素都可使用。如果只允许在类或者属性上使用可以定义:AttributeTargets.Class或者AttributeTargets.Property
 /// AllowMultiple(可选的)bool类型。如果为 true,则该特性是多用的。默认值是 false(单用的)
 /// Inherited(可选的)bool类型。如果为 true,则该特性可被派生类继承。默认值是 false(不被继承)
 /// </summary>
 [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
 public class PropertyMapperAttribute:Attribute
 {
     public string SourceName { get; set; }
     //public Type SourceType { get; set; }
 }

 

2.在需要映射的Dto中添加特性

AutoMapAttribute,AutoMapper包自带的特性用于明确映射对象,添加至类中

PropertyMapperAttribute,用于属性的特性,本次用来表明映射的字段(当映射双方字段不相同时)

[AutoMap(typeof(User))]
public class UserDto
{
    public string UserName { get; set; }

    /// <summary>
    /// 名字
    /// </summary>
    public string Name { get; set; }

    public string Password { get; set; }

    /// <summary>
    /// 用户是否锁定
    /// </summary>
    [PropertyMapper(SourceName = "IsLockoutEnabled")]
    public bool IsLock { get; set; }

    public string PhoneNumber { get; set; }
}

 

3.映射配置文件改进-BatchAutoMapperProfile

/// <summary>
/// 自动添加映射配置(需使用特性AutoMapAttribute的DTO)
/// </summary>
public class BatchAutoMapperProfile:Profile
{
    public BatchAutoMapperProfile()
    {
        InitMapper();
    }

    private void InitMapper()
    {//寻找应用中所有包含TestApp(应用名称)的程序集,且找程序集中名称中带Dto的类
        var allTypeses = AppDomain.CurrentDomain.GetAssemblies().Where(a => a.FullName.Contains("TestApp")).SelectMany(a => a.GetTypes()).Where(a=>a.Name.Contains("Dto")).ToArray();//.Where(a => a.FullName.Contains("PlantAtlas.Interface")|| a.FullName.Contains("PlantAtlas.Server")).ToArray();

        //类映射配置
        var typeList =allTypeses.Where(t=>t.GetCustomAttributes(typeof(AutoMapAttribute)).Any()).ToList();//过滤类中带有AutoMapAttribute特性标签的类
        typeList.ForEach(type =>
        {
            var attribute = (type.GetCustomAttributes(typeof(AutoMapAttribute)).FirstOrDefault());
            if (attribute != null)
            {
                var a = (AutoMapAttribute)attribute;
                if (a.SourceType == null) return;
                var mapper = CreateMap(a.SourceType, type);//.ReverseMap();
                //类属性映射配置
                var propertyList = type.GetProperties().Where(t => t.GetCustomAttributes(typeof(PropertyMapperAttribute)).Any()).ToList();//过滤出带有PropertyMapperAttribute特性的属性做特殊映射
                propertyList.ForEach(pro =>
                {
                    var property = pro.GetCustomAttributes<PropertyMapperAttribute>().FirstOrDefault();
                    if (property != null && !string.IsNullOrEmpty(property.SourceName))
                    {
                        mapper.ForMember(pro.Name, src => src.MapFrom(property.SourceName));
                    }
                });
                mapper.ReverseMap();//ReverseMap表示双向映射
            }
        });
        
    }
}

 

4.Program.cs中注入映射服务

//自动映射
builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());

注:AddAutoMapper中传入的参数表明是那个范围内找所有继承了Profile的类然后进行配置

 

posted @ 2024-07-17 12:22  流年sugar  阅读(24)  评论(0编辑  收藏  举报