【问题标题】:List of public Properties and their values [duplicate]公共属性列表及其值[重复]
【发布时间】:2014-02-12 22:00:49
【问题描述】:

.Net 4.5 C#

要支持许多类的“导出到 Excel”功能,我需要能够获取一个类,然后从中获取公共属性名称(用于标题)和属性值(用于行)

有没有办法反映类的实例并获取属性名称和属性值?

【问题讨论】:

    标签: c# reflection


    【解决方案1】:

    实际上,我最近为我的工作创建了类似的东西。我正在编写一个自定义 CSV 序列化程序类来支持一个考虑不周的 CSV 文件规范。

    public CSVSerializer Serialize<T>(T data, Func<T, object> map)
    {
        if (map == null) throw new ArgumentNullException("map");
    
        object mappedData = map(data);
        if (mappedData == null) throw new NullReferenceException("Mapped data produced null value");
    
        // Iterate over public members of `mappedData`
        MemberInfo[] members = mappedData.GetType().GetMembers(BindingFlags.Instance | BindingFlags.Public);
        List<string> values = new List<string>();
        foreach (MemberInfo member in members)
        {
            // Skip events and methods
            if (!(member is FieldInfo || member is PropertyInfo)) continue;
    
            // Value of `mappedData`
            object memberVal = MemberInfoValue(member, mappedData);
            if (memberVal == null)
            {
                // If the actual value stored by `memberVal` is null, store string.Empty and continue
                values.Add(string.Empty);
                continue;
            }
    
            // Check if `memberVal` contains a member named "map"
            MemberInfo[] maps = memberVal.GetType().GetMember("map");
            MemberInfo memberMap = maps.Length > 0 ? maps[0] : null;
            string val = MapToString(memberVal, o => o.ToString());
    
            if (map != null) // map is present
            {
                // Get first property other than map
                MemberInfo dataVal = memberVal.GetType().GetMembers(BindingFlags.Instance | BindingFlags.Public)
                                                    .Where(mi => mi is FieldInfo || mi is PropertyInfo)
                                                    .Except(new MemberInfo[] { memberMap })
                                                    .DefaultIfEmpty(memberMap)
                                                    .FirstOrDefault();
    
                object tmp = MemberInfoValue(memberMap, memberVal);
                if (dataVal == memberMap)
                {
                    // map is only property, so serialize it
                    val = MapToString(tmp, o => o.ToString());
                }
                else
                {
                    // try to serialize map(dataVal), or use empty string if it fails
                    Delegate dlg = tmp as Delegate;
                    if (dlg != null)
                    {
                        object param = MemberInfoValue(dataVal, memberVal);
                        try { val = MapToString(dlg, d => d.DynamicInvoke(param).ToString()); }
                        catch (Exception ex)
                        {
                            // exception should only occur with parameter count/type mismatch
                            throw new SerializationException(string.Format("Poorly formatted map function in {0}", member.Name), ex);
                        }
                    }
                    else
                    {
                        // map is not a delegate (!!)
                        throw new SerializationException(string.Format("map member in {0} is not a delegate type", member.Name));
                    }
                }
            }
    
            // Handle quotes and the separator string
            val = val.Trim('"');
            if (val.Contains("\""))
            {
                val = val.Replace("\"", "\\\"");
            }
            if (val.Contains(Separator))
            {
                val = string.Format("\"{0}\"", val);
            }
    
            values.Add(val);
        }
        string line = string.Join(Separator, values);
        Writer.WriteLine(line);
    
        return this;
    }
    

    此函数按定义的顺序序列化data 的公共字段和属性;这些成员的名字将被忽略。

    如果您只对属性感兴趣,可以使用GetProperties 代替GetMembers(使用PropertyInfo 代替MemberInfo)。如果您不创建 CSV,则显然可以忽略 CSV 文件格式部分。

    MemberInfoValue(info, parent) 返回 ((FieldInfo)info).GetValue(parent)((PropertyInfo)info).GetValue(parent, null),视情况而定。 MapToString 只是一个空保护函数。

    map 参数的存在和寻找名为“map”的成员是我特定情况的必需品的一部分,尽管它可能对您有用。映射允许以下内容:

    mySerializer.Serialize(myPersonObject,
        p => new {
            name = string.Format("{0}, {1}", p.LastName, p.FirstName),
            address = p.address
        });
    

    我有一个Serialize 的重载,它调用Serialize(data, d =&gt; d);。寻找“地图”成员允许这样的事情:

    mySerializer.Serialize(new {
            employeeID = new { val = myEmployeeObject.ID, map = d => d.ToUpperCase() },
            employeeName = myEmployeeObject.Name
        });
    

    【讨论】:

      【解决方案2】:

      你可以这样使用:

      public static Dictionary<string, object> KeyValue(object obj)
      {
          return obj.GetType().GetProperties().ToDictionary(
              m => m.Name, 
              m => m.GetValue(obj, new object[] { })
          );
      }
      

      【讨论】:

        【解决方案3】:

        这里有一个关于如何做到这一点的快速示例。当然,您需要对其进行更新,以便正确创建/构造 CSV,但这让您了解如何获得所需的值。

        class Program
        {
            static void Main(string[] args)
            {
                var myClass = new MyClass()
                {
                    Number = 1,
                    String = "test"
                };
        
                var properties = myClass.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
        
                foreach (var property in properties)
                {
                    var columnName = property.Name;
                    var value = myClass.GetType().GetProperty(columnName).GetValue(myClass, null);
        
                    Console.WriteLine(string.Format("{0} - {1}", columnName, value));
                }
                Console.ReadKey();
            }
        }
        
        public class MyClass
        {
            public int Number { get; set; }
            public string String { get; set; }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-01-17
          • 1970-01-01
          • 1970-01-01
          • 2011-11-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多