У меня есть самореферентные отношения с участием .NET Core ApplicationUser
:
public class Network
{
public ApplicationUser ApplicationUser { get; set; }
public string ApplicationUserId { get; set; }
public ApplicationUser Follower { get; set; }
public string FollowerId { get; set; }
}
Это позволяет вести список «подписчиков» и «подписчиков» в модели пользователя:
public class ApplicationUser : IdentityUser
{
//...
public ICollection<Network> Following { get; set; }
public ICollection<Network> Followers { get; set; }
}
Я использую Automapper для сопоставления подписчиков и отслеживаемых списков с моделью представления. Вот видовые модели:
public class UserProfileViewModel
{
//...
public IEnumerable<FollowerViewModel> Followers { get; set; }
public IEnumerable<NetworkUserViewModel> Following { get; set; }
}
public class NetworkUserViewModel
{
public string UserName { get; set; }
public string ProfileImage { get; set; }
public bool IsFollowing { get; set; } = true;
public bool IsOwnProfile { get; set; }
}
public class FollowerViewModel
{
public string UserName { get; set; }
public string ProfileImage { get; set; }
public bool IsFollowing { get; set; } = true;
public bool IsOwnProfile { get; set; }
}
Чтобы учесть различные способы отображения подписчиков и подписчиков, мне пришлось создать два идентичных класса: NetworkUserViewModel
и FollowerViewModel
, чтобы логика сопоставления Automapper могла различать, как отображать подписчиков и как отображать подписчиков. , Вот профиль отображения:
CreateMap<Network, NetworkUserViewModel>()
.ForMember(x => x.UserName, y => y.MapFrom(x => x.ApplicationUser.UserName))
.ForMember(x => x.ProfileImage, y => y.MapFrom(x => x.ApplicationUser.ProfileImage))
.ReverseMap();
CreateMap<Network, FollowerViewModel>()
.ForMember(x => x.UserName, y => y.MapFrom(x => x.Follower.UserName))
.ForMember(x => x.ProfileImage, y => y.MapFrom(x => x.Follower.ProfileImage))
.ReverseMap();
CreateMap<ApplicationUser, UserProfileViewModel>()
.ForMember(x => x.UserName, y => y.MapFrom(x => x.UserName))
.ForMember(x => x.Followers, y => y.MapFrom(x => x.Followers))
.ForMember(x => x.Following, y => y.MapFrom(x => x.Following))
.ReverseMap();
Вы можете видеть, что подписчики отображаются как .MapFrom(x => x.Follower.UserName))
, а подписчики отображаются как .MapFrom(x => x.ApplicationUser.UserName))
.
У меня вопрос: могу ли я определить различные способы отображения подписчиков и подписчиков, не задавая дубликаты классов? Я бы предпочел использовать NetworkUserViewModel
для последователей и ; так что мне не нужен дубликат FollowerViewModel
, если это возможно. Есть ли способ сделать это?
Обновление
Я реализовал предложение @Matthijs (см. Первый комментарий) использовать наследование, чтобы избежать ненужного дублирования свойств. Теперь мои view-модели:
public class UserProfileViewModel
{
//...
public IEnumerable<FollowerViewModel> Followers { get; set; }
public IEnumerable<FollowingViewModel> Following { get; set; }
}
public class NetworkUserViewModel
{
public string UserName { get; set; }
public string ProfileImage { get; set; }
public bool IsFollowing { get; set; }
public bool IsOwnProfile { get; set; }
}
public class FollowingViewModel : NetworkUserViewModel
{
}
public class FollowerViewModel : NetworkUserViewModel
{
}
Со следующим изменением логики Automapper:
CreateMap<Network, FollowingViewModel>()
.ForMember(x => x.UserName, y => y.MapFrom(x => x.ApplicationUser.UserName))
.ForMember(x => x.ProfileImage, y => y.MapFrom(x => x.ApplicationUser.ProfileImage))
.ReverseMap();
CreateMap<Network, FollowerViewModel>()
.ForMember(x => x.UserName, y => y.MapFrom(x => x.Follower.UserName))
.ForMember(x => x.ProfileImage, y => y.MapFrom(x => x.Follower.ProfileImage))
.ReverseMap();
CreateMap<ApplicationUser, UserProfileViewModel>()
.ForMember(x => x.UserName, y => y.MapFrom(x => x.UserName))
.ForMember(x => x.Followers, y => y.MapFrom(x => x.Followers))
.ForMember(x => x.Following, y => y.MapFrom(x => x.Following))
.ReverseMap();
Этот рефактор уменьшает дублирование и упрощает логику отображения.
Я оставляю это открытым на несколько дней на случай, если найдется решение, основанное исключительно на логике Automapper ...