C# 模型绑定器提供者是否应被视为服务定位器?

C# 模型绑定器提供者是否应被视为服务定位器?,c#,asp.net,design-patterns,asp.net-web-api,model-binding,C#,Asp.net,Design Patterns,Asp.net Web Api,Model Binding,我想为我的可查询web api提供一些自定义模型绑定,即为以下接口: IQueryOptions`1 ISortingOptions`2implementingIQueryOptions`1 IPagingOptions`2实施ISortingOptions`2 根据控制器操作上指定的参数,我希望提供正确的模型绑定器 public void Test([ModelBinding] IPagingOptions<MyEntity, int> pagingOptions) //

我想为我的可查询web api提供一些自定义模型绑定,即为以下接口:

  • IQueryOptions`1
  • ISortingOptions`2
    implementing
    IQueryOptions`1
  • IPagingOptions`2
    实施
    ISortingOptions`2
根据控制器操作上指定的参数,我希望提供正确的模型绑定器

public void Test([ModelBinding] IPagingOptions<MyEntity, int> pagingOptions)
   // -> PagingOptionsModelBinder
我这样问是因为一方面,服务定位是一种(可怕的,IMHO)反模式,因为对于要绑定的每一种新类型,我都需要更改模型绑定器提供程序,但另一方面,如果没有在这里完成,则查找正确提供程序的责任只会委托给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;
    }
}
公共类EntityModelBinder
:IModelBinder
其中tenty:实体
{
专用只读IRepository存储库;
公共EntityModelBinder(IRepository存储库)
{
_存储库=存储库;
}
公共对象绑定模型(ControllerContext ControllerContext,
ModelBindingContext(绑定上下文)
{
ValueProviderResult值=bindingContext
.ValueProvider.GetValue(bindingContext.ModelName);
var id=Guid.Parse(value.AttemptedValue);
var entity=\u repository.GetById(id);
返回实体;
}
}
然后在提供程序中使用反射:

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;
    }
}
公共类EntityModelBinder提供程序
:IModelBinderProvider
{
公共IModelBinder GetBinder(类型modelType)
{
如果(!typeof(Entity).IsAssignableFrom(modelType))
返回null;
类型modelBinderType=typeof(EntityModelBinder)
.MakeGenericType(模型类型);
var modelBinder=ObjectFactory.GetInstance(modelBinderType);
返回(IModelBinder)modelBinder;
}
}

之后,您只需注册一个永不更改的提供程序。

这来自Jimmy Bogards的文章“智能模型绑定与模型绑定提供程序”@LosTechies:;)伟大的感谢吉米·博加德斯。:)这个解决方案对您不起作用吗?您有什么问题吗?为了涵盖希望使用WebAPI而不是MVC的用户:
config.Services.Insert(typeof(ModelBinderProvider),0,new MyModelBinderProvider())其中
MyModelBinderProvider:ModelBinderProvider
而不是
MyModelBinderProvider:IModelBinderProvider
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;
    }
}