我想为可查询的web api提供一些自定义模型绑定,即以下接口:
IQueryOptions`1
ISortingOptions`2
实施IQueryOptions`1
IPagingOptions`2
实施ISortingOptions`2
根据控制器操作中指定的参数,我想提供正确的模型绑定器。
public void Test([ModelBinding] IPagingOptions<MyEntity, int> pagingOptions)
// -> PagingOptionsModelBinder
我的问题是:每个模型绑定器是否应该有一个模型绑定器提供程序,或者模型绑定器是否应该作为服务定位器工作,并为每个要绑定的类型提供模型绑定器?
e.g ..
public QueryOptionsModelBinderProvider : ModelBinderProvider {
public override IModelBinder GetBinder(HttpConf...
if(modelType.IsOfGeneric((typeof(ISortingOptions<,>))
return new SortingOptionsModelBinder();
if(modelType.IsOfGeneric((typeof(IPagingOptions<,>))
return new PagingOptionsModelBinder();
...
...或
public SortingOptionsModelBinderProvider
public PagingOptionsModelBinderProvider
// etc.
我问这个是因为一方面,服务定位是一个(可怕的,恕我直言)反模式,因为对于每个要绑定的新类型,我需要改变模型绑定器提供者,但另一方面,如果它不是'在这里完成,找到合适的提供者的责任只是委托给ASP.NET WebApi,我需要每次都注册一个新的提供者。
答案 0 :(得分:2)
我曾经看过一个聪明的方式(不记得在哪里,当我找到它时我会赞同它)是创建一个通用的模型绑定器:
public class EntityModelBinder<TEntity>
: IModelBinder
where TEntity : Entity
{
private readonly IRepository<TEntity> _repository;
public EntityModelBinder(IRepository<TEntity> repository)
{
_repository = repository;
}
public object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext)
{
ValueProviderResult value = bindingContext
.ValueProvider.GetValue(bindingContext.ModelName);
var id = Guid.Parse(value.AttemptedValue);
var entity = _repository.GetById(id);
return entity;
}
}
然后在提供者中使用反射:
public class EntityModelBinderProvider
: IModelBinderProvider
{
public IModelBinder GetBinder(Type modelType)
{
if (!typeof(Entity).IsAssignableFrom(modelType))
return null;
Type modelBinderType = typeof(EntityModelBinder<>)
.MakeGenericType(modelType);
var modelBinder = ObjectFactory.GetInstance(modelBinderType);
return (IModelBinder) modelBinder;
}
}
之后,您只需注册一个永不改变的提供商。