gpt4 book ai didi

asp.net-mvc - 使用 Autofac 将服务注入(inject)基类

转载 作者:行者123 更新时间:2023-12-04 06:42:19 24 4
gpt4 key购买 nike

TL;DR: 如何合并两个自定义 ModelBinder 共享的逻辑实现到单个基类中,当两个实现都依赖 Autofac 向它们注入(inject)(公共(public))依赖项时?

在查看我正在处理的 ASP.NET MVC 项目中的一些代码时,我意识到我有两个自定义模型绑定(bind)器,它们基本上做同样的事情。它们都继承自 DefaultModelBinder ,并且它们都使用 IEncodingService 对两个单独的 View 模型类上的单个属性进行编码注入(inject)到它们的构造函数中。

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;
}
}

使用 Autofac,我将如何注入(inject) IEncodingService进入基类构造函数,同时强制派生类提供要编码的属性名称?

最佳答案

我实际上会稍微不同地处理这个问题,favoring composition over inheritance .这意味着我将封装属性操作的细节,并将不同的实现传递给单个模型绑定(bind)器。

首先,定义一个表示绑定(bind)单个属性的接口(interface):

public interface IPropertyBinder
{
void SetPropertyValue(object model, ModelBindingContext context);
}

然后,使用来自 EncodedPropertyModelBinder 的参数来实现它:
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);
}
}
}

接下来,执行 EncodedPropertyModelBinder使用新界面:
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命名实例注册两个版本的 View 模型,传入 PropertyBinder的不同配置:
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");

关于asp.net-mvc - 使用 Autofac 将服务注入(inject)基类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4088716/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com