Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/14.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
Asp.net mvc 使用Autofac将服务注入基类_Asp.net Mvc_Dependency Injection_Modelbinders_Autofac - Fatal编程技术网

Asp.net mvc 使用Autofac将服务注入基类

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

TL;DR:当两个自定义
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”);