简体   繁体   English

应将模型联编程序提供者视为服务定位符吗?

[英]Should model binder providers be considered as service locators?

I'd like to provide some custom model binding for my queryable web api, namely for the following interfaces: 我想为我的可查询Web api提供一些自定义模型绑定,即以下接口:

  • IQueryOptions`1
  • ISortingOptions`2 implementing IQueryOptions`1 ISortingOptions`2实现IQueryOptions`1
  • IPagingOptions`2 implementing ISortingOptions`2 IPagingOptions`2实现ISortingOptions`2

Depending on the parameter specified on the controller action, I want to provide the correct model binder. 根据控制器操作上指定的参数,我想提供正确的模型绑定器。

public void Test([ModelBinding] IPagingOptions<MyEntity, int> pagingOptions)
   // -> PagingOptionsModelBinder

My question is: Should there be a model binder provider for each model binder or should the model binder work as service locator and provide a model binder for each type to be bound? 我的问题是:每个模型联编程序都应该有一个模型联编程序提供者,还是应该将模型联编程序用作服务定位器,并为每种要绑定的类型提供一个模型联编程序?

eg. 例如。

public QueryOptionsModelBinderProvider : ModelBinderProvider {

   public override IModelBinder GetBinder(HttpConf...
      if(modelType.IsOfGeneric((typeof(ISortingOptions<,>))
         return new SortingOptionsModelBinder();
      if(modelType.IsOfGeneric((typeof(IPagingOptions<,>))
         return new PagingOptionsModelBinder();
   ...

or... 要么...

public SortingOptionsModelBinderProvider

public PagingOptionsModelBinderProvider

// etc.

I'm asking this because on one hand, service locating is a (horrible, IMHO) anti pattern since for every new type to be bound, I need to alter the model binder provider, but on the other if it isn't being done here, the responsibility of finding the right provider is just delegated to ASP.NET WebApi, where I need to register a new provider everytime. 我之所以这样问是因为,一方面,服务定位是一种(可怕的,恕我直言)反模式,因为对于每种要绑定的新类型,我都需要更改模型绑定程序提供程序,但另一方面,如果未完成在这里,找到合适的提供程序的责任仅委托给ASP.NET WebApi,在这里我需要每次都注册一个新的提供程序。

A clever way I saw once (don't remember where, when I find it I will give its credit) is create a generic model binder: 我曾经看过一个聪明的方法(不记得在哪里,当我发现它时,我会给予它荣誉)是创建一个通用模型绑定器:

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

Then use reflection in the provider: 然后在提供程序中使用反射:

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

After that you just have to register one provider that never changes. 之后,您只需注册一个永不更改的提供商。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM