У меня есть приложение, которое загружает список номеров клиентов / материалов из входного файла и отображает их в пользовательском интерфейсе. Эти числа являются простыми нумерованными строками, такими как «02240/00106». Вот класс ClientMatter
:
public class ClientMatter
{
public string ClientNumber { get; set; }
public string MatterNumber { get; set; }
}
Я использую MVVM, и он использует внедрение зависимостей с корнем композиции, содержащимся в пользовательском интерфейсе. Существует сервисный интерфейс IMatterListLoader
, где реализации представляют механизмы для загрузки списков из разных типов файлов. Для простоты, скажем, что с приложением используется только одна реализация, то есть приложение в настоящее время не поддерживает более одного типа файлов.
public interface IMatterListLoader
{
IReadOnlyCollection<string> MatterListFileExtensions { get; }
IReadOnlyCollection<ClientMatter> Load(FileInfo fromFile);
}
Допустим, в моей первоначальной версии я выбрал реализацию MS Excel для загрузки списка вопросов, например:
Я бы хотел, чтобы пользователь мог настроить во время выполнения номера строк и столбцов, с которых начинается список, поэтому представление может выглядеть следующим образом:
А вот реализация MS Excel IMatterListLoader
:
public sealed class ExcelMatterListLoader : IMatterListLoader
{
public uint StartRowNum { get; set; }
public uint StartColNum { get; set; }
public IReadOnlyCollection<string> MatterListFileExtensions { get; set; }
public IReadOnlyCollection<ClientMatter> Load(FileInfo fromFile)
{
// load using StartRowNum and StartColNum
}
}
Номера строк и столбцов являются подробностями реализации, специфичными для реализаций MS Excel, и модель представления об этом не знает. Тем не менее, MVVM требует, чтобы я управлял свойствами представления в модели представления, поэтому если бы я был , чтобы сделать это, это было бы так:
public sealed class MainViewModel
{
public string InputFilePath { get; set; }
// These two properties really don't belong
// here because they're implementation details
// specific to an MS Excel implementation of IMatterListLoader.
public uint StartRowNum { get; set; }
public uint StartColNum { get; set; }
public ICommandExecutor LoadClientMatterListCommand { get; }
public MainViewModel(IMatterListLoader matterListLoader)
{
// blah blah
}
}
Просто для сравнения, вот реализация на основе текстового файла ASCII, которую я мог бы рассмотреть для следующей версии приложения:
public sealed class TextFileMatterListLoader : IMatterListLoader
{
public bool HasHeaderLine { get; set; }
public IReadOnlyCollection<string> MatterListFileExtensions { get; set; }
public IReadOnlyCollection<ClientMatter> Load(FileInfo fromFile)
{
// load tab-delimited client/matters from each line
// optionally skipping the header line.
}
}
Теперь у меня нет номеров строк и столбцов, необходимых для реализации MS Excel, но у меня есть логический флаг, указывающий, начинаются ли номера клиента / материи в первой строке (т.е. без строки заголовка) или начинаются во второй строка (т.е. с строкой заголовка).
Я считаю, что модель представления не должна знать об изменениях между реализациями IMatterListLoader
. Как я могу позволить модели представления выполнять свою работу, контролируя проблемы представления, но при этом не раскрывая некоторые детали реализации?
Вот диаграмма зависимостей: