erow = ws.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
В вашем коде было 2 ошибки. Во-первых, команда
xlUp
, а неx1Up
- «xl» означает «Excel», а не «X One» - это прекрасный пример того, почему вы почти всегда должны использоватьOption Explicit
[119 ]Второе: ваш код как есть попытается поместить
.Value
из ячейки в нетипизированную переменнуюerow
- поскольку ячейка пуста (так как ячейка ниже последней ячейка с данными), это означает, чтоerow
будет всегда будет0
. И строка 0 не существует для помещения данных.Вместо этого, используя
Range.Row
, мы получаем следующий номер строки для вставки данных в
Анонимные типы инкапсулируют ряд свойств только для чтения. Это объясняет
Почему Type.GetFields
возвращает пустой массив при вызове на анонимном типе: анонимные типы не имеют общедоступных полей.
Общественные собственности на анонимном типе только для чтения и не могут иметь своего набора значений вызовом к PropertyInfo.SetValue
. Если Вы звоните PropertyInfo.GetSetMethod
на свойстве в анонимном типе Вы получите назад null
.
На самом деле, если Вы изменяетесь
var properties = TypeDescriptor.GetProperties(sample);
while (nwReader.Read()) {
// No way to create a constructor so this call creates the object without calling a ctor. Could this be a source of the problem?
T obj = (T)FormatterServices.GetUninitializedObject(typeof(T));
foreach (PropertyDescriptor info in properties) {
for (int i = 0; i < nwReader.FieldCount; i++) {
if (info.Name == nwReader.GetName(i)) {
// This loop runs fine but there is no change to obj!!
info.SetValue(obj, nwReader[i]);
break;
}
}
}
fdList.Add(obj);
}
кому:
PropertyInfo[] properties = sample.GetType().GetProperties();
while (nwReader.Read()) {
// No way to create a constructor so this call creates the object without calling a ctor. Could this be a source of the problem?
T obj = (T)FormatterServices.GetUninitializedObject(typeof(T));
foreach (PropertyInfo info in properties) {
for (int i = 0; i < nwReader.FieldCount; i++) {
if (info.Name == nwReader.GetName(i)) {
// This loop will throw an exception as PropertyInfo.GetSetMethod fails
info.SetValue(obj, nwReader[i], null);
break;
}
}
}
fdList.Add(obj);
}
Вы получите исключение, сообщающее Вам, что метод набора свойств не может быть найден.
Теперь, для решения проблемы, что можно сделать, использовать Activator.CreateInstance
. Я сожалею, что я слишком ленив для вывода кода для Вас, но следующее продемонстрирует, как использовать его.
var car = new { Make = "Honda", Model = "Civic", Year = 2008 };
var anothercar = Activator.CreateInstance(car.GetType(), new object[] { "Ford", "Focus", 2005 });
Так просто пробегите цикл, как Вы сделали, для заполнения объектного массива, которому необходимо передать Activator.CreateInstance
и затем звоните Activator.CreateInstance
когда цикл сделан. Порядок свойства важен здесь, поскольку два анонимных типа являются тем же, если и только если у них есть то же количество свойств с тем же типом и тем же именем в том же порядке.
Для больше, посмотрите страницу MSDN на анонимных типах.
Наконец, и это действительно в стороне и не релевантно Вашему вопросу, но следующему коду
foreach (PropertyDescriptor info in properties) {
for (int i = 0; i < nwReader.FieldCount; i++) {
if (info.Name == nwReader.GetName(i)) {
// This loop runs fine but there is no change to obj!!
info.SetValue(obj, nwReader[i]);
break;
}
}
}
мог быть упрощен
foreach (PropertyDescriptor info in properties) {
info.SetValue(obj, nwReader[info.Name]);
}
Вопрос № 2:
Я действительно не знаю, но я был бы склонен использовать Активатор. CreateObject () вместо FormatterServices. GetUninitializedObject (), потому что Ваш объект не мог бы быть создан правильно. GetUninitializedObject () не будет работать, конструктор по умолчанию как CreateObject () будет, и Вы не обязательно знаете то, что находится в черном квадрате T...