2012-05-19 2 views
3

У меня есть следующий код, который принимает SQL заявление (строка), загружает результаты в ArrayList (organisationList), который представляет собой совокупность организаций:Заполните любые ArrayList с результатами оператора SQL

public void FillDataGridView(DataGridView grid, string SQLCommand) 
{ 
    SqlCommand dataCommand = new SqlCommand(); 
    dataCommand.Connection = dataConnection; 
    dataCommand.CommandType = CommandType.Text; 
    dataCommand.CommandText = SQLCommand; 

    SqlDataReader dataReader = dataCommand.ExecuteReader(); 

    while (dataReader.Read()) 
    { 
     Organisation org = new Organisation(); 

     org.OrganisationId = (int)dataReader["OrganisationId"]; 
     org.OrganisationName = (string)dataReader["OrganisationName"]; 

     organisationList.Add(org); 
    } 

    grid.DataSource = organisationList; 
    dataReader.Close(); 
} 

I хотел бы адаптировать этот метод, чтобы можно было заполнить ArrayList, переданный в него.

Можно ли мне передать список в метод и есть что-то вроде:

public void FillArrayList(DataGridView grid, SqlDataReader reader, ArrayList list) 
{ 
    //Fill the list with the contents of the reader 
    while (reader.Read()) 
    { 
     Object obj = new Object 

     for(int i; i = 0; i < obj.NoOfProperties) 
     { 
      obj.Property[i] = reader[i]; 
     } 

     list.Add(obj); 
    } 
} 

Извините, если это немного расплывчатым, я совершенно новой для объектно-ориентированного программирования и немного потеряли!

Edit: На основе рекомендаций Даррена Дэвиса, я изменил метод следующим образом:

public void FillArrayList<T>(DataGridView grid, SqlDataReader reader, List<T> list) 
{ 
    //Fill the list with the contents of the reader 
    while (reader.Read()) 
    { 
     Object obj = new Object(); 
     Type type = typeof(T); 

     FieldInfo[] fields = type.GetFields(); // Get the fields of the assembly 
     int i = 0; 

     foreach(var field in fields) 
     { 
      field.SetValue(obj, reader[i]); // set the fields of T to the reader's value 
      // field.setValue(obj, reader[field.Name]); // You can also set the field value to the explicit reader name, i.e. reader["YourProperty"] 
      i++; 
     } 

     list.Add((T)obj); 
    } 

    grid.DataSource = list; 
} 

Когда я запускаю код, я получаю ошибку при забросе объекта типа T:

Unable to cast object of type 'System.Object' to type 'TestHarness.Organisation'.

У меня создалось впечатление, что объект может хранить что угодно. Может ли кто-нибудь посоветовать мне, почему этот актер не может быть выполнен?

Спасибо,

Энди

ответ

2

Если вы используете C# 2.0. или больше использования Generics, а не ArrayList.

Вы можете использовать Reflection к получить свойства типа, которые Вы передаете в:

public void FillArrayList<T>(DataGridView grid, SqlDataReader reader, List<T> list) 
{ 
    //Fill the list with the contents of the reader 
    while (reader.Read()) 
    { 
     Object obj = new Object(); 
     Type type = typeof(T); // get the type of T (The paramter you passed in, i.e. Organisations) 

     FieldInfo[] fields = type.GetFields(); // Get the fields of the assembly 
     int i = 0; 

     foreach(var field in fields) // Loop round the fields 
     { 
      field.setValue(obj, reader[i]); // set the fields of T to the readers value 
      // field.setValue(obj, reader[field.Name]); // You can also set the field value to the explicit reader name, i.e. reader["YourProperty"] 
      i++; 
     } 

     list.Add(obj); 
    } 
} 

Для вызова:

FillArrayList(grid, reader, list); 

Где список типа Список организаций

List<Organisations> list = new List<Organisations>(); 

http://msdn.microsoft.com/en-us/library/ms379564(v=vs.80).aspx

+0

Этот ответ определенно получил мне дальше всех, но Visual Studio не нравится list.Add (OBJ); линия. Компилятор пытается преобразовать из «Объекта» в «Т». Мне не хватает строки, где я указываю, что объект всегда будет иметь тип T? Спасибо за помощь. – amarsha4

+0

@ amarshs Im в настоящее время использует мой телефон, чтобы ответить, поэтому мой ответ будет коротким, пока я не получу доступ к компьютеру. Я считаю, что ошибка относится к списку, который вы передаете, это не тот же тип, что и Object. Вместо использования Object obj = new Object(); вы могли бы сделать Организации obj = new Organization(); затем добавьте его в список. Вы также можете изменить организации на тип (T), который вы передаете –

+0

Hi Darren, Спасибо за ваш ответ. Я не хочу использовать какую-либо ссылку на организацию в этом методе, так как хочу, чтобы метод взял считыватель данных и заполнил список объекта _any_. Перед тем, как ответить, я попытался заменить строку, указанную в списке.Add ((T) obj); но это породило ошибку во время выполнения: Невозможно передать объект типа «System.Object», чтобы ввести «QSurveillanceTestHarness.Organisation». Я думал, что класс «Объект» может ссылаться на любой тип объекта. Теперь я более смущен. Еще раз спасибо, Andy – amarsha4

1

Если вы создаете свойства вашего класса с таким же именем, как и столбцы в возвращенных данных установлен, то вы можете использовать отражение для создания любого типа объекта от чтения данных или данных table (если сопоставляются столбцы считывателя данных или таблицы данных и свойства объекта).

Вы можете увидеть followin this ссылка. Он показывает, как преобразовать таблицу данных в коллекцию настраиваемого класса. Работа с считывателем данных будет такой же.

5

Если вы используете .NET 1.1, вы, вероятно, не должны использовать ArrayList; предпочтительным является общий List<T>.

Вы не можете добавить участников в object - его нельзя расширить. Вам нужно знать тип создаваемого объекта. Дженерики были бы разумным объектом. Однако, чтобы сэкономить ваше время, вы можете сделать так, чтобы смотреть на dapper:

var list = dataConnection.Query<YourType>(SQLCommand).ToList(); 

Что будет делать все, используя имя столбца прямой для отображения имен членов. Вам нужно будет создать класс YourType со свойствами (соответствующим образом введенным), которые вы ожидаете.

Если вы используете 4.0, щеголеватый также поддерживает dynamic:

var list = dataConnection.Query(SQLCommand).ToList(); 

dynamic Это использует, так что вы можете сделать (без объявления типа):

foreach(var obj in list) { 
    Console.WriteLine(obj.OrganisationId); 
    Console.WriteLine(obj.OrganisationName); 
} 

Лично я только используйте подход dynamic, если данные используются очень близко к тому, к которому он обращается. Для возврата из метода предпочтительным является общий подход. Аналогично, dynamic не работает с DataGridView.

Наконец, я не вижу никаких параметров; вы всегда хотите использовать параметры, а не конкатенацию. Dapper поддерживает это тоже:

string foo = ...; 
var list = dataConnection.Query<YourType>(
    "select * from SomeTable where Foo = @foo", new { foo }).ToList(); 
Смежные вопросы