继承的类属性顺序

时间:2018-01-02 10:43:02

标签: c# inheritance epplus

我有两个类,其中一个继承自另一个:

public class First
{
public string a{get;set;}
public string b{get;set;}
}
public class Second: First
{
public string c {get;set;}
}

然后我创建一个List<Second>并填写一些信息,然后我使用EPPlus将此列表导出到Excel。 但是“问题”是继承类(第二个)的属性首先出现,而基类(第一个)的属性出现在excel之后:

c     |  a    |   b
-------------------

问题是我是否可以先放置基类的属性,还是可以说EPPlus属性的顺序?

编辑:

我把代码创建为Excel,非常简单

:

 using (ExcelPackage package = new ExcelPackage(archivo))            
{
 ExcelWorksheet ws= package.Workbook.Worksheets.Add("Solds");
 {
   ws.Cells["A3"].LoadFromCollection(lstSolds);
   package.Save();
 }

}

2 个答案:

答案 0 :(得分:4)

您可以使用属性和反射来选择属性的顺序。它还允许选择要输出的属性

public class First {
    [Order(1)]
    public string a { get; set; }
    [Order(2)]
    public string b { get; set; }
}
public class Second : First {
    [Order(3)]
    public string c { get; set; }
}

[AttributeUsage(AttributeTargets.Property)]
public class OrderAttribute : Attribute {
    public int Order {get; set; }
    public OrderAttribute(int order) {
        Order = order;
    }
}

class Program {
    static void Main(string[] args) {
        List<Second> list = new List<Second>();
        list.Add(new Second {
            a = "a",
            b = "b",
            c = "c"
        });
        WriteList(list);
    }

    static void WriteList(List<Second> list) {
        PropertyInfo[] properties = typeof(Second).GetProperties();
        int row = 3;
        int col = 0;
        foreach (var item in list) {
            Dictionary<int, object> values = new Dictionary<int, object>();
            foreach (var pi in properties) {
                var orderAttr = pi.GetCustomAttribute(typeof(OrderAttribute)) as OrderAttribute;
                if (orderAttr != null) {    //this allow to output selective propertes. Those properties without [order] attriburte will not output
                    values.Add(orderAttr.Order, pi.GetValue(item, null));
                }
            }
            foreach (var key in values.Keys.OrderBy(x => x)) {
                ws.Cells[row, col + key].Value = values[key];
            }
            row++;
        }
    }

编辑为@Ion评论,添加了从Excel中读取的功能

    static List<Second> ReadFromExcel(string filePath) {
        List<Second> result = new List<Second>();
        PropertyInfo[] props = typeof(Second).GetProperties();

        //Allow access propertyInfo by name
        Dictionary<string, PropertyInfo> properties = new Dictionary<string, PropertyInfo>();
        foreach (var pi in props) {
            properties.Add(pi.Name, pi);
        }


        using (var xls = new ExcelPackage(new FileInfo(filePath))) {

            ExcelWorksheet ws = xls.Workbook.Worksheets[0];

            //Let's assume you have property names has row heading in Excel
            List<string> names = new List<string>(3);
            for (int i = 1; i <= 4; i++) {
                names.Add(ws.Cells[1, i].Value.ToString());
            }

            //Fill the list from Excel
            for (int row = 3; row <= ws.Dimension.End.Row; row++) {
                Second second = new Second();
                for (int col = 1; col <= 4; col++) {
                    object value = ws.Cells[row, col].Value;
                    if (value != null)
                        properties[names[col]].SetValue(second, value);
                }
                result.Add(second);
            }
        }

        return result;
    }

答案 1 :(得分:3)

另一种方式,更多&#34; Epplus&#34;我想你可以说,这将是这样的:

var lstSolds = new List<First>();
for (var i = 0; i < 10; i++)
{
    lstSolds.Add(new Second
    {
        a = "A-" + i,
        b = "B-" + i,
        c = "C-" + i
    });
}

using (ExcelPackage package = new ExcelPackage(archivo)) 
{
    var mi = typeof (Second)
        .GetProperties()
        .OrderBy(pi => pi.Name)  //This controls the column order
        .Cast<MemberInfo>()
        .ToArray();

    ws.Cells["A3"]
        .LoadFromCollection(
            lstSolds
            , true
            , TableStyles.Custom
            , BindingFlags.Default
            , mi
        );

    package.Save();
}

您可以通过调整mi收集顺序来控制列的顺序。在这种情况下,它按升序排序,但LoadFromCollection将遵守任何订单集。

enter image description here

对评论的回应

很容易让它们以您需要的任何顺序排序。只需要在传递保证排序顺序的方式之前构建数组。假设我们向d类添加了一个属性First。我们可以确保在c之前对其进行排序:

public class First
{
    public string a { get; set; }
    public string b { get; set; }
    public string d { get; set; }  //Say we need this to sort before 'c'
}
public class Second : First
{
    public string c { get; set; }
}

...

var lstSolds = new List<First>();
for (var i = 0; i < 10; i++)
{
    lstSolds.Add(new Second
    {
        a = "A-" + i,
        b = "B-" + i,
        c = "C-" + i,
        d = "D-" + i,
    });
}

using (var package = new ExcelPackage(file))
{
    var ws = package.Workbook.Worksheets.Add("table");

    //var mi = typeof(Second)
    //    .GetProperties()
    //    .OrderBy(pi => pi.Name)  //This controls the column order
    //    .Cast<MemberInfo>()
    //    .ToArray();

    var firstmi = typeof (First)
        .GetProperties()
        .OrderBy(pi => pi.Name);

    var secondmi = typeof (Second)
        .GetProperties()
        .Where(pi => !firstmi.Select(fpi => fpi.Name).Contains(pi.Name))
        .OrderBy(pi => pi.Name);

    //Sorting above will keep first proper before second
    var mi = firstmi
        .Concat(secondmi)
        .Cast<MemberInfo>()
        .ToArray();

    ws.Cells["A3"]
        .LoadFromCollection(
            lstSolds
            , true
            , TableStyles.Custom
            , BindingFlags.Public | BindingFlags.Instance
            , mi
        );

    package.Save();
}

enter image description here