继承 class 属性顺序
inherited class properties order
我有 2 个 classes,其中一个继承自另一个:
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。
但是 "problem" 是继承的 class(Second) 的属性首先出现,而基础 class(First) 的属性出现在 excel 之后:
c | a | b
-------------------
问题是我能不能把基础的属性放在前面class,或者我能告诉EPPlus属性的顺序吗?
编辑:
我把代码创建了Excel,很简单
:
using (ExcelPackage package = new ExcelPackage(archivo))
{
ExcelWorksheet ws= package.Workbook.Worksheets.Add("Solds");
{
ws.Cells["A3"].LoadFromCollection(lstSolds);
package.Save();
}
}
您可以使用属性和反射来 select 属性的顺序。它还允许 select 您要输出或不输出哪些属性
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;
}
另一种方式,更多 "Epplus" 我猜你会说的方式是这样的:
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
.
将遵守任何顺序集
对评论的回复
让它们按您需要的任何顺序排序很容易。只需要在以保证排序顺序的方式传递之前构建数组。假设我们将 属性 d
添加到 First
class。我们可以像这样确保它在 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();
}
我有 2 个 classes,其中一个继承自另一个:
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。
但是 "problem" 是继承的 class(Second) 的属性首先出现,而基础 class(First) 的属性出现在 excel 之后:
c | a | b
-------------------
问题是我能不能把基础的属性放在前面class,或者我能告诉EPPlus属性的顺序吗?
编辑:
我把代码创建了Excel,很简单
:
using (ExcelPackage package = new ExcelPackage(archivo))
{
ExcelWorksheet ws= package.Workbook.Worksheets.Add("Solds");
{
ws.Cells["A3"].LoadFromCollection(lstSolds);
package.Save();
}
}
您可以使用属性和反射来 select 属性的顺序。它还允许 select 您要输出或不输出哪些属性
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;
}
另一种方式,更多 "Epplus" 我猜你会说的方式是这样的:
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
.
对评论的回复
让它们按您需要的任何顺序排序很容易。只需要在以保证排序顺序的方式传递之前构建数组。假设我们将 属性 d
添加到 First
class。我们可以像这样确保它在 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();
}