我有相对简单的控制器逻辑和丑陋的对象创建部分。有些对象非常庞大,尽管控制器所做的只是返回对象,但它看起来很混乱,很难读懂。因此,我想问一问,怎样才能使这些案件变得更干净。我给你们举几个例子:
例如,请注意视图模型的创建:
public async Task<ActionResult> Edit(Guid id)
{
if (id.IsValidGuid())
{
// Get User Details
var userTask = ApiGatewayService.GetUserDetail(id, AuthService.BearerToken);
var nationalitiesTask = ApiGatewayService.GetNationalityList(
new FilterParameters(),
AuthService.BearerToken
);
var countriesTask = ApiGatewayService.GetCountryList(
new FilterParameters(),
AuthService.BearerToken
);
await Task.WhenAll(userTask, nationalitiesTask, countriesTask);
var user = userTask.Result;
var nationalities = nationalitiesTask.Result;
var countries = countriesTask.Result;
if (user is null)
return NotFound();
var userAddress = user.PrimaryAddress;
var userHomePhone = user.Phones.FirstOrDefault(
x => x.Type == PhoneType.LandLine
);
var userMobilePhone = user.Phones.FirstOrDefault(
x => x.Type == PhoneType.Mobile
);
// View Model
var viewModel = new EditUserViewModel
{
User = user,
Id = user.Id,
FirstName = user.FirstName,
LastName = user.LastName,
BirthDay = user.Detail?.BirthDay,
Email = user.Email,
Nationality = user.Detail?.Nationality?.Id,
Title = user.Detail != null ? user.Detail.Title : TitleType.Mr,
ProfilePhotoName = user.Detail?.ProfilePhotoName,
MarketingOptin = user.Detail != null
? user.Detail.MarketingOptin
: false,
ChangePassword = false,
Password = null,
Address_City = userAddress?.City,
Address_Country = userAddress?.Country.Id,
Address_HouseName = userAddress?.HouseName,
Address_HouseNumber = userAddress?.HouseNumber,
Address_Line = userAddress?.AddressLine,
Address_PostCode = userAddress?.PostCode,
Address_StreetName = userAddress?.StreetName,
Home_CountryCode = userHomePhone?.CountryCode?.ToString(),
Home_PhoneNumber = userHomePhone?.PhoneNumber,
Mobile_CountryCode = userMobilePhone?.CountryCode?.ToString(),
Mobile_PhoneNumber = userMobilePhone?.PhoneNumber,
CountriesList = countries.List,
NationalitiesList = nationalities.List
};
return View(viewModel);
}
else
return RedirectToAction("Index");
}或者另一个使用LINQ进行巨大选择的
public CompanyDetailModel GetCompanyDetails(Guid accountHolderId)
{
CompanyDetailModel companyDetailModel = new CompanyDetailModel();
var accountHolder = _dbContext.AccountHolders.FirstOrDefault(
x => x.Id == accountHolderId
);
var companyId = accountHolder.ObjectId;
var company = _dbContext.Companies.FirstOrDefault(x => x.Id == companyId);
companyDetailModel.CompanyId = company.Id;
companyDetailModel.Description = company.Description;
companyDetailModel.Name = company.Name;
companyDetailModel.RegistrationNumber = company.RegistrationNumber;
companyDetailModel.VATNumber = company.VATNumber;
var users =
from ah in _dbContext.AccountHolders
join uc in _dbContext.UserCompanies
on ah.ObjectId
equals uc.CompanyId
join u in _dbContext.Users
on uc.UserId
equals u.Id
where ah.Id == accountHolderId
select new CompanyUserModel
{
UserId = u.Id,
CompanyId = (Guid)uc.CompanyId,
FullName = u.FirstName + " " + u.LastName,
Email = u.Email,
PhoneNumber = u.PhoneNumber,
UserCompanyRoleType = uc.Role
}
;
var invites =
from ci in _dbContext.UserCompanyInvites
select new CompanyUserInviteModel
{
Id = ci.Id,
CompanyId = ci.CompanyId,
IsAccepted = ci.IsAccepted,
UserEmail = ci.UserEmail,
RoleType = ci.RoleType
}
;
companyDetailModel.CompanyUsers = users.ToList();
companyDetailModel.CompanyUserInvites = invites.ToList();
return companyDetailModel;
}用私有方法创建对象就足够了,还是有更好的方法?设置一个映射器不是很乏味吗?
发布于 2018-11-28 13:54:59
无论将此逻辑移动到视图模型或数据映射器中,您都有数据映射逻辑。设置数据映射程序并不比控制器中已经存在的代码更繁琐。这似乎更多的是一个关于代码美学的问题。它在控制器“看起来”凌乱,你想要“干净”的外观控制器。这可以通过以下方式之一实现:
您选择的解决方案将导致“更干净”的控制器代码,这似乎是您的最终目标。我以前使用过数字2和3的组合,其中2号用于简单视图模型,第3号用于复杂视图模型,或表示应用程序中整个“页面”或“屏幕”的视图模型。
使用方法2和3,您将需要一个额外的层来将对视图模型中的数据的更改应用到您的实体。您可以使用模糊的“服务类”,也可以使用干净的体系结构中的用例。
无论哪种方式,您都需要代码将数据从实体映射到查看模型,然后再返回。这不会改变的。你所能做的就是让它看起来更漂亮,并希望把有意义的名字应用于事物。
发布于 2018-11-28 10:48:01
老实说我不觉得这太糟了。关键是控制器有一个单一的责任。
如果你想让它变得更干净,你可以移动映射,ViewModel本身。
public class EditUserViewModel
{
private User user;
EditUserViewModel(User user) {this.user = user;}
public bool MarketingOptin
{
get
{
return user.Detail != null ? user.Detail.MarketingOptin : false,
}
set {...}
}
}https://softwareengineering.stackexchange.com/questions/382133
复制相似问题