C# 依赖注入-将参数传递给构造的类型

C# 依赖注入-将参数传递给构造的类型,c#,parameters,constructor,dependency-injection,unity-container,C#,Parameters,Constructor,Dependency Injection,Unity Container,我正在我的项目中引入依赖注入。我有一个对话框窗口,可以作为新实体或现有实体的编辑器。其ViewModel如下所示: public class ContractWindowViewModel { private IRepository<Contract> contractRepository; private Contract model; private bool isNew; public ContractWindowViewModel(Contr

我正在我的项目中引入依赖注入。我有一个对话框窗口,可以作为新实体或现有实体的编辑器。其ViewModel如下所示:

public class ContractWindowViewModel
{
    private IRepository<Contract> contractRepository;
    private Contract model;
    private bool isNew;

    public ContractWindowViewModel(Contract contract, IRepository<Contract> contractRepository)
    {
        if (contract == null)
            throw new ArgumentNullException(nameof(contract));
        if (contractRepository == null)
            throw new ArgumentNullException(nameof(contractRepository));

        this.contractRepository = contractRepository;
        this.model = contract;
        this.isNew = false;
    }

    public ContractWindowViewModel(IRepository<Contract> contractRepository)
    {
        this.contractRepository = contractRepository;
        this.model = new Contract();
        this.isNew = true;
    }

    // (...)
}
公共类合同WindowViewModel
{
私人电子储存库;
私人合同模式;
私有布尔是新的;
public ContractWindowViewModel(合同、IRepository contractRepository)
{
如果(合同==null)
抛出新的异常(合同名称);
如果(contractRepository==null)
抛出新ArgumentNullException(nameof(contractRepository));
this.contractRepository=contractRepository;
该模型=合同;
this.isNew=false;
}
public ContractWindowViewModel(IRepository contractRepository)
{
this.contractRepository=contractRepository;
this.model=新合同();
this.isNew=true;
}
// (...)
}

计划是注入
IRepository
。但有时我需要将
合同
传递给ViewModel(如果我想编辑现有的),或者不传递给ViewModel(如果我想创建新的)。我应该如何使用Unity来实现这一点?

可能是这样的

unityContainer.Resolve<ContractWindowViewModel>(
    new ResolverOverride[] {
        new ParameterOverride("contract", new Contract()),
        new ParameterOverride("contractRepository", new Repository<Contract>())
    });
unityContainer.Resolve(
新罗维瑞德[]{
新参数覆盖(“合同”,新合同()),
新参数覆盖(“contractRepository”,new Repository())
});
来源

使用代码中的DI容器(例如在按钮事件处理程序中)称为服务位置和

相反,您应该有一个工厂,允许您从按钮处理程序(或ViewModel命令)内部创建视图模型

以下是一个工厂的示例:

public interface IContractWindowViewModelFactory
{
    ContractWindowViewModel CreateForNewContract();

    ContractWindowViewModel CreateForExistingContract(Contract existing_contract);
}

public class ContractWindowViewModelFactory : IContractWindowViewModelFactory
{
    private readonly IRepository<Contract> m_Repository;

    public ContractWindowViewModelFactory(IRepository<Contract> repository)
    {
        m_Repository = repository;
    }

    public ContractWindowViewModel CreateForNewContract()
    {
        return new ContractWindowViewModel(m_Repository);
    }

    public ContractWindowViewModel CreateForExistingContract(Contract existing_contract)
    {
        return new ContractWindowViewModel(existing_contract, m_Repository);
    }
}
在处理程序中,您可以将其用于新合同:

var viewmodel_for_new = container.Resolve<ContractWindowViewModel>("ForNew");
Contract existing_contract = ...
var viewmodel_for_existing = container.Resolve<ContractWindowViewModel>(
    "ForExisting",
    new ParameterOverride("contract", existing_contract));
var viewmodel_for_new=container.Resolve(“ForNew”);
或者,对于现有合同:

var viewmodel_for_new = container.Resolve<ContractWindowViewModel>("ForNew");
Contract existing_contract = ...
var viewmodel_for_existing = container.Resolve<ContractWindowViewModel>(
    "ForExisting",
    new ParameterOverride("contract", existing_contract));
现有合同\u合同=。。。
var viewmodel_for_existing=container.Resolve(
“前世的”,
新参数覆盖(“合同”,现有合同);

应用程序运行时,您需要能够稍后创建此视图模型,对吗?例如,当用户单击某个按钮时?也许根据用户单击的按钮,您将决定调用哪个构造函数,对吗?您不应该让ViewModel直接与存储库对话,而应该让它仅依赖于
合同
类吗?为什么您需要知道
合同
是否是新的?@YacoubMassad当然,但按钮单击处理程序将调用
unityContainer.Resolve()
。如何通过该构造传递参数?问题的根源在于将运行时数据(合同实例)注入组件的构造(本例中的合同WindowViewModel)中。您的对象图应该是无状态的,运行时数据应该使用方法调用通过现有的对象图传递。任何时候你违背了这个想法,你就会让一切变得更加困难(正如你已经经历过的那样)。因此,不要使用构造函数注入
契约
,而是在视图模型上定义一个允许设置现有契约的方法。