前言
上回说到,我们实现了IntArrayModelBinder
,可以让 ASP.NET Core 绑定查询字符串中的数组。但是必须显示指定ModelBinder
:
public string Get([FromQuery][ModelBinder(BinderType = typeof(IntArrayModelBinder))] int[] values)
而官方提供的ByteArrayModelBinder
不需要指定ModelBinder
即可生效:
public string Get([FromQuery]byte[] values)
那么,它是如何做到的呢?
ByteArrayModelBinderProvider
在源码中查找ByteArrayModelBinder
的所有引用。发现只有一处使用:
public class ByteArrayModelBinderProvider : IModelBinderProvider
{/// <inheritdoc />public IModelBinder? GetBinder(ModelBinderProviderContext context){if (context == null){throw new ArgumentNullException(nameof(context));}if (context.Metadata.ModelType == typeof(byte[])){var loggerFactory = context.Services.GetRequiredService<ILoggerFactory>();return new ByteArrayModelBinder(loggerFactory);}return null;}
}
MvcCoreMvcOptionsSetup
继续查找ByteArrayModelBinderProvider
的所有引用。发现也只有一处使用:
internal class MvcCoreMvcOptionsSetup : IConfigureOptions<MvcOptions>, IPostConfigureOptions<MvcOptions>
{public void Configure(MvcOptions options){...options.ModelBinderProviders.Add(new ByteArrayModelBinderProvider());...}
}
那么,现在的思路就是,实现IntArrayModelBinderProvider
,然后调用options.ModelBinderProviders.Add(new IntArrayModelBinderProvider());
。
现在,关键就在于这个MvcOptions
在哪访问?
AddControllers 方法
继续查找MvcOptions
的所有引用。发现使用的地方不少,但是,其中有一个扩展方法:
public static IMvcBuilder AddControllers(this IServiceCollection services, Action<MvcOptions>? configure)
而IServiceCollection
是可以在 Startup.cs 中访问的:
public void ConfigureServices(IServiceCollection services)
实现
接下来就好办了。
实现
IntArrayModelBinderProvider
:
public class IntArrayModelBinderProvider : IModelBinderProvider
{ public IModelBinder? GetBinder(ModelBinderProviderContext context){if (context == null){throw new ArgumentNullException(nameof(context));}if (context.Metadata.ModelType == typeof(int[])){return new IntArrayModelBinder();}return null;}
}
修改 Startup.cs:
public void ConfigureServices(IServiceCollection services)
{services.AddControllers(options =>{options.ModelBinderProviders.Insert(0, new IntArrayModelBinderProvider());});
}
测试一下,执行成功:
[HttpGet]
public string Get([FromQuery]int[] values)
{return string.Join(" ", values.Select(p => p.ToString()));
}
结论
通过IntArrayModelBinderProvider
,我们无需显示指定ModelBinder
。即可让 ASP.NET Core 自动使用IntArrayModelBinder
。
添加微信号【MyIO666】,邀你加入技术交流群