2013-11-21 14 views
2

У меня есть список пользовательского класса, который содержит различные переменные типа двойной, строки и т.д.Преобразовать список заказного класса в массив объектов

Для того, чтобы вернуть это, чтобы преуспеть с ДНК 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; 

ответ

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; 
+0

Спасибо! Означает ли это, что настройки пользовательского класса соответствуют одному и тому же порядку? – nik

+0

@nik нет. [Заказ вообще не гарантируется] (http://msdn.microsoft.com/en-us/library/kyaxdd3x (v = vs.110) .aspx), поэтому вы должны как-то заказать его. Я добавлю это к моему ответу. –

+0

вот что я думал. Благодаря! – nik

1

Ну, Тим С. дал вам довольно надежный ответ.

Однако, если вы указали эти поля, а не свойства, это не сработает. Вы можете просто изменить его на GetFields вместо GetProperties (и ПолучитьЗначение не нужен второй 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[]

EDIT:

Как указано 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, и это сработает.

Надеюсь, это поможет.

+0

Спасибо! тот же вопрос, что и Тиму.Я слышал, что если вы используете рефлексию, вы не можете быть уверены, что поля приходят в одном порядке каждый раз, но, очевидно, это имеет значение здесь, поскольку мне нужно заполнить это, чтобы преуспеть в правильном порядке ... – nik

+0

Подождите, я приду с обходным путем для вас. –

+0

@nik Посмотрите, работает ли это для вас. –

Смежные вопросы