Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/273.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我如何用IOC替换一个switch语句,以便我能够保持坚实的原则_C#_Inversion Of Control_Switch Statement_Solid Principles - Fatal编程技术网

C# 我如何用IOC替换一个switch语句,以便我能够保持坚实的原则

C# 我如何用IOC替换一个switch语句,以便我能够保持坚实的原则,c#,inversion-of-control,switch-statement,solid-principles,C#,Inversion Of Control,Switch Statement,Solid Principles,我想避免使用switch语句。我有30多种文档类型。我还可能需要添加更多的文档类型。我宁愿通过IDocument并在IDocument的实现中指定类型。我忘了提到的还有ProgressNoteViewModel,LabViewModel。。。所有继承自WorkspaceViewModel,并且所有具体实现构造函数都将iPartient类型作为参数。我还使用Castle作为我的IoC容器 我想将代码重构为 viewModel = new TreeViewModel(repository.GetPa

我想避免使用switch语句。我有30多种文档类型。我还可能需要添加更多的文档类型。我宁愿通过IDocument并在IDocument的实现中指定类型。我忘了提到的还有ProgressNoteViewModel,LabViewModel。。。所有继承自WorkspaceViewModel,并且所有具体实现构造函数都将iPartient类型作为参数。我还使用Castle作为我的IoC容器

我想将代码重构为

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]

在您的CastleXML配置中,您可以添加(我在这里只对Castle有一点模糊的了解)

现在您根本不需要switch语句


然而,值得注意的是,开关并不是邪恶的,它们只是闻起来很难闻,就像所有难闻的气味一样,应该与一切好闻的东西隔离开来;这就是工厂模式要实现的目标。

我将尝试将策略和工厂模式结合起来,而不是IoC容器。如果您需要为每种情况定制构造函数参数,那么我假设您需要一个适当的带连接的IoC容器

class ViewModelBuilderFactory
{
    private Dictionary<string, System.Type> resolver;

    public void ViewModelBuilderFactory()
    {
        resolver = new Dictionary<string, Type>
        {
            {"ProgressNotes", typeof(ProgressNotesViewModelBuilder)},
            {"Labs", typeof(LabsViewModelBuilder)}
        };
    }

    public IViewModelBuilder GetViewModelBuilder(string key)
    {
        System.Type type = this.resolver[key];
        return (IViewModelBuilder)Activator.CreateInstance(type);
    }

}
class ViewModelBuilderFactory
{
专用字典解析器;
public void ViewModelBuilderFactory()
{
解析程序=新字典
{
{“ProgressNotes”,类型(ProgressNotesViewModelBuilder)},
{“实验室”,typeof(LabsViewModelBuilder)}
};
}
公共IViewModelBuilder GetViewModelBuilder(字符串键)
{
System.Type Type=this.resolver[key];
return(IViewModelBuilder)Activator.CreateInstance(类型);
}
}
编辑

参考以上使用Castle Windsor的答案,以下代码可以使用命名组件执行相同操作,但在代码中初始化:

container.Register(Component
.For<IViewModelBuilder>()
.ImplementedBy<ProgressNotesViewModelBuilder>()
.Named("ProgressNotes"));
container.Register(Component
.For<IViewModelBuilder>()
.ImplementedBy<LabsViewModelBuilder>()
.Named("Labs"));

var builder = container.Resolve<IViewModelBuilder>(key);
container.Register(组件
.对于()
.由()实施
。命名为(“进度注释”);
容器寄存器(组件
.对于()
.由()实施
。命名为(“实验室”);
var builder=container.Resolve(键);

您使用的是什么IoC容器?Yarg只差几分钟就被打败了。您还可以让每个ModelBuilder类实现
IViewModelBuilder
接口。如果你真的想要一个IoC容器,你可以使用docType来区分命名的配置,但是在容器中配置的业务逻辑可能有点太多了。要让它们实现接口,否则就没有意义了。编辑。与控制反转原则相适应的变化是依赖于
IViewModelBuilder
,而不是具体的实现
ProgressNotesViewModelBuilder
LabsViewModelBuilder
。是的,如果您知道正在使用哪个容器,IoC容器很容易放入。我的想法是假设没有,让提问者决定如何做出改变。没必要问这个问题对不起,我是新来的。我想避免使用switch语句。我有30多种文档类型。我还可能需要添加更多的文档类型。我宁愿通过IDocument并在IDocument的实现中指定类型。我忘了提到的还有ProgressNoteViewModel,LabViewModel。。。所有继承自WorkspaceViewModel,并且所有具体实现构造函数都将iPartient类型作为参数。我还使用Castle作为我的IoC容器
IViewModelBuilder modelBuilder = (IViewModelBuilder)
    container.Resolve(docType + "ViewModelBuilder");
class ViewModelBuilderFactory
{
    private Dictionary<string, System.Type> resolver;

    public void ViewModelBuilderFactory()
    {
        resolver = new Dictionary<string, Type>
        {
            {"ProgressNotes", typeof(ProgressNotesViewModelBuilder)},
            {"Labs", typeof(LabsViewModelBuilder)}
        };
    }

    public IViewModelBuilder GetViewModelBuilder(string key)
    {
        System.Type type = this.resolver[key];
        return (IViewModelBuilder)Activator.CreateInstance(type);
    }

}
container.Register(Component
.For<IViewModelBuilder>()
.ImplementedBy<ProgressNotesViewModelBuilder>()
.Named("ProgressNotes"));
container.Register(Component
.For<IViewModelBuilder>()
.ImplementedBy<LabsViewModelBuilder>()
.Named("Labs"));

var builder = container.Resolve<IViewModelBuilder>(key);