我有一个自定义类的列表,其中包含double,string等类型的各种变量。
为了使用Excel DNA将其返回到excel,我需要将列表转换为object[,]
。
这是我做的,但有更好的方法吗?如果我添加另一个变量,我需要记住重做列数等等。
List<customclass> BMrep = somefunction();
var retdata = new object[BMrep.Count,22];
for (int i = 0; i < BMrep.Count; i++)
{
retdata[i, 0] = BMrep[i].product_code;
retdata[i, 1] = BMrep[i].RG;
...
}
return retdata;
答案 0 :(得分:6)
您可以使用反射来获取属性:
var properties = typeof(customclass).GetProperties(BindingFlags.Public |
BindingFlags.Instance).OrderBy(x => x.Name).ToList();
List<customclass> BMrep = somefunction();
var retdata = new object[BMrep.Count, properties.Count];
for (int i = 0; i < BMrep.Count; i++)
{
for (int j = 0; j < properties.Count; j++)
{
retdata[i, j] = properties[j].GetValue(BMrep[i], null);
}
}
return retdata;
答案 1 :(得分:1)
嗯,Tim S.给了你一个非常可靠的答案。
但是,如果您提到的那些various variables
是字段而不是属性,则它将无效。您只需将其更改为GetFields
而不是GetProperties
(并且GetValue不需要第二个null
参数)
这是另一个可以使用字段的例子(使用linq,有点短):
class A
{
public string Field1;
public string Field2;
public string Field3;
}
static void Main(string[] args)
{
A myA = new A() { Field1 = "rofl", Field2 = "lol", Field3 = "omg" };
var obj = (from prop in typeof(A).GetFields(BindingFlags.Public | BindingFlags.Instance)
select prop.GetValue(myA)).ToArray();
Debug.Assert(obj[0] == "rofl");
Debug.Assert(obj[1] == "lol");
Debug.Assert(obj[2] == "omg");
}
如果您希望使用属性,只需将linq替换为:
var obj2 = (from prop in typeof(A).GetProperties(BindingFlags.Public | BindingFlags.Instance)
select prop.GetValue(myA,null)).ToArray();
我输入var
为简短,obj
和obj2
类型为Object[]
修改强>
由MSDN指定,
GetProperties方法不会按特定顺序返回属性,例如按字母顺序或声明顺序。
因此,如果您想保留订单,可以在字段/属性上创建Attribute
,以保留此信息。见下文:
class OrderAttribute : Attribute
{
public int Order { get; private set; }
public OrderAttribute(int order)
{
this.Order = order;
}
}
class A
{
public string FieldWithoutOrder;
[Order(3)] public string Field1;
[Order(2)] public string Field2;
[Order(1)] public string Field3;
}
static void Main(string[] args)
{
A myA = new A() { Field1 = "rofl", Field2 = "lol", Field3 = "omg", FieldWithoutOrder = "anarchy" };
var obj = (from prop in typeof(A).GetFields(BindingFlags.Public | BindingFlags.Instance)
orderby prop.GetCustomAttributes(typeof(OrderAttribute),true).Select(att=>((OrderAttribute)att).Order).DefaultIfEmpty(Int32.MaxValue).First()
select prop.GetValue(myA)
).ToArray();
var obj2 = (from prop in typeof(A).GetProperties(BindingFlags.Public | BindingFlags.Instance)
select prop.GetValue(myA,null)).ToArray();
Debug.Assert(obj[0] == "omg"); //Field3
Debug.Assert(obj[1] == "lol"); //Field2
Debug.Assert(obj[2] == "rofl"); //Field1
Debug.Assert(obj[3] == "anarchy"); //FieldWithoutOrder
}
DefaultIfEmpty
指定一个值,以防该字段没有Order
属性。
通过这种方式,您可以轻松维护(如果您需要更改字段的顺序,只需更改属性)
我没有为obj2
执行此操作,但您可以粘贴相同的orderby
语句,它会起作用。
希望它有所帮助。