gpt4 book ai didi

使用接口(interface)而不是具体类进行 ASP.NET Web API 操作

转载 作者:行者123 更新时间:2023-12-01 22:25:46 25 4
gpt4 key购买 nike

我的团队需要为我们的公司和使用该框架的产品开发一个框架。必要条件之一是可以为特定客户定制产品,但应该可以轻松地使用同一产品的另一个版本进行更新(不是自动更新)。

我们正在使用 ASP.NET MVC 4 + Web API(目前,明年将基于我们的框架创建桌面产品)、NHibernate、使用 Autofac 作为 DI 容器和 N 层的大量 IoC。

因此,在 WebApp 的某些方面,我们使用 ViewModel 作为具有一个默认实现的接口(interface),并使用 Autofac 来链接它们,这在未来的自定义中很容易更改。

在 ASP.NET MVC 中,我们实现了 IModelBinderProvider 并创建继承 DefaultModelBinder 的自定义类:

类似这样的事情:

public class MyCustomMVCModelBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(Type modelType)
{
if (modelType.IsInterface)
return new MyCustomMVCModelBinder();

return new DefaultModelBinder();
}
}
public class MyCustomMVCModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var context = new ModelBindingContext(bindingContext);
var item = DependencyResolver.Current.GetService(bindingContext.ModelType);

Func<object> modelAccessor = () => item;
context.ModelMetadata = new ModelMetadata(new DataAnnotationsModelMetadataProvider(),
bindingContext.ModelMetadata.ContainerType, modelAccessor, item.GetType(), bindingContext.ModelName);

return base.BindModel(controllerContext, context);
}
}

在我的 Controller 中,我只使用接口(interface)作为参数。因此,它工作正常,因为值填充正确。

但是,如何在 Web API 中使用正确绑定(bind)的值执行相同操作?我尝试实现IModelBinder并继承ModelBinderProvider。我可以获得接口(interface)实现的实例,但未填充值。

这是 WebAPI 中的尝试实现:

public class MyCustomWebAPIModelBinderProvider : ModelBinderProvider
{
public override IModelBinder GetBinder(System.Web.Http.HttpConfiguration configuration, Type modelType)
{
return new MyCustomWebAPIModelBinder();
}
}

public class MyCustomWebAPIModelBinder : IModelBinder
{
public bool BindModel(System.Web.Http.Controllers.HttpActionContext actionContext, ModelBindingContext bindingContext)
{
if (bindingContext.ModelType.IsInterface)
{
var item = GlobalConfiguration.Configuration.DependencyResolver.GetService(bindingContext.ModelType);

if (item != null)
{
Func<object> modelAccessor = () => item;
var a = bindingContext.ModelMetadata.ContainerType;
var b = modelAccessor;
var c = item.GetType();
var d = bindingContext.ModelName;

bindingContext.ModelMetadata = new ModelMetadata(new DataAnnotationsModelMetadataProvider(), a, b, c, d);

bindingContext.Model = item;

return true;
}
}

return false;
}
}

我错过了什么?是否可以做我们想要的事情?

最佳答案

不使用 ModelBinder,而是使用 MediaTypeFormatter 的实现。

您可以重写方法“ReadFromStreamAsync”并将类型更改为您需要的任何类型。

在下面的示例中,通过使用 MVC 的 DependencyResolver 解析具体类型来更改类型,这对于 WebAPI 效果很好。



public class CustomFormUrlEncodedMediaTypeFormatter : FormUrlEncodedMediaTypeFormatter
{
public CustomFormUrlEncodedMediaTypeFormatter() : base() { }

public override Task ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
{
if (type.IsInterface)
type = GetConcreteType(type);

return base.ReadFromStreamAsync(type, readStream, content, formatterLogger);
}

public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
{
if (type.IsInterface)
type = GetConcreteType(type);

return base.WriteToStreamAsync(type, value, writeStream, content, transportContext);
}

private Type GetConcreteType(Type type)
{
object concrete = System.Web.Mvc.DependencyResolver.Current.GetService(type);
return concrete.GetType();
}
}

如果您想使用 JsonFormatter 来做到这一点,那么为 Json.NET 创建“CustomCreationConverter”是一个更好的方法,而不是它们可以解决您界面中所有子对象的依赖关系。



public class DomainConverter : CustomCreationConverter
{
public DomainConverter() { }

public override bool CanConvert(Type objectType)
{
return objectType.IsInterface;
}

public override object Create(Type objectType)
{
return System.Web.Mvc.DependencyResolver.Current.GetService(objectType);
}
}

关于使用接口(interface)而不是具体类进行 ASP.NET Web API 操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17119073/

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