模型活页夹提供者是否应该被视为服务定位器?
Should model binder providers be considered as service locators?
我想为我的可查询网站 api 提供一些自定义模型绑定,即以下接口:
IQueryOptions`1
ISortingOptions`2
实施 IQueryOptions`1
IPagingOptions`2
实施 ISortingOptions`2
根据控制器操作上指定的参数,我想提供正确的模型绑定器。
public void Test([ModelBinding] IPagingOptions<MyEntity, int> pagingOptions)
// -> PagingOptionsModelBinder
我的问题是:每个模型绑定器是否应该有一个模型绑定器提供程序,或者模型绑定器是否应该作为服务定位器并为每个要绑定的类型提供一个模型绑定器?
例如..
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,我每次都需要在其中注册一个新的提供者。
我曾经看到过一个聪明的方法(不记得在哪里,当我找到它时我会赞扬它)是创建一个通用模型活页夹:
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;
}
}
之后您只需注册一个永不更改的提供商。
我想为我的可查询网站 api 提供一些自定义模型绑定,即以下接口:
IQueryOptions`1
ISortingOptions`2
实施IQueryOptions`1
IPagingOptions`2
实施ISortingOptions`2
根据控制器操作上指定的参数,我想提供正确的模型绑定器。
public void Test([ModelBinding] IPagingOptions<MyEntity, int> pagingOptions)
// -> PagingOptionsModelBinder
我的问题是:每个模型绑定器是否应该有一个模型绑定器提供程序,或者模型绑定器是否应该作为服务定位器并为每个要绑定的类型提供一个模型绑定器?
例如..
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,我每次都需要在其中注册一个新的提供者。
我曾经看到过一个聪明的方法(不记得在哪里,当我找到它时我会赞扬它)是创建一个通用模型活页夹:
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;
}
}
之后您只需注册一个永不更改的提供商。