我有一个ModelStateDictionary的包装器,我的所有服务都接受它。是否可以配置autofac将控制器ModelStateDictionary注入包装器的构造函数,然后将其注入服务构造函数?
//code
public class ModelValidation : IModelValidation {
public ModelValidation(ModelStateDictionary msd){...}
..
..
}
public class CustomerService{
public CustomerService(IModelValidation mv){...}
..
}
由于
答案 0 :(得分:9)
根据您的意见,我特此修改我的答案:)
ModelStateDictionary
显然不是应由容器解析的服务,而是应在实例化时提供的数据。我们可以告诉我,ModelState由每个Controller实例拥有,因此在“解析时间”不能用于容器。
此外,每个ModelValidation
实例都会绑定到ModelStateDictionary
个实例,因此也会被视为数据。
在Autofac中,当必须将数据传递给构造函数时(可选地除了其他依赖项之外),我们必须使用工厂委托。这些委托将处理传递给构造函数的依赖项和数据。 Autofac的好处在于这些代表可以自动生成。
我提出以下解决方案:
由于ModelValidation和CustomerService都需要构造函数中的数据,因此我们需要两个工厂委托(注意:参数名称必须与其相应构造函数中的名称匹配):
public delegate IModelValidation ModelValidationFactory(ModelStateDictionary msd);
public delegate CustomerService CustomerServiceFactory(ModelStateDictionary msd);
由于您的控制器不应该知道这些委托来自何处,因此它们应该作为依赖项传递给控制器构造函数:
public class EditCustomerController : Controller
{
private readonly CustomerService _customerService;
public EditCustomerController(CustomerServiceFactory customerServiceFactory
/*, ...any other dependencies required by the controller */
)
{
_customerService = customerServiceFactory(this.ModelState);
}
}
CustomerService应该有一个与此类似的构造函数(可选择在ServiceBase类中处理其中一些):
public class CustomerService
{
private readonly IModelValidation _modelValidation;
public CustomerService(ModelStateDictionary msd,
ModelValidationFactory modelValidationFactory)
{
_modelValidation = modelValidationFactory(msd);
}
为了实现这一点,我们需要像这样构建容器:
var builder = new ContainerBuilder();
builder.Register<ModelValidation>().As<IModelValidation>().FactoryScoped();
builder.Register<CustomerService>().FactoryScoped();
builder.RegisterGeneratedFactory<ModelValidationFactory>();
builder.RegisterGeneratedFactory<CustomerServiceFactory>();
builder.Register<EditCustomerController>().FactoryScoped();
因此,当控制器被解析时(例如,当使用the MvcIntegration module时),工厂代表将被注入控制器和服务。
更新:为了减少所需的代码,您可以将CustomerServiceFactory
替换为我所描述的here之类的通用工厂代理。
答案 1 :(得分:1)
Builder.RegisterInstance(new ModelStateDictionary()).SingleInstance();
builder.Register(c => new SW.PL.Util.ModelStateWrapper
(c.Resolve<ModelStateDictionary>())).As<IValidationDictionary>().InstancePerHttpRequest();
答案 2 :(得分:0)
添加不带ValidationService的新构造函数。使用属性分配ValidationService。
该属性必须在ICostumerService接口
中实现public class ModelStateWrapper: IValidationDictionary {
public ModelStateWrapper(ModelStateDictionary msd){}
}
public class CustomerService: ICostumerService{
public IValidationDictionary ValidationDictionary { get; set; }
public CustomerService(ICustomerRepsitory customerRepository, IValidationDictionary validationDictionary ){}
public CustomerService(ICustomerRepsitory customerRepository){}
}
public Controller(ICustomerService customerService)
{
_customerService= menuService;
_customerService.ValidationDictionary = new ModelStateWrapper(this.ModelState);
_customerService= sportsService;
}