С# Строка описания для типа, известная во время выполнения
У меня есть файл, содержащий некоторые из переменных класса, и каждая строка представляет собой пару: variable, value. Я ищу способ загрузить их во время выполнения (a-la XmlSerializer
), используя отражение.
Есть ли способ проанализировать string
в Type
, который известен только во время выполнения?
Ниже приведен пример желаемого кода, в котором последняя строка (с pi.SetValue()
неверна, поскольку PropertyType
имеет класс Type
, который не имеет общего метода Parse()
.
using (var sr = new StreamReader(settingsFileName))
{
String line;
while ((line = sr.ReadLine()) != null)
{
String[] configValueStrs = line.Trim().Split(seps);
PropertyInfo pi = configurableProperties
.Single(p => p.Name == configValueStrs[0].Trim());
//How do I manage this?
pi.SetValue(this, pi.PropertyType.Parse(configValueStrs[1].Trim()), null);
}
}
Поскольку все соответствующие переменные являются Ints, Doubles, Strings или Booleans, в качестве последнего средства, я могу включить тип и использовать соответствующий метод ToType()
, но я уверен, что есть более элегантное решение.
Ответы
Ответ 1
Для этого можно использовать статический метод Convert.ChangeType
. Он принимает в качестве первого параметра объект и Type
экземпляр, в который вы хотите преобразовать объект. Возвращаемое значение относится к типу, который вы запросили, или null, если подходящее преобразование не найдено. Этот метод выдает четыре разных исключения, из которых три вызваны значением, которое он пытается преобразовать. Вы можете захотеть поймать и обработать их.
Используйте следующую функцию в своем примере:
// Convert.ChangeType can throw if the string doesn't convert to any known type
pi.SetValue(this
, Convert.ChangeType(configValueStrs[1], pi.PropertyType)
, null);
Ответ 2
TypeConverters - это путь. Посмотрите here для хорошего примера того, что делать.
Ник прямо из блога hanselmans:
public static T GetTfromString<T>(string mystring)
{
var foo = TypeDescriptor.GetConverter(typeof(T));
return (T)(foo.ConvertFromInvariantString(mystring));
}
Ответ 3
Я считаю, что TypeConverters
, в частности StringConverter
может помочь вам с этой проблемой.
http://msdn.microsoft.com/en-us/library/system.componentmodel.stringconverter.aspx
Ответ 4
Я бы рекомендовал использовать MethodInfo для свойства для метода Parse и посмотреть, действительно ли объект MethodInfo. Затем выполните операцию анализа, если она действительна.
http://msdn.microsoft.com/en-us/library/system.reflection.methodinfo.aspx
Ответ 5
У меня была та же задача загрузить переменные класса, используя отражение. Я загружаю строки пары ключ/значение из файла, затем анализирую значения, основываясь на определениях ключевых переменных ключей из моего класса настроек.
Вкратце, я использую следующий код (метод FieldInfo.SetValue (Object, Object)
- это ключ здесь, потому что он не требует какого-либо преобразования типа значения Object
, возвращаемого методом TypeConverter.ConvertFromString
):
using System.Reflection;
using System.ComponentModel;
using System.Globalization;
....
Settings settings = new Settings(); // my Settings class with variables to load
FieldInfo[] fields = settings.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Static);
....
foreach (var field in fields)
{
if (key.KeyName == field.Name)
{
try
{
field.SetValue(settings, TypeDescriptor.GetConverter(field.FieldType).ConvertFromString(null, CultureInfo.InvariantCulture, key.Value));
}
catch (Exception ex)
{
Console.WriteLine("Error: The value string \"{0}\" isn't parsed!", key.Value);
//Console.WriteLine(ex.ToString());
}
break;
}
}