Есть менеджер, которому передается экземпляр класса и некий массив строковых данных. Экземпляр передается любого класса (заранее неизвестного). Нужно пройтись по всем свойствам этого класса и попытаться распарсить значения в соответствующем элементе массива. То есть, например, если у нас пятое по счету свойство является типом DateTime, то нужно 5-ый элемент массива попробовать распарсить как DateTime.
Задача по сути с водится к нескольким операторам сравнения: если у нас тип такой-то, то пытаемся его распарсить так-то. Проблема только в обилии различных числовых форматов. Заранее не могу сказать какой тип будет использовать пользователь Int16 или UInt64, или Decimal. Писать для каждого свое сравнение как-то не очень красиво на мой взгляд — если ли какое-то более изящное решение. Можно ли например как-то определить, что объект является числом и как-то в общем виде его распарсить?
Здравствуйте, Аноним, Вы писали:
А> Есть менеджер, которому передается экземпляр класса и некий массив строковых данных. Экземпляр передается любого класса (заранее неизвестного). Нужно пройтись по всем свойствам этого класса и попытаться распарсить значения в соответствующем элементе массива. То есть, например, если у нас пятое по счету свойство является типом DateTime, то нужно 5-ый элемент массива попробовать распарсить как DateTime. А> Задача по сути с водится к нескольким операторам сравнения: если у нас тип такой-то, то пытаемся его распарсить так-то. Проблема только в обилии различных числовых форматов. Заранее не могу сказать какой тип будет использовать пользователь Int16 или UInt64, или Decimal. Писать для каждого свое сравнение как-то не очень красиво на мой взгляд — если ли какое-то более изящное решение. Можно ли например как-то определить, что объект является числом и как-то в общем виде его распарсить?
Дык конечный автомат-преобразователь жеж!
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Свято уверен, что под такие вещи все-таки обязана быть жесткая схема, описывающая формат.
Спустя 10 лет никто не вспомнит, почему как и что и куда должно писаться. И будут вас проклинать.
Вам это надо ?
Здравствуйте, Аноним, Вы писали:
А> Есть менеджер, которому передается экземпляр класса и некий массив строковых данных. Экземпляр передается любого класса (заранее неизвестного). Нужно пройтись по всем свойствам этого класса и попытаться распарсить значения в соответствующем элементе массива. То есть, например, если у нас пятое по счету свойство является типом DateTime, то нужно 5-ый элемент массива попробовать распарсить как DateTime. А> Задача по сути с водится к нескольким операторам сравнения: если у нас тип такой-то, то пытаемся его распарсить так-то. Проблема только в обилии различных числовых форматов. Заранее не могу сказать какой тип будет использовать пользователь Int16 или UInt64, или Decimal. Писать для каждого свое сравнение как-то не очень красиво на мой взгляд — если ли какое-то более изящное решение. Можно ли например как-то определить, что объект является числом и как-то в общем виде его распарсить?
Это возможно только если жёстко известен формат этих строковых данных.
И, если это задано, то надо парсить элементы согласно этому формату, а не в общем виде.
Иначе это невозможно в принципе. Например, 10/12/2010 это 10 декабря или 12 октября?
12,345 это двенадцать целых триста сорок пять тысячных или двенадцать тысяч триста сорок пять?
Здравствуйте, Аноним, Вы писали:
А> Есть менеджер, которому передается экземпляр класса и некий массив строковых данных. Экземпляр передается любого класса (заранее неизвестного). Нужно пройтись по всем свойствам этого класса и попытаться распарсить значения в соответствующем элементе массива. То есть, например, если у нас пятое по счету свойство является типом DateTime, то нужно 5-ый элемент массива попробовать распарсить как DateTime. А> Задача по сути с водится к нескольким операторам сравнения: если у нас тип такой-то, то пытаемся его распарсить так-то. Проблема только в обилии различных числовых форматов. Заранее не могу сказать какой тип будет использовать пользователь Int16 или UInt64, или Decimal. Писать для каждого свое сравнение как-то не очень красиво на мой взгляд — если ли какое-то более изящное решение. Можно ли например как-то определить, что объект является числом и как-то в общем виде его распарсить?
Если у вас только числа (как явствует из темы), то можно распарсить число в наиболее "общем" виде — который без потерь конвертируется в большинство типов чисел, например, Decimal.
После этого можно воспользоваться, скажем, Convert.ChangeType для конвертации в известный тип свойства.
Более сложная ситуация, если у вас там не только числа, а и значения других типов (например, DateTime, как указано в теле). В таком случае нужно плясать от типа данных, которые вам нужны. Во многих случаях спасет тот же Convert.ChangeType. В остальных можно написать кастомные конвертеры.
There is no such thing as the perfect design.
Re[2]: Как в общем виде распарсить число?
От:
Аноним
Дата:
16.03.10 19:37
Оценка:
Здравствуйте, belnetmon, Вы писали:
B>Свято уверен, что под такие вещи все-таки обязана быть жесткая схема, описывающая формат. B>Спустя 10 лет никто не вспомнит, почему как и что и куда должно писаться. И будут вас проклинать. B>Вам это надо ?
Я немного упростил описание задачи. На самом деле делаю импорт из экселя. Хочу в общем виде написать базу для импорта. То есть, чтобы можно было просто описать вспомогательный класс (каждое свойство которого соответствует колонке в экселе) и заимпортить — получить коллекцию таких классов.
Re[2]: Как в общем виде распарсить число?
От:
Аноним
Дата:
16.03.10 19:43
Оценка:
Здравствуйте, sto, Вы писали:
sto>Здравствуйте, Аноним, Вы писали:
А>> Есть менеджер, которому передается экземпляр класса и некий массив строковых данных. Экземпляр передается любого класса (заранее неизвестного). Нужно пройтись по всем свойствам этого класса и попытаться распарсить значения в соответствующем элементе массива. То есть, например, если у нас пятое по счету свойство является типом DateTime, то нужно 5-ый элемент массива попробовать распарсить как DateTime. А>> Задача по сути с водится к нескольким операторам сравнения: если у нас тип такой-то, то пытаемся его распарсить так-то. Проблема только в обилии различных числовых форматов. Заранее не могу сказать какой тип будет использовать пользователь Int16 или UInt64, или Decimal. Писать для каждого свое сравнение как-то не очень красиво на мой взгляд — если ли какое-то более изящное решение. Можно ли например как-то определить, что объект является числом и как-то в общем виде его распарсить?
sto>Если у вас только числа (как явствует из темы), то можно распарсить число в наиболее "общем" виде — который без потерь конвертируется в большинство типов чисел, например, Decimal. sto>После этого можно воспользоваться, скажем, Convert.ChangeType для конвертации в известный тип свойства.
sto>Более сложная ситуация, если у вас там не только числа, а и значения других типов (например, DateTime, как указано в теле). В таком случае нужно плясать от типа данных, которые вам нужны. Во многих случаях спасет тот же Convert.ChangeType. В остальных можно написать кастомные конвертеры.
По сути нужно просто более компактно записать код, который чуть ниже. Не хочется каждый тип данных отдельно проверять (там их под 2 десятка наверное). Хотелось бы хотябы обойтись двумя проверками — целочисленный тип и с плавающей точкой.
код не компилирующийся — просто чтобы показать принцип
Здравствуйте, <Аноним>, Вы писали:
А> Есть менеджер, которому передается экземпляр класса и некий массив строковых данных. Экземпляр передается любого класса (заранее неизвестного). Нужно пройтись по всем свойствам этого класса и попытаться распарсить значения в соответствующем элементе массива. То есть, например, если у нас пятое по счету свойство является типом DateTime, то нужно 5-ый элемент массива попробовать распарсить как DateTime. А> Задача по сути с водится к нескольким операторам сравнения: если у нас тип такой-то, то пытаемся его распарсить так-то. Проблема только в обилии различных числовых форматов. Заранее не могу сказать какой тип будет использовать пользователь Int16 или UInt64, или Decimal. Писать для каждого свое сравнение как-то не очень красиво на мой взгляд — если ли какое-то более изящное решение. Можно ли например как-то определить, что объект является числом и как-то в общем виде его распарсить?
Так не пойдет?
public static void MapToObject(object obj, string[] strings)
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(obj);
if(properties.Count!=strings.Length)
throw new Exception("Bla bla bla");
for(int i = 0; i < properties.Count; i++)
{
PropertyDescriptor pd = properties[i];
if(!pd.Converter.CanConvertFrom(typeof(string)))
{
throw new Exception("Bla bla bla");
}
pd.SetValue(obj, pd.Converter.ConvertFrom(strings[i]));
}
}
class Test
{
public int IntValue{ get; set; }
public decimal DecimalValue { get; set; }
public string StrValue { get; set; }
public DateTime DateTimeValue { get; set; }
public Point PointValue { get; set; }
public override string ToString()
{
return string.Format("IntValue: {0}, DecimalValue: {1}, StrValue: {2}, DateTimeValue: {3}, PointValue: {4}",
this.IntValue,
this.DecimalValue,
this.StrValue,
this.DateTimeValue,
this.PointValue);
}
}
var obj = new Test();
Console.WriteLine(obj);
MapToObject(obj,new string[]{"4711","22","ABC","12.12.2000","5;10"});
Console.WriteLine(obj);
... << RSDN@Home 1.2.0 alpha 4 rev. 1446>>
Re[3]: Как в общем виде распарсить число?
От:
Аноним
Дата:
17.03.10 09:00
Оценка:
Здравствуйте, Аноним, Вы писали:
А> Я немного упростил описание задачи. На самом деле делаю импорт из экселя. Хочу в общем виде написать базу для импорта. То есть, чтобы можно было просто описать вспомогательный класс (каждое свойство которого соответствует колонке в экселе) и заимпортить — получить коллекцию таких классов.
Как вариант: открыть книгу Excel как источник данных.