[英]How bad is to use reflection in a ModelValidationProvider?
我目前正在嘗試尋找一種方法來簡化DataAnnotations中的ErrorMessage的使用。 在閱讀了該主題之后,最常見的解決方案(基於每個Attribute創建一個類並自動定義ErrorMessageResourceName和ErrorMessageResourceType)使我不滿意。 因此,我決定重寫ModelValidationProvider來這樣做。
不幸的是,我在解決方案中不得不求助於Reflection,並且我很清楚這種技術的性能成本。 我已經在考慮“緩存”每個modelValidator的屬性信息,這樣我就不必每次都運行GetProperties。 還有其他關於使用這種方法的建議/批評嗎?
public class LocalizedDataAnnotationsModelValidatorProvider : DataAnnotationsModelValidatorProvider
{
protected override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable<Attribute> attributes)
{
var baseReturn = base.GetValidators(metadata, context, attributes);
var resourceManager = Validation.ResourceManager;
var culture = Thread.CurrentThread.CurrentUICulture;
foreach (var modelValidator in baseReturn)
{
var type = modelValidator.GetType();
var attributeProp = type.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(x => x.Name == "Attribute");
var attribute = attributeProp.GetValue(modelValidator, null) as ValidationAttribute;
if (attribute != null)
{
if (string.IsNullOrEmpty(attribute.ErrorMessage))
{
var attributeName = attribute.GetType().Name.Replace("Attribute", string.Empty);
attribute.ErrorMessage = resourceManager.GetString(attributeName, culture);
}
}
}
return baseReturn;
}
}
好吧,緩存屬性信息是一種方法,但是我建議您研究Reflection.Emit。
這是一個很好的示例,如何加速動態屬性訪問(而不是標准反射GetValue): HyperDescriptor:加速的動態屬性訪問
通過使用Reflection.Emit,您將獲得更好的性能。
當您可以做時,我看不到您從反思中學到了什么:
foreach(baseReturn中的var modelValidator){if(modelValidator是DataAnnotationsModelValidator){var attribute =(((DataAnnotationsModelValidator)modelValidator).Attribute; if(attribute!= null && string.IsNullOrEmpty(attribute.ErrorMessage)){var attributeName = attribute.GetType()。Name.Replace(“ Attribute”,string.Empty); attribute.ErrorMessage = resourceManager.GetString(attributeName,文化); }}}}
更新,這不起作用,因為Attribute
屬性是protected internal
。 但是,您仍然可以:
foreach(var validationAttribute in attributes.OfType<ValidationAttribute>()){
var attributeName = attribute.GetType().Name.Replace("Attribute", string.Empty);
attribute.ErrorMessage = resourceManager.GetString(attributeName, culture);
}
一點也不差。 不用擔心
使用類似的技術,我很少會因反射而產生60ms以上的開銷。 不要過早優化。
該應用程序投入生產后,幾乎可以肯定,您可以從優化存儲過程和媒體文件大小以提高加載時間方面獲得更多收益。
您最好/最簡單的選擇是在應用程序啟動時遍歷程序集並緩存您可以執行的操作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.