前言
上回说到,我们实现了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】,邀你加入技术交流群