反思,属性和属性选择

时间:2009-08-31 21:22:17

标签: c# .net

我正在尝试构建一个将列表导出为ex​​cel的通用方法。如果应该打印属性,则对象将具有属性。即:

public class someObject {
  public int DontPrint {get; set;}

  [ExcelAttributes(PrintMe = true)]
  public int PrintMe {get; set;}


  [ExcelAttributes(PrintMe = true)]
  public int PrintMeToo {get; set;}

}

我需要一种通用的方法来检查List并返回一个可打印的对象。如下所示。

public AppendCell<T>(List<T> list)
  var obj = list[0];

  PropertyInfo[] propertyInfos;
  propertyInfos = obj.GetType().GetProperties(BindingFlags.Public |
                                          BindingFlags.Instance);

  foreach (T list1 in list)
     {
      foreach (PropertyInfo info in propertyInfos)
        {
          object[] customAttr = info.GetCustomAttributes(true);
          // create cell with data
          foreach (object o in customAttr)
           {
               ExcelAttributes ea = o as ExcelAttributes;
               if (ea != null && ea.PrintMe ==true)
               Cell c = new Cell(info.GetValue(list1,null).ToString())

           }

        }
}

return c;
}

所以...我基本上希望能够检查对象列表,根据属性的值获取可打印属性并打印可打印属性的值。

如果我们使用值

创建someObject列表
{DontPrint = 0, PrintMe = 1, PrintMeToo = 2}
{DontPrint = 0, PrintMe = 4, PrintMeToo = 5}
{DontPrint = 0, PrintMe = 3, PrintMeToo = 8}

我希望看到:

1 2
4 5
3 8

类似于发布的代码就是我所需要的。是否有更简洁的方法来获取具有PrintMe属性的属性列表,然后遍历列表并对这些属性进行操作?

2 个答案:

答案 0 :(得分:4)

创建一个具有成员方法的接口IPrintable不是一个更好的主意,该成员方法会返回一组可打印属性吗?
例如,像这样:

interface IPrintable
{
   ICollection<PrintProperties> GetPrintableProperties();
}

其中PrintProperties类型包含例如2个成员(名称和值)。 ?

然后,您可以将此接口实现到您希望具有此行为的类。

但是,如果您只想坚持使用您的解决方案,并希望有更短的方式来编写它,那么您可以查看LINQ。 我相信这样的事情也应该做到(未经测试):

var printableProperties = obj.GetType().GetProperties().Where (pi => Attribute.IsDefined (pi, typeof(PrintableAttribute)).ToList();

答案 1 :(得分:0)

有关详细信息,请参阅代码注释...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication5 {
    internal class Program {
        static void Main(string[] args) {

            List<someObject> myList = new List<someObject>();

            myList.Add(new someObject() {
                DontPrint = 0,
                PrintMe = 1,
                PrintMeToo = 2
            });

            myList.Add(new someObject() {
                DontPrint = 0,
                PrintMe = 4,
                PrintMeToo = 5
            });

            myList.Add(new someObject() {
                DontPrint = 0,
                PrintMe = 3,
                PrintMeToo = 8
            });


            string[,] myPrintables = GetPrintables(myList);

            System.Console.ReadKey();
        }

        public class someObject {
            public int DontPrint {
                get;
                set;
            }
            [ExcelAttributes( true)]
            public int PrintMe {
                get;
                set;
            }
            [ExcelAttributes(true)]
            public int PrintMeToo {
                get;
                set;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <returns>string[,] - very easy to export to excel in array operation</returns>
        public static string[,] GetPrintables<T>(System.Collections.Generic.IList<T> list) {

            List<System.Reflection.PropertyInfo> discoveredProperties = 
                new List<System.Reflection.PropertyInfo>();

            System.Type listType = typeof(T);

            // first get the property infos (not on every iteration)
            foreach (System.Reflection.PropertyInfo propertyInfo in listType.GetProperties(
                System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance)) {

                // no indexers
                if (propertyInfo.GetIndexParameters().Length == 0) {
                    ExcelAttributes[] attributes = propertyInfo.GetCustomAttributes(typeof(ExcelAttributes), true) as ExcelAttributes[];

                    // allowmultiple = false hence length e {0;1}
                    if (attributes != null && attributes.Length == 1) {

                        if (attributes[0].PrintMe) {
                            discoveredProperties.Add(propertyInfo);
                        }
                    }
                }
            }

            int numberOfDiscoveredProperties = discoveredProperties.Count;

                       // can be instantiated only if there are discovered properties, but null may be returned
            string[,] arrayItems = new string[list.Count, numberOfDiscoveredProperties];

            // if we have any printables
            if (numberOfDiscoveredProperties > 0) {

                for (int iItem = 0; iItem < list.Count; iItem++) {

                    for (int iProperty = 0; iProperty < numberOfDiscoveredProperties; iProperty++) {

                        object value = discoveredProperties[iProperty].GetValue(list[iItem], null);
                        // value.ToString may not be ideal, perhaps also cache StringConverters
                        arrayItems[iItem, iProperty] = value != null ? value.ToString() : string.Empty;
                    }

                }
            }

            return arrayItems;
        }
    }

    [System.AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
    public class ExcelAttributes : System.Attribute {

        // use readonly field
        private readonly bool _PrintMe;

        public ExcelAttributes(bool printMe) {
            _PrintMe = printMe;
        }

        public bool PrintMe {
            get {
                return _PrintMe;
            }
        }
    }
}