4 回答
TA贡献1757条经验 获得超7个赞
出于我的目的,似乎最整洁的解决方案是这样的:
将 User 类拆分为基类和派生类,并添加构造函数以复制必填字段:
public class User
{
public User() { }
public User(UserDetails user)
{
this.UserId = user.UserId;
this.Name = user.Name;
this.Email = user.Email;
}
public string UserId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
public class UserDetails : User
{
public string PasswordHash { get; set; }
}
数据访问类将返回一个 UserDetails 对象,然后可以在返回之前对其进行转换:
UserDetails userDetails = _dataAccess.GetUser();
User userToReturn = new User(userDetails);
也可以按照 Daniel 的建议使用自动映射器而不是构造函数方法来完成。我不喜欢这样做,因此我问这个问题,但这似乎是最整洁的解决方案,需要最少的重复。
TA贡献1780条经验 获得超4个赞
有两种方法可以做到这一点:
使用相同的类,并且仅填充要发送的属性。这样做的问题是,值类型将具有默认值(属性将作为 发送,如果这可能不准确)。
int
0
对要发送到客户端的数据使用其他类。这基本上就是丹尼尔在评论中得到的 - 你有一个不同的模型,由客户“查看”。
第二种选择是最常见的。如果您使用的是 Linq,则可以使用以下命令映射值:Select()
users.Select(u => new UserModel { Name = u.Name, Email = u.Email });
基本类型不会像您希望的那样工作。如果将派生类型强制转换为其父类型并对其进行序列化,它仍会序列化派生类型的属性。
以这个为例:
public class UserBase {
public string Name { get; set; }
public string Email { get; set; }
}
public class User : UserBase {
public string UserId { get; set; }
public string PasswordHash { get; set; }
}
var user = new User() {
UserId = "Secret",
PasswordHash = "Secret",
Name = "Me",
Email = "something"
};
var serialized = JsonConvert.SerializeObject((UserBase) user);
请注意,序列化时强制转换。即便如此,结果是:
{
"UserId": "Secret",
"PasswordHash": "Secret",
"Name": "Me",
"Email": "something"
}
它仍然序列化了该类型的属性,即使它被强制转换为 。UserUserBase
TA贡献1818条经验 获得超7个赞
如果要忽略该属性,只需在模型中添加忽略 annotation,就像这样,当模型序列化时,它将跳过该属性。
[JsonIgnore]
public string PasswordHash { get; set; }
如果你想在运行时忽略(这意味着动态).Newtonsoft.Json中有一个构建函数可用
public class User
{
public string UserId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string PasswordHash { get; set; }
//FYI ShouldSerialize_PROPERTY_NAME_HERE()
public bool ShouldSerializePasswordHash()
{
// use the condtion when it will be serlized
return (PasswordHash != this);
}
}
它被称为“条件属性序列化”,文档可以在这里找到。
TA贡献1851条经验 获得超3个赞
问题是你看错了。API 即使直接与特定的数据库实体一起工作,也不会处理实体。这里有一个关注点分离问题。您的 API 正在处理用户实体的表示形式。实体类本身是数据库的函数。它上面有一些只对数据库重要的东西,重要的是,它上面的东西对你的API无关紧要。尝试使用一个可以满足多个不同应用程序的类是愚蠢的,并且只会导致具有嵌套依赖项的代码变脆。
更重要的是,您将如何与此 API 交互?也就是说,如果您的API直接公开您的实体,那么使用此API的任何代码都必须依赖于您的数据层以便它可以访问,或者它必须实现自己的类来表示,并希望它与API实际想要的相匹配。User
User
User
现在想象一下替代方案。创建一个“通用”类库,该类库将在 API 和任何客户端之间共享。在该库中,您可以定义类似 .您的 API 仅绑定到/从 绑定,并将其来回映射到 。现在,您已经完全隔离了数据层。客户端只知道,唯一触及数据层的是你的API。当然,现在您可以限制向API客户端公开的信息,只需通过构建方式即可。更好的是,如果您的应用程序需求发生变化,则可以更改,而不会像每个消费客户端的API冲突一样螺旋式上升。您只需修复API,客户端就会在不知情的情况下继续。如果确实需要进行重大更改,可以执行某些操作,例如创建类以及新版本的 API。如果不创建一个全新的表,就无法创建一个全新的表,然后这会在标识中引发冲突。UserResource
UserResource
User
UserResource
User
UserResource
User
UserResource2
User2
长话短说,使用 API 的正确方法是始终使用单独的 DTO 类,甚至多个 DTO 类。API 永远不应该直接使用实体类,否则你只会感到痛苦。
- 4 回答
- 0 关注
- 97 浏览
添加回答
举报