了解 aspnet core 中的元数据
Understanding metadata in aspnet core
我从这里被重定向:https://github.com/aspnet/AspNetCore/issues/11963
我正在从 .Net 4.6 转换解决方案,我正在查看元数据。
在旧的解决方案中,我有一个数据注释元数据提供程序的自定义实现,我已经像这样扩展了....
public class ApiMetadataProvider : DataAnnotationsModelMetadataProvider, IDisposable
{
public IResourceProvider ResourceProvider { get; }
public ICoreDataContext CoreDb { get; }
public ApiMetadataProvider(IResourceProvider resourceProvider, ICoreDataContext core)
{
ResourceProvider = resourceProvider;
CoreDb = core;
}
protected override ModelMetadata CreateMetadata(
IEnumerable<Attribute> attributes,
Type containerType,
Func<object> modelAccessor,
Type modelType,
string propertyName)
{
ModelMetadata modelMetadata = base.CreateMetadata(
attributes,
containerType,
modelAccessor,
modelType,
propertyName);
Type serverType = (modelType == typeof(string))
? typeof(string)
: modelType.ImplementsGenericInterface(typeof(IEnumerable<>)) ?? modelType;
if (serverType.IsGenericType && serverType.Name.StartsWith("Nullable") && typeof(Nullable<>).MakeGenericType(serverType.GenericTypeArguments) == serverType) { serverType = serverType.GenericTypeArguments[0]; }
modelMetadata.AdditionalValues.Add("ServerType", serverType.AssemblyQualifiedName);
SetTemplateHint(modelMetadata);
SetCustomAttributes(attributes, modelMetadata, modelType, propertyName);
SetResourceStrings(modelMetadata);
return modelMetadata;
}
....
}
...这里的关键是我提取了给定类型的模型元数据的基本副本,然后以我自己的自定义方式对其进行操作(其中一些在上面的示例中显示)。
我把剩下的剪掉了,因为有很多。
最终结果是,从我自己的基本通用控制器中,我有一个看起来像这样的动作......
protected MetadataContainer GetMetadataForType(Type type)
{
return new MetadataContainer(MetaProvider.GetMetadataForType(null, type));
}
控制者通常会据此做出决定。
我希望重现这种行为,关键是能够从堆栈中获取 "final meta" 的自定义版本(我从中收集到:https://github.com/aspnet/Mvc/issues/2522 ...那个元现在在某种程度上是 "chain of providers")。
所以我有几个问题....
如何在给定类型的元信息中添加或删除/更新自定义 "properties" / 属性?
在执行所有提供程序后,如何获取堆栈视为 "final result" 的元实例?
现有的解决方案通常将此元信息传递给客户端 JS 代码以允许在浏览器中使用 "dynamic component construction",这种情况是否具有任何形式的最佳实践,我可以从中收集更多建议(也许你们有博客 post 或其他让我开始的东西)?
最后答案很简单...
不要费心做任何这些,构建反射派生信息的缓存,并在控制器中提供它。
这基本上只是意味着这是一个简单的反射代码,用于提取所需的相关类型信息。
我从这里被重定向:https://github.com/aspnet/AspNetCore/issues/11963
我正在从 .Net 4.6 转换解决方案,我正在查看元数据。
在旧的解决方案中,我有一个数据注释元数据提供程序的自定义实现,我已经像这样扩展了....
public class ApiMetadataProvider : DataAnnotationsModelMetadataProvider, IDisposable
{
public IResourceProvider ResourceProvider { get; }
public ICoreDataContext CoreDb { get; }
public ApiMetadataProvider(IResourceProvider resourceProvider, ICoreDataContext core)
{
ResourceProvider = resourceProvider;
CoreDb = core;
}
protected override ModelMetadata CreateMetadata(
IEnumerable<Attribute> attributes,
Type containerType,
Func<object> modelAccessor,
Type modelType,
string propertyName)
{
ModelMetadata modelMetadata = base.CreateMetadata(
attributes,
containerType,
modelAccessor,
modelType,
propertyName);
Type serverType = (modelType == typeof(string))
? typeof(string)
: modelType.ImplementsGenericInterface(typeof(IEnumerable<>)) ?? modelType;
if (serverType.IsGenericType && serverType.Name.StartsWith("Nullable") && typeof(Nullable<>).MakeGenericType(serverType.GenericTypeArguments) == serverType) { serverType = serverType.GenericTypeArguments[0]; }
modelMetadata.AdditionalValues.Add("ServerType", serverType.AssemblyQualifiedName);
SetTemplateHint(modelMetadata);
SetCustomAttributes(attributes, modelMetadata, modelType, propertyName);
SetResourceStrings(modelMetadata);
return modelMetadata;
}
....
}
...这里的关键是我提取了给定类型的模型元数据的基本副本,然后以我自己的自定义方式对其进行操作(其中一些在上面的示例中显示)。
我把剩下的剪掉了,因为有很多。
最终结果是,从我自己的基本通用控制器中,我有一个看起来像这样的动作......
protected MetadataContainer GetMetadataForType(Type type)
{
return new MetadataContainer(MetaProvider.GetMetadataForType(null, type));
}
控制者通常会据此做出决定。
我希望重现这种行为,关键是能够从堆栈中获取 "final meta" 的自定义版本(我从中收集到:https://github.com/aspnet/Mvc/issues/2522 ...那个元现在在某种程度上是 "chain of providers")。
所以我有几个问题....
如何在给定类型的元信息中添加或删除/更新自定义 "properties" / 属性? 在执行所有提供程序后,如何获取堆栈视为 "final result" 的元实例? 现有的解决方案通常将此元信息传递给客户端 JS 代码以允许在浏览器中使用 "dynamic component construction",这种情况是否具有任何形式的最佳实践,我可以从中收集更多建议(也许你们有博客 post 或其他让我开始的东西)?
最后答案很简单... 不要费心做任何这些,构建反射派生信息的缓存,并在控制器中提供它。
这基本上只是意味着这是一个简单的反射代码,用于提取所需的相关类型信息。