Asp.net-Mvc
以強類型方式獲取屬性的 [DisplayName] 屬性
再會!
我有這樣的方法來獲取
[DisplayName]屬性的屬性值(直接附加或使用[MetadataType]屬性)。我在需要[DisplayName]輸入控制器程式碼的極少數情況下使用它。public static class MetaDataHelper { public static string GetDisplayName(Type dataType, string fieldName) { // First look into attributes on a type and it's parents DisplayNameAttribute attr; attr = (DisplayNameAttribute)dataType.GetProperty(fieldName).GetCustomAttributes(typeof(DisplayNameAttribute), true).SingleOrDefault(); // Look for [MetadataType] attribute in type hierarchy // http://stackoverflow.com/questions/1910532/attribute-isdefined-doesnt-see-attributes-applied-with-metadatatype-class if (attr == null) { MetadataTypeAttribute metadataType = (MetadataTypeAttribute)dataType.GetCustomAttributes(typeof(MetadataTypeAttribute), true).FirstOrDefault(); if (metadataType != null) { var property = metadataType.MetadataClassType.GetProperty(fieldName); if (property != null) { attr = (DisplayNameAttribute)property.GetCustomAttributes(typeof(DisplayNameAttribute), true).SingleOrDefault(); } } } return (attr != null) ? attr.DisplayName : String.Empty; } }它有效,但有兩個缺點:
- 它需要欄位名稱作為字元串
- 如果我想獲得財產的財產,它不起作用
是否可以使用 lambdas 來克服這兩個問題,就像我們在 ASP.NET MVC 中遇到的那樣:
Html.LabelFor(m => m.Property.Can.Be.Very.Complex.But.Strongly.Typed);更新
這是來自BuildStarted解決方案的更新和檢查版本。修改為使用
DisplayName屬性(如果使用,可以修改回Display屬性)。並修復了小錯誤以獲取嵌套屬性的屬性。public static string GetDisplayName<TModel>(Expression<Func<TModel, object>> expression) { Type type = typeof(TModel); string propertyName = null; string[] properties = null; IEnumerable<string> propertyList; //unless it's a root property the expression NodeType will always be Convert switch (expression.Body.NodeType) { case ExpressionType.Convert: case ExpressionType.ConvertChecked: var ue = expression.Body as UnaryExpression; propertyList = (ue != null ? ue.Operand : null).ToString().Split(".".ToCharArray()).Skip(1); //don't use the root property break; default: propertyList = expression.Body.ToString().Split(".".ToCharArray()).Skip(1); break; } //the propert name is what we're after propertyName = propertyList.Last(); //list of properties - the last property name properties = propertyList.Take(propertyList.Count() - 1).ToArray(); //grab all the parent properties foreach (string property in properties) { PropertyInfo propertyInfo = type.GetProperty(property); type = propertyInfo.PropertyType; } DisplayNameAttribute attr; attr = (DisplayNameAttribute)type.GetProperty(propertyName).GetCustomAttributes(typeof(DisplayNameAttribute), true).SingleOrDefault(); // Look for [MetadataType] attribute in type hierarchy // http://stackoverflow.com/questions/1910532/attribute-isdefined-doesnt-see-attributes-applied-with-metadatatype-class if (attr == null) { MetadataTypeAttribute metadataType = (MetadataTypeAttribute)type.GetCustomAttributes(typeof(MetadataTypeAttribute), true).FirstOrDefault(); if (metadataType != null) { var property = metadataType.MetadataClassType.GetProperty(propertyName); if (property != null) { attr = (DisplayNameAttribute)property.GetCustomAttributes(typeof(DisplayNameAttribute), true).SingleOrDefault(); } } } return (attr != null) ? attr.DisplayName : String.Empty; }
有兩種方法可以做到這一點:
Models.Test test = new Models.Test(); string DisplayName = test.GetDisplayName(t => t.Name); string DisplayName = Helpers.GetDisplayName<Models.Test>(t => t.Name);第一個是通過為任何 TModel(所有類型)編寫通用擴展方法來工作的。這意味著它將可用於任何對象,而不僅僅是您的模型。不是很推薦,但很好,因為它的語法簡潔。
第二種方法要求您傳入模型的類型 - 您已經在執行此操作,但將其作為參數。這個方法需要通過泛型定義類型,因為 Func 需要它。
以下是您檢查的方法。
所有對象的靜態擴展方法
public static string GetDisplayName<TModel, TProperty>(this TModel model, Expression<Func<TModel, TProperty>> expression) { Type type = typeof(TModel); MemberExpression memberExpression = (MemberExpression)expression.Body; string propertyName = ((memberExpression.Member is PropertyInfo) ? memberExpression.Member.Name : null); // First look into attributes on a type and it's parents DisplayAttribute attr; attr = (DisplayAttribute)type.GetProperty(propertyName).GetCustomAttributes(typeof(DisplayAttribute), true).SingleOrDefault(); // Look for [MetadataType] attribute in type hierarchy // http://stackoverflow.com/questions/1910532/attribute-isdefined-doesnt-see-attributes-applied-with-metadatatype-class if (attr == null) { MetadataTypeAttribute metadataType = (MetadataTypeAttribute)type.GetCustomAttributes(typeof(MetadataTypeAttribute), true).FirstOrDefault(); if (metadataType != null) { var property = metadataType.MetadataClassType.GetProperty(propertyName); if (property != null) { attr = (DisplayAttribute)property.GetCustomAttributes(typeof(DisplayNameAttribute), true).SingleOrDefault(); } } } return (attr != null) ? attr.Name : String.Empty; }類型特定方法的簽名 - 與上面相同的程式碼只是不同的呼叫
public static string GetDisplayName<TModel>(Expression<Func<TModel, object>> expression) { }您不能單獨使用
Something.GetDisplayName(t => t.Name)它的原因是因為在 Razor 引擎中您實際上是在傳遞一個實例化對象,HtmlHelper<TModel>這就是第一個方法需要實例化對象的原因 - 這只需要編譯器推斷屬於哪些類型哪個通用名稱。使用遞歸屬性更新
public static string GetDisplayName<TModel>(Expression<Func<TModel, object>> expression) { Type type = typeof(TModel); string propertyName = null; string[] properties = null; IEnumerable<string> propertyList; //unless it's a root property the expression NodeType will always be Convert switch (expression.Body.NodeType) { case ExpressionType.Convert: case ExpressionType.ConvertChecked: var ue = expression.Body as UnaryExpression; propertyList = (ue != null ? ue.Operand : null).ToString().Split(".".ToCharArray()).Skip(1); //don't use the root property break; default: propertyList = expression.Body.ToString().Split(".".ToCharArray()).Skip(1); break; } //the propert name is what we're after propertyName = propertyList.Last(); //list of properties - the last property name properties = propertyList.Take(propertyList.Count() - 1).ToArray(); //grab all the parent properties Expression expr = null; foreach (string property in properties) { PropertyInfo propertyInfo = type.GetProperty(property); expr = Expression.Property(expr, type.GetProperty(property)); type = propertyInfo.PropertyType; } DisplayAttribute attr; attr = (DisplayAttribute)type.GetProperty(propertyName).GetCustomAttributes(typeof(DisplayAttribute), true).SingleOrDefault(); // Look for [MetadataType] attribute in type hierarchy // http://stackoverflow.com/questions/1910532/attribute-isdefined-doesnt-see-attributes-applied-with-metadatatype-class if (attr == null) { MetadataTypeAttribute metadataType = (MetadataTypeAttribute)type.GetCustomAttributes(typeof(MetadataTypeAttribute), true).FirstOrDefault(); if (metadataType != null) { var property = metadataType.MetadataClassType.GetProperty(propertyName); if (property != null) { attr = (DisplayAttribute)property.GetCustomAttributes(typeof(DisplayNameAttribute), true).SingleOrDefault(); } } } return (attr != null) ? attr.Name : String.Empty; }