Я хотел избежать оператора переключения. У меня есть более чем 30 типов документов. Существует также возможность, я должен буду добавить больше продвижения типов документов. Я передал бы IDocument, и укажите тип в реализации IDocument. Что-то еще, что я забыл упоминать, было ProgressNoteViewModel, LabViewModel... все наследовались WorkspaceViewModel, и все конструкторы конкретной реализации берут тип IPatient в качестве параметра. Я также использую Замок в качестве своего контейнера МОК
Я хотел бы осуществить рефакторинг код к чему-то как
viewModel = new TreeViewModel(repository.GetPatientDocumentListing(IDocumentType);
this.DocTreeViewModel = viewModel;
//How would I then be able to instantiate the right ViewModel
//based on IDocumentType and also pass a object into the
//constructor that is not know at compile time
У меня есть следующий код:
switch (docType)
{
case "ProgressNotes":
viewModel = new TreeViewModel(repository.GetPatientProgressNotes());
this.DocTreeViewModel = viewModel;
ProgressNoteViewModel workspace = ProgressNoteViewModel.NewProgressNoteViewModel(_patient);
break;
case "Labs":
viewModel = new TreeViewModel(repository.GetPatientLabs());
this.DocTreeViewModel = viewModel;
LabViewModel workspace = LabViewModel.NewLabViewModel(_patient);
break;
}
this.Workspaces.Add(workspace);
this.SetActiveWorkspace(workspace);
Полностью не проверено:
public class ViewModelBuilderFactory
{
public IViewModelBuilder GetViewModelBuilder (string docType, IRepository repository)
{
switch (docType)
{
case "ProgressNotes":
return new ProgressNotesViewModelBuilder(repository);
case "Labs":
return new LabsViewModelBuilder(repository);
default:
throw new ArgumentException(
string.Format("docType \"{0}\" Invalid", docType);
}
}
}
public interface IViewModelBuilder
{
TreeViewModel GetDocTreeViewModel();
WorkSpace GetWorkSpace(Patient patient);
}
public class LabsViewModelBuilder : IViewModelBuilder
{
private IRepository _repository;
public LabsViewModelBuilder(IRepository repository)
{
_repository = repository;
}
public TreeViewModel GetDocTreeViewModel()
{
return new TreeViewModel(_repository.GetPatientLabs());
}
public Workspace GetWorkspace(Patient patient)
{
return LabViewModel.NewLabViewModel(patient);
}
}
public class ProgressNotesViewModelBuilder : IViewModelBuilder
{
private IRepository _repository;
public ProgressNotesViewModelBuilder(IRepository repository)
{
_repository = repository;
}
public TreeViewModel GetDocTreeViewModel()
{
return new TreeViewModel(_repository.GetPatientProgressNotes());
}
public Workspace GetWorkspace(Patient patient)
{
return ProgressNoteViewModel.NewProgressNoteViewModel(patient);
}
}
Теперь ваш телефонный код:
ViewModelBuilderFactory factory = new ViewModelBuilderFactory();
IViewModelBuilder modelBuilder = factory.GetViewModelBuilder(docType, repository);
this.DocTreeViewModel = modelBuilder.GetDocTreeViewModel();
Workspace workspace = modelBuilder.GetWorkspace(patient);
this.Workspaces.Add(workspace);
this.SetActiveWorkspace(workspace);
[4 правки с момента первого сообщения ; продолжайте видеть ошибки]
[Дальнейшее редактирование с учетом того, что вы используете Castle IOC]
В свою конфигурацию Castle xml вы можете добавить (и я работаю здесь только смутное знание Castle)
<component id="ProgressNotesViewModelBuilder"
type="MyNamespace.ProgressNotesViewModelBuilder, MyAssembly">
<parameters>
<!-- reference to repository here -->
</parameters>
</component>
<component id="LabsViewModelBuilder"
type="MyNamespace.LabsViewModelBuilder, MyAssembly">
<parameters>
<!-- reference to repository here -->
</parameters>
</component>
Тогда вам не понадобится ViewModelBuilderFactory, вы можете просто заменить
IViewModelBuilder modelBuilder = factory.GetViewModelBuilder(docType, repository);
на
IViewModelBuilder modelBuilder = (IViewModelBuilder)
container.Resolve(docType + "ViewModelBuilder");
. Теперь вам вообще не нужен оператор switch.
Однако стоит отметить, что выключатели не являются злом, они просто плохо пахнут и, как и все неприятные запахи, следует изолировать от всего, что хорошо пахнет; вот для чего предназначен шаблон Factory.