Asp.net mvc 使用Autofac将服务注入基类
TL;DR:当两个自定义Asp.net mvc 使用Autofac将服务注入基类,asp.net-mvc,dependency-injection,modelbinders,autofac,Asp.net Mvc,Dependency Injection,Modelbinders,Autofac,TL;DR:当两个自定义ModelBinder实现都依赖Autofac向它们注入(公共)依赖项时,如何将它们共享的逻辑整合到一个基类中 在查看我正在处理的ASP.NETMVC项目中的一些代码时,我意识到我有两个自定义模型绑定器,它们基本上做相同的事情。它们都继承自DefaultModelBinder,并且都使用注入其构造函数的IEncodingService对两个独立视图模型类上的单个属性进行编码 public class ResetQuestionAndAnswerViewModelBind
ModelBinder
实现都依赖Autofac向它们注入(公共)依赖项时,如何将它们共享的逻辑整合到一个基类中
在查看我正在处理的ASP.NETMVC项目中的一些代码时,我意识到我有两个自定义模型绑定器,它们基本上做相同的事情。它们都继承自
DefaultModelBinder
,并且都使用注入其构造函数的IEncodingService
对两个独立视图模型类上的单个属性进行编码
public class ResetQuestionAndAnswerViewModelBinder : DefaultModelBinder {
public ResetQuestionAndAnswerViewModelBinder(IEncodingService encodingService) {
encoder = encodingService;
}
private readonly IEncodingService encoder;
public override object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext) {
var model = base.BindModel(controllerContext, bindingContext) as ResetQuestionAndAnswerViewModel;
if (model != null) {
var answer = bindingContext.ValueProvider.GetValue("Answer");
if ((answer != null) && !(answer.AttemptedValue.IsNullOrEmpty())) {
model.Answer = encoder.Encode(answer.AttemptedValue);
}
}
return model;
}
}
public class ConfirmIdentityViewModelBinder : DefaultModelBinder {
public ConfirmIdentityViewModelBinder(IEncodingService encodingService) {
encoder = encodingService;
}
private readonly IEncodingService encoder;
public override object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext) {
var model = base.BindModel(controllerContext, bindingContext) as ConfirmIdentityViewModel;
if (model != null) {
var secretKey = bindingContext.ValueProvider.GetValue("SecretKey");
if ((secretKey != null) && !(secretKey.AttemptedValue.IsNullOrEmpty())) {
model.SecretKeyHash = encoder.Encode(secretKey.AttemptedValue);
}
}
return model;
}
}
我为这两个类编写了一个要从中继承的通用基类:
public class EncodedPropertyModelBinder<TViewModel> : DefaultModelBinder
where TViewModel : class {
public EncodedPropertyModelBinder(IEncodingService encodingService,
string propertyName) {
encoder = encodingService;
property = propertyName;
}
private readonly IEncodingService encoder;
private readonly string property;
public override object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext) {
var model = base.BindModel(controllerContext, bindingContext) as TViewModel;
if (model != null) {
var value = bindingContext.ValueProvider.GetValue(property);
if ((value != null) && !(value.AttemptedValue.IsNullOrEmpty())) {
var encodedValue = encoder.Encode(value.AttemptedValue);
var propertyInfo = model.GetType().GetProperty(property);
propertyInfo.SetValue(model, encodedValue, null);
}
}
return model;
}
}
公共类EncodedPropertyModelBinder:DefaultModelBinder
TViewModel:类的位置{
公共编码属性模型绑定器(IceodingService encodingService,
字符串属性名称){
编码器=编码服务;
property=propertyName;
}
专用只读编码服务编码器;
私有只读字符串属性;
公共覆盖对象绑定模型(ControllerContext ControllerContext,
ModelBindingContext(绑定上下文){
var model=base.BindModel(controllerContext,bindingContext)作为TViewModel;
如果(型号!=null){
var value=bindingContext.ValueProvider.GetValue(属性);
if((value!=null)&&&!(value.AttemptedValue.IsNullOrEmpty()){
var encodedValue=encoder.Encode(value.AttemptedValue);
var propertyInfo=model.GetType().GetProperty(属性);
propertyInfo.SetValue(model,encodedValue,null);
}
}
收益模型;
}
}
使用Autofac,我如何将
IEncodingService
注入基类构造函数,同时强制派生类提供要编码的属性的名称?实际上,我的做法略有不同。这意味着我将封装属性操作的细节,并将不同的实现传递给单个模型绑定器
首先,定义一个表示绑定单个属性的接口:
public interface IPropertyBinder
{
void SetPropertyValue(object model, ModelBindingContext context);
}
然后,使用最初来自encodedpropertypodelbinder
的参数实现它:
public sealed class PropertyBinder : IPropertyBinder
{
private readonly IEncodingService _encodingService;
private readonly string _propertyName;
public PropertyBinder(IEncodingService encodingService, string propertyName)
{
_encodingService = encodingService;
_propertyName = propertyName;
}
public void SetPropertyValue(object model, ModelBindingContext bindingContext)
{
var value = bindingContext.ValueProvider.GetValue(_propertyName);
if(value != null && !value.AttemptedValue.IsNullOrEmpty())
{
var encodedValue = _encodingService.Encode(value.AttemptedValue);
var property = model.GetType().GetProperty(_propertyName);
property.SetValue(model, encodedValue, null);
}
}
}
builder.
Register(c => new EncodedPropertyModelBinder(new PropertyBinder(c.Resolve<IEncodingService>(), "Answer")))
.Named<EncodedPropertyModelBinder>("AnswerBinder");
builder.
Register(c => new EncodedPropertyModelBinder(new PropertyBinder(c.Resolve<IEncodingService>(), "SecretKey")))
.Named<EncodedPropertyModelBinder>("SecretKeyBinder");
接下来,使用新接口实现encodedpropertypodelbinder
:
public class EncodedPropertyModelBinder : DefaultModelBinder
{
private readonly IPropertyBinder _propertyBinder;
public EncodedPropertyModelBinder(IPropertyBinder propertyBinder)
{
_propertyBinder = propertyBinder;
}
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var model = base.BindModel(controllerContext, bindingContext);
if(model != null)
{
_propertyBinder.SetPropertyValue(model, bindingContext);
}
return model;
}
}
最后,使用Autofac命名实例注册视图模型的两个版本,传入不同的PropertyBinder
配置:
public sealed class PropertyBinder : IPropertyBinder
{
private readonly IEncodingService _encodingService;
private readonly string _propertyName;
public PropertyBinder(IEncodingService encodingService, string propertyName)
{
_encodingService = encodingService;
_propertyName = propertyName;
}
public void SetPropertyValue(object model, ModelBindingContext bindingContext)
{
var value = bindingContext.ValueProvider.GetValue(_propertyName);
if(value != null && !value.AttemptedValue.IsNullOrEmpty())
{
var encodedValue = _encodingService.Encode(value.AttemptedValue);
var property = model.GetType().GetProperty(_propertyName);
property.SetValue(model, encodedValue, null);
}
}
}
builder.
Register(c => new EncodedPropertyModelBinder(new PropertyBinder(c.Resolve<IEncodingService>(), "Answer")))
.Named<EncodedPropertyModelBinder>("AnswerBinder");
builder.
Register(c => new EncodedPropertyModelBinder(new PropertyBinder(c.Resolve<IEncodingService>(), "SecretKey")))
.Named<EncodedPropertyModelBinder>("SecretKeyBinder");
builder。
寄存器(c=>newencodedpropertypodelbinder(newpropertybinder(c.Resolve(),“Answer”))
.命名为(“AnswerBinder”);
建设者
寄存器(c=>newencodedpropertypodelbinder(newpropertybinder(c.Resolve(),“SecretKey”))
.命名为(“SecretKeyBinder”);