Как в общем виде распарсить число?
От: Аноним  
Дата: 16.03.10 17:47
Оценка:
Есть менеджер, которому передается экземпляр класса и некий массив строковых данных. Экземпляр передается любого класса (заранее неизвестного). Нужно пройтись по всем свойствам этого класса и попытаться распарсить значения в соответствующем элементе массива. То есть, например, если у нас пятое по счету свойство является типом DateTime, то нужно 5-ый элемент массива попробовать распарсить как DateTime.
Задача по сути с водится к нескольким операторам сравнения: если у нас тип такой-то, то пытаемся его распарсить так-то. Проблема только в обилии различных числовых форматов. Заранее не могу сказать какой тип будет использовать пользователь Int16 или UInt64, или Decimal. Писать для каждого свое сравнение как-то не очень красиво на мой взгляд — если ли какое-то более изящное решение. Можно ли например как-то определить, что объект является числом и как-то в общем виде его распарсить?
Re: Как в общем виде распарсить число?
От: LaptevVV Россия  
Дата: 16.03.10 17:49
Оценка:
Здравствуйте, Аноним, Вы писали:

А> Есть менеджер, которому передается экземпляр класса и некий массив строковых данных. Экземпляр передается любого класса (заранее неизвестного). Нужно пройтись по всем свойствам этого класса и попытаться распарсить значения в соответствующем элементе массива. То есть, например, если у нас пятое по счету свойство является типом DateTime, то нужно 5-ый элемент массива попробовать распарсить как DateTime.

А> Задача по сути с водится к нескольким операторам сравнения: если у нас тип такой-то, то пытаемся его распарсить так-то. Проблема только в обилии различных числовых форматов. Заранее не могу сказать какой тип будет использовать пользователь Int16 или UInt64, или Decimal. Писать для каждого свое сравнение как-то не очень красиво на мой взгляд — если ли какое-то более изящное решение. Можно ли например как-то определить, что объект является числом и как-то в общем виде его распарсить?
Дык конечный автомат-преобразователь жеж!
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re: Как в общем виде распарсить число?
От: dims12 http://www.relativity.ru
Дата: 16.03.10 17:53
Оценка:
Здравствуйте, Аноним, Вы писали:

А> Есть менеджер...


Рекурсивный разборщик. Каждая функция распознаёт свой вариант и пользуется другими для распознавания компонент.
Re: Как в общем виде распарсить число?
От: Lloyd Россия  
Дата: 16.03.10 18:03
Оценка:
Здравствуйте, Аноним, Вы писали:

А>То есть, например, если у нас пятое по счету свойство ...


Это как?
Re: Как в общем виде распарсить число?
От: belnetmon Беларусь  
Дата: 16.03.10 18:26
Оценка:
Свято уверен, что под такие вещи все-таки обязана быть жесткая схема, описывающая формат.
Спустя 10 лет никто не вспомнит, почему как и что и куда должно писаться. И будут вас проклинать.
Вам это надо ?
Re: Как в общем виде распарсить число?
От: vmpire Россия  
Дата: 16.03.10 18:38
Оценка:
Здравствуйте, Аноним, Вы писали:

А> Есть менеджер, которому передается экземпляр класса и некий массив строковых данных. Экземпляр передается любого класса (заранее неизвестного). Нужно пройтись по всем свойствам этого класса и попытаться распарсить значения в соответствующем элементе массива. То есть, например, если у нас пятое по счету свойство является типом DateTime, то нужно 5-ый элемент массива попробовать распарсить как DateTime.

А> Задача по сути с водится к нескольким операторам сравнения: если у нас тип такой-то, то пытаемся его распарсить так-то. Проблема только в обилии различных числовых форматов. Заранее не могу сказать какой тип будет использовать пользователь Int16 или UInt64, или Decimal. Писать для каждого свое сравнение как-то не очень красиво на мой взгляд — если ли какое-то более изящное решение. Можно ли например как-то определить, что объект является числом и как-то в общем виде его распарсить?
Это возможно только если жёстко известен формат этих строковых данных.
И, если это задано, то надо парсить элементы согласно этому формату, а не в общем виде.
Иначе это невозможно в принципе. Например, 10/12/2010 это 10 декабря или 12 октября?
12,345 это двенадцать целых триста сорок пять тысячных или двенадцать тысяч триста сорок пять?
Re: Как в общем виде распарсить число?
От: Spiceman  
Дата: 16.03.10 19:20
Оценка:
Здравствуйте, Аноним, Вы писали:

Если типы простые то можно через Convert.ChangeType().
Например,
        int a = (int)Convert.ChangeType("1", typeof(int));


Или обернуть в более удобную функцию
        static T ConvertTo<T>(string str)
        {
            return (T)Convert.ChangeType(str, typeof(T));
        }
        static void Main(string[] args)
        {
            int a = ConvertTo<int>("1");
            DateTime b = ConvertTo<DateTime>("01.01.2010");
        }
Re: Как в общем виде распарсить число?
От: sto Украина http://overstore.codeplex.com
Дата: 16.03.10 19:26
Оценка:
Здравствуйте, Аноним, Вы писали:

А> Есть менеджер, которому передается экземпляр класса и некий массив строковых данных. Экземпляр передается любого класса (заранее неизвестного). Нужно пройтись по всем свойствам этого класса и попытаться распарсить значения в соответствующем элементе массива. То есть, например, если у нас пятое по счету свойство является типом 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 десятка наверное). Хотелось бы хотябы обойтись двумя проверками — целочисленный тип и с плавающей точкой.

код не компилирующийся — просто чтобы показать принцип

object sourceValue = ...

object valueToSet = null;

if(propertyInfo.PropertyType == typeof(Int16))
{
   Int16.TryParse(sourceValue, out valueToSet);
}
else if(propertyInfo.PropertyType == typeof(Int32))
{
   Int32.TryParse(sourceValue, out valueToSet);
}
...

else if(propertyInfo.PropertyType == typeof(UInt16))
{
   UInt16.TryParse(sourceValue, out valueToSet);
}
...

else if(propertyInfo.PropertyType == typeof(Double))
{
   Double.TryParse(sourceValue, out valueToSet);
}

...
propertyInfo.SetValue(obj,valueToSet);
Re[3]: Как в общем виде распарсить число?
От: Spiceman  
Дата: 16.03.10 21:50
Оценка:
Здравствуйте, Аноним, Вы писали:

А>код не компилирующийся — просто чтобы показать принцип

А>
А>object sourceValue = ...
А>object valueToSet = null;
А>if(propertyInfo.PropertyType == typeof(Int16))
А>{
А>   Int16.TryParse(sourceValue, out valueToSet);
А>}
А>


Ну так а чем не устраивает Convert.ChangeType ?
object sourceValue = ...
object valueToSet = Convert.ChangeType(sourceValue, propertyInfo.PropertyType);
Re: Как в общем виде распарсить число?
От: Kalina9001  
Дата: 17.03.10 08:39
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А> Есть менеджер, которому передается экземпляр класса и некий массив строковых данных. Экземпляр передается любого класса (заранее неизвестного). Нужно пройтись по всем свойствам этого класса и попытаться распарсить значения в соответствующем элементе массива. То есть, например, если у нас пятое по счету свойство является типом 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 как источник данных.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.