using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using AutoMapper;
using Dpz.Core.Entity.Base.MapperConfig;
using Dpz.Core.EnumLibrary;
using Dpz.Core.Public.Entity;
namespace Dpz.Core.Public.ViewModel;
/// <summary>
/// 评论 出参
/// </summary>
public class CommentViewModel : IHaveCustomMapping
{
public required string Id { get; set; }
/// <summary>
/// 评论类型
/// </summary>
public CommentNode Node { get; set; }
/// <summary>
/// 关联
/// </summary>
public required string Relation { get; set; }
/// <summary>
/// 回复时间
/// </summary>
public DateTime PublishTime { get; set; }
/// <summary>
/// 评论人 (多态)分为匿名评论和成员评论
/// </summary>
[JsonConverter(typeof(CommenterConverter))]
public required VmCommenter Commenter { get; set; }
/// <summary>
/// 回复内容
/// </summary>
public required string CommentText { get; set; }
/// <summary>
/// 回复ID
/// </summary>
public List<string> Replies { get; set; } = [];
/// <summary>
/// 是否删除
/// </summary>
public required bool IsDelete { get; set; }
/// <summary>
/// 回复
/// </summary>
public List<CommentChildren> Children { get; set; } = [];
public static void CreateMappings(MapperConfigurationExpression cfg)
{
var mapper = new Mapper(
new MapperConfiguration(x =>
{
x.CreateMap<MembleCommenter, VmMemberCommenter>();
x.CreateMap<GuestCommenter, VmGuestCommenter>();
})
);
cfg.CreateMap<Comment, CommentViewModel>()
.ConvertUsing(
(entity, _) =>
{
if (entity.IsDelete)
{
entity.Commenter = new GuestCommenter
{
Email = "",
NickName = "该用户发言已被删除",
Site = "",
};
entity.CommentText = "该用户发言因某些原因已被删除";
}
var viewModel = new CommentViewModel
{
Id = entity.Id.ToString(),
Node = entity.Node,
Relation = entity.Relation,
PublishTime = entity.PublishTime.ToLocalTime(),
CommentText = entity.CommentText,
Replies = entity.Replies.Select(x => x.ToString()).ToList(),
IsDelete = entity.IsDelete,
Children = new List<CommentChildren>(),
Commenter = entity.Commenter switch
{
MembleCommenter membleCommenter => mapper.Map<VmMemberCommenter>(
membleCommenter
),
GuestCommenter guestCommenter => mapper.Map<VmGuestCommenter>(
guestCommenter
),
_ => throw new NotSupportedException(
$"not supported commenter type:{entity.Commenter.GetType().Name}"
),
},
};
return viewModel;
}
);
}
}
public class CommentChildren : IHaveCustomMapping
{
public required string Id { get; set; }
/// <summary>
/// 回复时间
/// </summary>
public DateTime PublishTime { get; set; }
/// <summary>
/// 评论人
/// </summary>
[JsonConverter(typeof(CommenterConverter))]
public required VmCommenter Commenter { get; set; }
/// <summary>
/// 回复内容
/// </summary>
public required string CommentText { get; set; }
/// <summary>
/// 回复ID
/// </summary>
public List<string> Replies { get; set; } = [];
/// <summary>
/// 是否删除
/// </summary>
public required bool IsDelete { get; set; }
public static void CreateMappings(MapperConfigurationExpression cfg)
{
var mapper = new Mapper(
new MapperConfiguration(x =>
{
x.CreateMap<MembleCommenter, VmMemberCommenter>();
x.CreateMap<GuestCommenter, VmGuestCommenter>();
})
);
cfg.CreateMap<Comment, CommentChildren>()
.ConvertUsing(
(entity, _) =>
{
if (entity.IsDelete)
{
entity.Commenter = new GuestCommenter
{
Email = "",
NickName = "该用户发言已被删除",
Site = "",
};
entity.CommentText = "该用户发言因某些原因已被删除";
}
var viewModel = new CommentChildren
{
Id = entity.Id.ToString(),
PublishTime = entity.PublishTime.ToLocalTime(),
CommentText = entity.CommentText,
Replies = entity.Replies.Select(x => x.ToString()).ToList(),
IsDelete = entity.IsDelete,
Commenter = entity.Commenter switch
{
MembleCommenter membleCommenter => mapper.Map<VmMemberCommenter>(
membleCommenter
),
GuestCommenter guestCommenter => mapper.Map<VmGuestCommenter>(
guestCommenter
),
_ => throw new NotSupportedException(
$"not supported commenter type:{entity.Commenter.GetType().Name}"
),
},
};
return viewModel;
}
);
}
}
public abstract class VmCommenter
{
/// <summary>
/// 昵称
/// </summary>
public required string NickName { get; set; }
}
/// <summary>
/// 登录会员评论
/// </summary>
public class VmMemberCommenter : VmCommenter, IMapFrom<MembleCommenter>
{
/// <summary>
/// 头像
/// </summary>
public required string Avatar { get; set; }
/// <summary>
/// 身份标识
/// </summary>
public required string Identity { get; set; }
}
/// <summary>
/// 匿名评论
/// </summary>
public class VmGuestCommenter(string email) : VmCommenter, IMapFrom<GuestCommenter>
{
/// <summary>
/// 网站
/// </summary>
public string? Site { get; set; }
/// <summary>
/// 邮箱MD5
/// </summary>
public string EmailMd5 => email.GenerateHashMd5();
/// <summary>
/// 获取邮箱
/// </summary>
public string GetEmail() => email;
}
public class CommenterConverter : JsonConverter<VmCommenter>
{
public override VmCommenter? Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options
)
{
if (reader.TokenType == JsonTokenType.Null)
{
return null;
}
if (reader.TokenType != JsonTokenType.StartObject)
{
throw new JsonException("JsonTokenType.StartObject not found.");
}
if (
!reader.Read()
|| reader.TokenType != JsonTokenType.PropertyName
|| reader.GetString() != "$type"
)
{
throw new JsonException("Property $type not found.");
}
if (!reader.Read() || reader.TokenType != JsonTokenType.String)
{
throw new JsonException("Value at $type is invalid.");
}
var typeStr = reader.GetString();
var type = typeStr switch
{
"GuestCommenter" => typeof(VmGuestCommenter),
"MemberCommenter" => typeof(VmMemberCommenter),
_ => typeof(Commenter),
};
using var output = new MemoryStream();
ReadObject(ref reader, output, options);
var result = JsonSerializer.Deserialize(output.ToArray(), type, options);
return result as VmCommenter;
}
private void ReadObject(ref Utf8JsonReader reader, Stream output, JsonSerializerOptions options)
{
using var writer = new Utf8JsonWriter(
output,
new JsonWriterOptions { Encoder = options.Encoder, Indented = options.WriteIndented }
);
writer.WriteStartObject();
var objectIntend = 0;
while (reader.Read())
{
switch (reader.TokenType)
{
case JsonTokenType.None:
case JsonTokenType.Null:
writer.WriteNullValue();
break;
case JsonTokenType.StartObject:
writer.WriteStartObject();
objectIntend++;
break;
case JsonTokenType.EndObject:
writer.WriteEndObject();
if (objectIntend == 0)
{
writer.Flush();
return;
}
objectIntend--;
break;
case JsonTokenType.StartArray:
writer.WriteStartArray();
break;
case JsonTokenType.EndArray:
writer.WriteEndArray();
break;
case JsonTokenType.PropertyName:
writer.WritePropertyName(reader.GetString() ?? "");
break;
case JsonTokenType.Comment:
writer.WriteCommentValue(reader.GetComment());
break;
case JsonTokenType.String:
writer.WriteStringValue(reader.GetString());
break;
case JsonTokenType.Number:
writer.WriteNumberValue(reader.GetInt32());
break;
case JsonTokenType.True:
case JsonTokenType.False:
writer.WriteBooleanValue(reader.GetBoolean());
break;
default:
throw new ArgumentOutOfRangeException();
}
}
}
public override void Write(
Utf8JsonWriter writer,
VmCommenter value,
JsonSerializerOptions options
)
{
writer.WriteStartObject();
var valueType = value.GetType();
//var valueAssemblyName = valueType.Assembly.GetName();
writer.WriteString("$type", $"{valueType.Name.Replace("Vm", "")}");
var json = JsonSerializer.Serialize(value, value.GetType(), options);
using (
var document = JsonDocument.Parse(
json,
new JsonDocumentOptions
{
AllowTrailingCommas = options.AllowTrailingCommas,
MaxDepth = options.MaxDepth,
}
)
)
{
foreach (var jsonProperty in document.RootElement.EnumerateObject())
{
jsonProperty.WriteTo(writer);
}
}
writer.WriteEndObject();
}
}
⚠⚠ 以下内容为AI分析的结果,请根据实际情况进行判断。
上述代码定义了一个用于处理评论的视图模型(ViewModel)及其相关类,主要用于将评论数据从实体模型转换为适合前端展示的格式。以下是代码的主要功能和结构的详细解释:
1. CommentViewModel 类
功能: 该类表示评论的视图模型,包含了评论的各种属性和相关信息。
属性:
Id: 评论的唯一标识符。Node: 评论的类型(使用CommentNode枚举)。Relation: 评论关联的对象(如文章、帖子等)。PublishTime: 评论的发布时间。Commenter: 评论者的信息,使用多态处理(可以是匿名评论或会员评论)。CommentText: 评论的内容。Replies: 评论的回复ID列表。IsDelete: 评论是否被删除的标志。Children: 评论的子评论(回复)。
映射: 使用 AutoMapper 将
Comment实体映射到CommentViewModel。在映射过程中,如果评论被标记为删除,则会用默认的删除信息替代评论者和评论内容。
2. CommentChildren 类
- 功能: 该类表示评论的子评论(回复),结构与
CommentViewModel类似。 - 属性: 包含与
CommentViewModel类似的属性,如Id,PublishTime,Commenter,CommentText,Replies,IsDelete。 - 映射: 也使用 AutoMapper 将
Comment实体映射到CommentChildren。
3. VmCommenter 抽象类
- 功能: 该类是评论者的基类,包含评论者的基本信息。
- 属性: 包含
NickName属性。
4. VmMemberCommenter 和 VmGuestCommenter 类
- 功能: 这两个类分别表示会员评论者和匿名评论者,继承自
VmCommenter。 - 属性:
VmMemberCommenter还包含Avatar和Identity属性。VmGuestCommenter包含Email和Site属性,并提供了一个方法GenerateEmailMd5用于生成邮箱的 MD5 哈希值。
5. CommenterConverter 类
- 功能: 自定义 JSON 转换器,用于在序列化和反序列化过程中处理
VmCommenter类型的对象。 - 方法:
Read: 从 JSON 中读取评论者信息,并根据$type属性确定具体的评论者类型(会员或匿名)。Write: 将VmCommenter对象序列化为 JSON,包含$type属性以指示具体类型。
总结
整体上,这段代码的目的是将评论数据从后端实体模型转换为适合前端展示的视图模型,支持多态处理评论者类型,并提供了自定义的 JSON 序列化和反序列化逻辑。通过使用 AutoMapper 和自定义 JSON 转换器,代码实现了灵活且可扩展的评论处理机制。
评论加载中...