【问题标题】:Can the DisplayName attribute be accessed without using MVC?可以不使用 MVC 访问 DisplayName 属性吗?
【发布时间】:2011-06-21 14:33:49
【问题描述】:

我使用 lambda 表达式为 List 重构了一个通用 CSV 构建器以访问正确的值

public static string ToCsv<TModel>(this List<TModel> list, string delimiter, string lineBreak, string valueWrap, params Expression<Func<TModel, object>>[] expressions)
{
  var sb = new StringBuilder();

  var headers = expressions.Select(m => String.Format("{0}{1}{0}", valueWrap, GetPropertyName(m))).ToArray();
  sb.Append(String.Format("{0}{1}", String.Join(delimiter, headers), lineBreak));

  foreach (var listItem in list)
  {
    var values = expressions.Select(m => String.Format("{0}{1}{0}", valueWrap, m.Compile()(listItem))).ToArray();
    sb.Append(String.Format("{0}{1}", String.Join(delimiter, values), lineBreak));
  }

  return sb.ToString();
}

这很好用,但是因为我正试图将它移动到一些通用代码中,以便跨多个服务器访问多个项目。我无法引用System.Web.Mvc 程序集

有没有访问DisplayName属性的好方法,如果不存在,访问变量名?

我当前尝试访问((MemberExpression) expression.Body).Member.Name 但是如果它必须将值转换为字符串,它将无法正常工作。 (即传递一个 int 并隐式转换)

第二次迭代属性的尝试对内部类不起作用(即model => model.innerClass.property

【问题讨论】:

  • 更多信息:在没有解决方案之后,我继续使用System.Web.Mvc.ExpressionHelper,但是我遇到了另一个问题。如果没有 HtmlHelper 及其 ViewData,它将无法获取属性的 DisplayName Attribute。有什么想法吗?

标签: c# asp.net-mvc linq reflection extension-methods


【解决方案1】:

通过几个简单的辅助函数,您可以消除对 System.Web.Mvc 程序集的所有引用。您还会在下面的示例中注意到 (model => model.member.property) 有效。

using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Linq.Expressions;
using System.ComponentModel;
using System.Reflection;

namespace Test
{
    public class Program
    {
        public static void Main(string[] args)
        {
            List<Class1> foobars = new List<Class1>();
            foobars.Add(new Class1 { Foo = "Hello world!", Bar = -1, Skip = false, Ref = new Class2 { ToBe = true } });

            string result = foobars.ToCsv(",", Environment.NewLine, "\"", m => m.Foo, m => m.Bar, m => m.Ref.ToBe);
        }

        public class Class1
        {
            [DisplayName("Foo Property")]
            public string Foo { get; set; }

            public int Bar { get; set; }

            [DisplayName("Skipped Property")]
            public bool Skip { get; set; }

            [DisplayName("Reference")]
            public Class2 Ref { get; set; }
        }

        public class Class2
        {
            [DisplayName("To Be or Not To Be")]
            public bool ToBe { get; set; }
        }
    }

    public static class Extensions
    {
        public static string ToCsv<TModel>(this List<TModel> list, string delimiter, string lineBreak, string valueWrap, params Expression<Func<TModel, object>>[] expressions)
        {
            var sb = new StringBuilder();

            var headers = expressions.Select(m => String.Format("{0}{1}{0}", valueWrap, GetDisplayName(m))).ToArray();
            sb.Append(String.Format("{0}{1}", String.Join(delimiter, headers), lineBreak));

            foreach (var listItem in list)
            {
                var values = expressions.Select(m => String.Format("{0}{1}{0}", valueWrap, m.Compile()(listItem))).ToArray();
                sb.Append(String.Format("{0}{1}", String.Join(delimiter, values), lineBreak));
            }

            return sb.ToString();
        }

        // Get DisplayName, otherwise fallback to Name
        private static string GetDisplayName(LambdaExpression memberReference)
        {
            MemberInfo info = GetMemberInfo(memberReference);
            DisplayNameAttribute displayNameAttr = Attribute.GetCustomAttribute(info, typeof(DisplayNameAttribute)) as DisplayNameAttribute;
            return (displayNameAttr != null ? displayNameAttr.DisplayName : info.Name);
        }

        // Can be swapped for your favourite GetMemberInfo/GetPropertyInfo utility method (there are many out there)
        // Source: http://blog.baltrinic.com/software-development/dotnet/extension-methods-for-converting-lambda-expression-to-strings
        private static MemberInfo GetMemberInfo(LambdaExpression memberReference)
        {
            MemberExpression memberExpression;
            var unary = memberReference.Body as UnaryExpression;
            if (unary != null)
                //In this case the return type of the property was not object,
                //so .Net wrapped the expression inside of a unary Convert()
                //expression that casts it to type object. In this case, the
                //Operand of the Convert expression has the original expression.
                memberExpression = unary.Operand as MemberExpression;
            else
                //when the property is of type object the body itself is the
                //correct expression
                memberExpression = memberReference.Body as MemberExpression;

            if (memberExpression == null || !(memberExpression.Member is MemberInfo))
                throw new ArgumentException("Expression was not of the form 'x => x.member'.");

            return memberExpression.Member;
        }
    }
}

【讨论】:

  • 非常感谢我今天会试试这个
猜你喜欢
  • 1970-01-01
  • 2013-06-22
  • 2012-01-03
  • 2011-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多