我在我的项目中引入了依赖注入。我有一个对话窗口,可以作为新实体或现有实体的编辑器。它的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;
}
// (...)
}
计划是注入IRepository<Contract>
。但有时我需要将Contract
传递给ViewModel(如果我想编辑现有的)或不传递(如果我想创建新的)。我应该如何使用Unity?
答案 0 :(得分:4)
使用代码中的DI容器(例如在按钮事件处理程序中)称为服务位置和is considered to be an anti-pattern。
您应该有一个工厂,允许您从按钮处理程序(或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);
}
}
现在您需要将IContractWindowViewModelFactory
注入需要能够创建ContractWindowViewModel
视图模型的类(例如,通过构造函数注入)。
由于您使用的是DI容器,因此需要在Composition Root中使用IContractWindowViewModelFactory
注册ContractWindowViewModelFactory
。您还需要注册IRepository<Contract>
(我猜您已经这样做了。)
现在,在您的按钮处理程序(或命令处理程序)中,您可以使用工厂为新的或现有的ContractWindowViewModel
创建Contract
。
如果由于某种原因,你仍然想要使用按钮处理程序中的容器(我鼓励你不),那么你可以像这样使用named registrations:
在作文根目录中:
container.RegisterType<ContractWindowViewModel>(
"ForNew",
new InjectionConstructor(
new ResolvedParameter<IRepository<Contract>>()));
container.RegisterType<ContractWindowViewModel>(
"ForExisting",
new InjectionConstructor(
new ResolvedParameter<Contract>(),
new ResolvedParameter<IRepository<Contract>>()));
在您的处理程序中,您可以将此用于新合同:
var viewmodel_for_new = container.Resolve<ContractWindowViewModel>("ForNew");
或现有合同:
Contract existing_contract = ...
var viewmodel_for_existing = container.Resolve<ContractWindowViewModel>(
"ForExisting",
new ParameterOverride("contract", existing_contract));
答案 1 :(得分:0)
可能是这样的......
unityContainer.Resolve<ContractWindowViewModel>(
new ResolverOverride[] {
new ParameterOverride("contract", new Contract()),
new ParameterOverride("contractRepository", new Repository<Contract>())
});
来源 http://mikaelkoskinen.net/post/unity-passing-constructor-parameters-to-resolve