IMetadataDetailsProvider
并不是“一个”接口,而是所有“模型元数据提供器”的统称/标记接口。它本身空无一物,真正的职责由下面三个“子接口”分担:
-
IBindingMetadataProvider
→ 决定“能不能绑、谁来绑” -
IDisplayMetadataProvider
→ 决定“显示名、模板、顺序” -
IValidationMetadataProvider
→ 决定“要验证什么、用什么规则”
框架在第一次遇到某个类型或属性时,会依次调用这些接口的实现,把收集到的“细节”写进同一个
ModelMetadata
对象,然后缓存起来供整个 ASP.NET Core 管道使用。-
定义——空接口,只是“标记”
public interface IMetadataDetailsProvider { }
文档原话:
“有关模型对象的元数据详细信息提供程序的标记接口。实现应实现
“有关模型对象的元数据详细信息提供程序的标记接口。实现应实现
IBindingMetadataProvider
、IDisplayMetadataProvider
和 IValidationMetadataProvider
中的一个或多个。”
-
工作位置——在
ModelMetadata
被创建时
-
启动阶段:
DefaultModelMetadataProvider
反射拿到类型/属性 → 新建MetadataDetails
对象。 -
运行阶段:
把MvcOptions.ModelMetadataDetailsProviders
集合里所有实现了上述子接口的实例跑一遍,让它们往Details
里写数据。 -
合成阶段:
用写满的Details
构造出最终的ModelMetadata
并全局缓存。
-
常见“真身”——你写的其实就是这三个
表格
子接口 | 典型用途 | 关键方法 |
---|---|---|
IBindingMetadataProvider |
禁用绑定、指定自定义绑定器 | void CreateBindingMetadata(BindingMetadataProviderContext) |
IDisplayMetadataProvider |
改 DisplayName、模板、顺序 | void CreateDisplayMetadata(DisplayMetadataProviderContext) |
IValidationMetadataProvider |
动态加验证特性 | void CreateValidationMetadata(ValidationMetadataProviderContext) |
一个类可以同时实现多个接口,一次性把绑定+显示+验证的规则全部注入。
-
代码例子——让所有
string
属性自动拥有[StringLength(100)]
public class StringLength100Provider : IValidationMetadataProvider
{public void CreateValidationMetadata(ValidationMetadataProviderContext ctx){if (ctx.Key.ModelType == typeof(string) &&!ctx.ValidationMetadata.ValidatorMetadata.OfType<StringLengthAttribute>().Any()){ctx.ValidationMetadata.ValidatorMetadata.Add(new StringLengthAttribute(100));}}
}// 全局注册
builder.Services.AddMvc(o =>o.ModelMetadataDetailsProviders.Add(new StringLength100Provider()));
注册后,任何实体类的
string
属性都会凭空多一条 StringLength(100)
验证,无需在实体上硬编码特性。-
一句话总结
IMetadataDetailsProvider
就是 ASP.NET Core 模型绑定/验证/显示管线里的“插件总线”——你自己实现它的三个子接口中的任意组合,再扔进
MvcOptions.ModelMetadataDetailsProviders
,就能在不改动实体类的前提下,全局、动态、按需地注入绑定规则、显示文案或验证逻辑。