Я хочу загрузить файл свойств (это - .csv наличие файла на каждой строке имя и связанное числовое значение), и затем получите доступ к тем значениям свойств как так: FileLoader.PropertyOne
или FileLoader.PropertyTwo
. Проблема, я не хочу должным быть писать свойство для каждого значения, я хочу, чтобы они были сгенерированы из файла. Так
public class FileLoader
{
public int Property1 { get; private set; }
}
не то, что я ищу. Действительно ли это возможно? Я не вижу способа сделать это, потому что, очевидно, компилятор не знал бы об именах свойства. Возможно, что-то подобное?
В C # 4.0 вы можете использовать ExpandoObject , ссылка содержит хорошее объяснение и несколько вариантов использования, например:
dynamic contact = new ExpandoObject();
contact.Name = "Patrick Hines";
contact.Phone = "206-555-0144";
contact.Address = new ExpandoObject();
contact.Address.Street = "123 Main St";
contact.Address.City = "Mercer Island";
contact.Address.State = "WA";
contact.Address.Postal = "68402";
Хотя великолепие ExpandoObject заключается в динамическом создании сложных иерархических объектов, я полагаю, вы могли бы использовать его в целом из-за его блестящего синтаксиса даже для простых динамически определяемых объектов.
РЕДАКТИРОВАТЬ: Вот еще один ответ на SO, добавляющий подробности о преимуществах ExpandoObject тем же обозревателем, который написал ранее связанную статью
Генерация кода , подобная этому, может выполняться несколькими способами.
.generated.cs
). Если ваш "FileLoader" фактически не перезаписывает себя, а затем использует Reflection для доступа к вновь созданным свойствам, на самом деле это невозможно сделать. (Полностью игнорируйте этот ответ, если вам нужно что-то, что работает во время разработки / компиляции, а не во время выполнения =)
В конечном итоге вы, вероятно, получите что-то вроде
public class FileLoader
{
// ... Other code for FileLoader goes here
public FileLoader(string propertiesFileNameAndPath)
{
// Load values from propertiesFile into _properties / _propertyValues
}
private _properties = new List<string>();
private _propertyValues = new Dictionary<string, string>();
public string[] Properties
{
// returning as an array stops your _properties being modified
return _properties.ToArray();
}
public void UpdateProperty(string propertyName, string propertyValue)
{
if (propertyValues.ContainsKey(propertyName))
{
propertyValues[propertyName] = propertyValue;
}
}
public string GetPropertyValue(string propertyValue)
{
if (propertyValues.ContainsKey(propertyName))
{
return propertyValues[propertyName];
}
}
}
Теперь вы можете:
var fileLoader = new FileLoader("path to properties.csv");
foreach(var property in fileLoader.Properties)
{
var propertyValue = fileLoader.GetPropertyValue(property);
}
] Конечно, вы могли бы просто упростить его до загрузки в словарь, который вы возвращаете из метода в FileLoader, но в приведенном выше коде сохраняется часть «внешнего вида» использования свойств класса FileLoader =)
Изменить: Добавить Код "индексатора"
Одна вещь, которая может сделать синтаксис более чистым, - это использовать "Индексатор", поэтому вы должны добавить следующее в FileLoader:
public string this[string index]
{
if (propertyValues.ContainsKey(propertyName))
{
return propertyValues[propertyName];
}
else
{
return null;
}
}
Тогда код для доступа к нему будет немного аккуратнее:
var fileLoader = new FileLoader("path to properties.csv");
foreach(var property in fileLoader.Properties)
{
var propertyValue = fileLoader[property];
}
Вот пример использования ExpandoObject
и динамической функции C # 4.0
public dynamic ParseCsvFile(string filePath) {
var expando = new ExpandoObject;
IDictionary<string,object> map = expando;
foreach ( var line in File.ReadAllLines(filePath)) {
var array = line.Split(new char[]{','},2);
map.Add(array[0],array[1]);
}
return expando;
}
...
var d = ParseCsvFile(someFilePath);
Console.WriteLine(d.Property1);
По сути, вам нужно будет произвести генерацию кода.
Напишите простое консольное приложение или приложение win forms, которое загружает CSV, затем берет информацию из CSV и генерирует файлы .cs.
Это возможно с помощью нового динамического материала в C # 4.0. Я не эксперт, но с динамическими объектами вы можете определить поведение, когда вызывается несуществующий метод. Этот пост показывает довольно забавный пример того, как настроить динамический словарь, который мог бы делать то, что вы хотите.
Для этого есть простое решение: считайте свойства в словарь и перегрузите оператор массива FileLoader
:
public T this[string propertyName]
{
get { return yourDictionary[propertyName]; }
}
That Таким образом, вы можете получить доступ к свойствам, используя fileLoadObject ["SomePropertyName"]
.
Как указал Одед, возможно динамически добавлять свойства с помощью Reflection. Вот пример здесь .