Если я правильно понимаю свойство, есть несколько вариантов:
1) Сделайте так, чтобы свойство FilePath использовало локатор службы для поиска FileService:
public string FilePath {
get {
FileService fileService = DependencyResolver.Current.GetService<FileService>();
return fileService.GetFilePathForDocument(this);
}
}
Хотя я не большой поклонник статических сервисных локаторов, поскольку они затрудняют тестирование, это может быть приемлемым вариантом. Чтобы сделать его более легко тестируемым, вы можете сделать локатор файловой службы инъекционным:
private static readonly Func<FileService> defaultFileServiceLocator = ()=>DependencyResolver.Current.GetService<FileService>():
private Func<FileService> fileServiceLocator = defaultFileServiceLocator;
public Func<FileService> FileServiceLocator {
get { return fileServiceLocator; }
set { fileServiceLocator = value ?? defaultFileServiceLocator; }
}
А затем используйте это в FilePath
public string FilePath {
get {
FileService fileService = fileServiceLocator();
return fileService.GetFilePathForDocument(this);
}
}
Таким образом, вы можете внедрить свой собственный локатор файловой службы во время тестирования.
2) Явно требует FileService при получении пути к файлу. Вместо свойства FilePath у вас будет:
public string GetFilePath(FileService service){
service.GetFilePathForDocument(this);
}
Проблема в этом, конечно, в том, что теперь вызывающему GetFilePath необходимо иметь FileService. Это не является большой проблемой для контроллеров, потому что если вы используете IoC, вы можете внедрить FileService в конструктор контроллера. Этот подход является более чистым, так как он не зависит от сервисных локаторов, но, как вы видите, он немного более неудобен для вызывающего абонента.
3) Вставить FileService в сам класс документа.
Вместо использования локатора файловой службы вы должны внедрить сам файловую службу, когда создаете свой ProductApprovalDocument. При таком подходе вы можете снова использовать простое свойство FilePath. Основная проблема заключается в том, что это часто не слишком хорошо работает с ORM, поскольку они часто конструируют объекты, используя конструктор по умолчанию, и вам нужно каким-то образом подключиться к процессу конструирования объекта, чтобы ввести зависимости. Кроме того, я не большой поклонник внедрения сервисов в доменные объекты.
4) Вы устанавливаете FilePath снаружи сущности. Как вы сказали, это должно быть сделано несколько автоматически, так как вы не хотите делать это каждый раз вручную. Для этого потребуется некоторый слой, через который должны пройти все объекты, который устанавливает свойство FilePath.
5) Не делайте FilePath свойством ProductApprovalDocument вообще. Это был бы разумный выбор тоже. ProductApprovalDocument ничего не знает о своем FilePath, так почему оно должно быть свойством? Это FileService, который вычисляет значение. У вас все еще может быть отдельная версия модели представления ProductApprovalDocument, у которой действительно есть свойство FilePath. Вы устанавливаете свойство при создании модели вида:
var model = new ProductApprovalDocumentViewModel();
mapper.Map(realDocument, model); // map common properties with AutoMapper or so
model.FilePath = fileService.GetFilePathForDocument(realDocument);
Однако, если ProductApprovalDocument нужно что-то делать со своим FilePath (зачем это нужно?), Этот подход больше не работает.
Лично я бы пошел с решением 5, 2 или 1 в том порядке приоритета, где это применимо.