Продолжая комментарий, который я оставил, один из способов, которым вы могли бы решить эту проблему, это сделать ваш BaseViewModel
абстрактным классом и иметь конкретные классы, производные от него.Так что UserViewModel
и AdminViewModel
.Эти два конкретных класса будут затем моделями для TableView
и TableManagentView
и будут отвечать за указание «внешнему миру», как маркировать поля.
Базовый класс имеет два основных аспекта (кромеваши обычные поля): аннотация Dictionary<string, string>
, которая будет содержать метки и метод для получения метки из списка: string GetLabel(string propName)
.Так что-то вроде этого:
public abstract class BaseViewModel
{
protected abstract Dictionary<string, string> Labels { get; }
public string UserComment { get; set; }
public string GetLabel(string propName)
{
if (!Labels.TryGetValue(propName, out var label))
throw new KeyNotFoundException($"Label not found for property name: {propName}");
return label;
}
}
Затем вы создаете два производных класса User
и Admin
:
public sealed class UserViewModel : BaseViewModel
{
protected override Dictionary<string, string> Labels => new Dictionary<string, string>
{
{ nameof(UserComment), "User label" }
};
}
public sealed class AdminViewModel : BaseViewModel
{
protected override Dictionary<string, string> Labels => new Dictionary<string, string>
{
{ nameof(UserComment), "Admin label" }
};
}
Они реализуют только Dictionary<string, string>
и задают соответствующий текстдля каждого поля базового класса.
Далее измените BaseViewComponent
на следующее:
Вид :
@model DisplayNameTest.Models.BaseViewModel
<h3>Hello from my View Component</h3>
<!-- Gets the label via the method on the base class -->
<p>@Model.GetLabel(nameof(BaseViewModel.UserComment))</p>
<p>@Model.UserComment)</p>
Класс ComponentView (теперь проще)
public IViewComponentResult Invoke(BaseViewModel viewModel)
{
return View(viewModel);
}
Наконец, изменив ваши представления TableView
и TableManagentView
на следующее:
@model WebApp.Models.AdminViewModel
@{
Layout = null;
}
<h1>Admin View</h1>
<div>
@await Component.InvokeAsync("Base", Model)
</div>
и контроллер на:
public IActionResult Index()
{
var adminViewModel = new AdminViewModel { UserComment = "some comment from admin" };
return View(adminViewModel);
}
Теперь, когда вы перейдете к TableView
, вы передадите UserViewModel
к BaseViewComponent
, и он определит правильную метку.Введение новых полей потребует от вас изменения ваших моделей представления и добавления новой записи в Словарь.
Это не идеально, но я думаю, что это хороший способ решить эту проблему.Я далеко не эксперт по MVC, так что, возможно, другие могут придумать более естественный способ сделать это.Я также подготовил рабочий пример приложения и отправил его на GitHub.Вы можете проверить это здесь: aspnet-view-component-demo .Надеюсь, это поможет.