我有一个由两部分组成的项目:
ASP.NET API使用Entity Framework.NET MAUI客户端应用程序我使用DTOs与API进行通信,以避免公开实体的其他属性。由于这种方法,我能够将从API中发送的实体数据和数据分离开来。
起初,我也在DTOs UI中使用了这些MAUI。但是过了一段时间,我开始注意到它们包含了与UI相关的属性、属性或方法,这些属性或方法与API本身无关,因此它们在请求中是多余的。
示例:
1- API将收到MAUI的请求,以便根据它的名称进行练习
2- ExerciseService返回:ExerciseEntity和ExerciseController使用AutoMapper映射ExerciseEntity -> ExerciseDto ommiting ExerciseId字段(只有管理员可以在DB中看到此信息),并在API响应中返回该信息。
3- MAUI从API ExerciseDto接收。但是在客户端,它还想知道来自ExerciseDto的数据是否在UI中折叠。因此,我将IsCollapsed属性添加到ExerciseDto中。但是现在这是API的一个冗余属性,因为我不想将这些信息保存在数据库中。
问题:
我是否应该将这些DTOs映射到客户端的新对象?
或者如何处理这个问题?
是否有更容易的方法来实现分离?
因为拥有另一个映射层将增加DTOs和那些新客户端对象之间的额外复杂性和许多重复属性。
发布于 2022-11-19 16:04:09
通常,如果您使用干净的体系结构方法,那么DTO应该不包含仅与某些项目相关的属性和其他特定数据,以便其他项目能够以依赖的形式自由使用。
然后在xamarin/maui应用程序中使用不同的DTO方法,例如:
方法1.将(当然)映射到适合UI的类中。这里有一些选项,使用手动映射,编写使用反射的自己的代码,或者使用相同的反射使用第三方库。就我个人而言,当谈到第三方libs时,Mapster为api和移动客户端向我展示了非常好的效果。
方法2. DTO子类。其基本思想是将dto反序列化为派生类,然后调用Init();如果需要的话。在反序列化器/映射器弹出之后,您用OnPropertyChanged手动实现的所有属性都将更新绑定,并且您也有一个调用RaiseProperties()的备份计划;对于所有的支持,甚至那些没有OnPropertyChanged的人,如果有的话,他们也可以更新绑定。
例子:我们的Api DTO
public class SomeDeviceDTO
{
public int Id { get; set; }
public int Port { get; set; }
public string Name { get; set; }
}我们的派生类用于移动客户端:
public class SomeDevice : SomeDeviceDTO, IFromDto
{
// we want to be able to change this Name property in run-time and to
// reflect changes so we make it bindable (other props will remain without
// OnPropertyChanged BUT we can always update all bindings in code if needed
// using RaiseProperties();):
private string _name;
public new string Name
{
get { return _name; }
set
{
if (_name != value)
{
_name = value;
OnPropertyChanged();
}
}
}
// ADD any properties you need for UI
// ...
#region IFromDto
public void Init()
{
//put any code you'd want to exec after dto's been imported
// for example to fill any new prop with data derived from what you received
}
public void RaiseProperties()
{
var props = this.GetType().GetProperties();
foreach (var property in props)
{
if (property.CanRead)
{
OnPropertyChanged(property.Name);
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
public interface IFromDto : INotifyPropertyChanged
{
//
// Summary:
// Can initialize model after it's being loaded from dto
void Init();
//
// Summary:
// Notify all properties were updated
void RaiseProperties();
}我们可以像这样:var device = JsonConvert.DeserializeObject<SomeDevice>(jsonOfSomeDeviceDTO);
如果需要的话我们可以打电话给Init();。
可以随意编辑这个答案来添加更多的方法。
https://stackoverflow.com/questions/74501223
复制相似问题