【发布时间】:2014-10-11 01:04:44
【问题描述】:
我有一个名为 Configuration 的类,它继承自 DynamicObject。它是Dictionary<string, object>。在构造函数中,它读取一个文本文件并从中加载由=分割的所有值,因此您可以像这样创建动态配置对象:
dynamic configuration = new Configuration("some_file.ini");
这是我的完整课程:
public sealed class Configuration : DynamicObject
{
private string Path { get; set; }
private Dictionary<string, object> Dictionary { get; set; }
public Configuration(string fileName)
{
this.Path = fileName;
this.Dictionary = new Dictionary<string, object>();
this.Populate();
}
~Configuration()
{
if (this.Dictionary != null)
{
this.Dictionary.Clear();
}
}
private void Populate()
{
using (StreamReader reader = new StreamReader(this.Path))
{
string line;
string currentSection = string.Empty;
while ((line = reader.ReadLine()) != null)
{
if (string.IsNullOrWhiteSpace(line))
{
continue;
}
if (line.StartsWith("[") && line.EndsWith("]"))
{
currentSection = line.Trim('[', ']');
}
else if (line.Contains("="))
{
this.Dictionary.Add(string.Format("{0}{1}{2}",
currentSection,
(currentSection != string.Empty) ? "_" : string.Empty,
line.Split('=')[0].Trim()),
ParseValue(line.Split('=')[1].Trim().Split(';')[0]));
}
}
}
}
private object ParseValue(string value)
{
if (string.IsNullOrWhiteSpace(value))
return string.Empty;
if (value.StartsWith("\"") && value.EndsWith("\""))
return value.Substring(1, value.Length - 1);
if (IsNumeric(value))
return Convert.ToInt32(value);
// TODO: FIXME Floating values (not to be confuse with IPAddress).
//if (IsFloating(value))
// return Convert.ToDouble(value);
if (string.Compare(value, "true", StringComparison.OrdinalIgnoreCase) == 0)
return true;
if (string.Compare(value, "false", StringComparison.OrdinalIgnoreCase) == 0)
return false;
return value;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (this.Dictionary.ContainsKey(binder.Name))
{
if (this.Dictionary[binder.Name] == null)
{
result = null;
}
else
{
result = this.Dictionary[binder.Name];
}
return true;
}
throw new ConfigurationException(binder.Name);
}
public override string ToString()
{
string result = this.Path + " [ ";
int processed = 0;
foreach (KeyValuePair<string, object> value in this.Dictionary)
{
result += value.Key;
processed++;
if (processed < this.Dictionary.Count)
{
result += ", ";
}
}
result += " ]";
return result;
}
private static bool IsNumeric(string value)
{
foreach (char c in value)
if (!char.IsDigit(c))
return false;
return true;
}
private static bool IsFloating(string value)
{
foreach (char c in value)
if (!char.IsDigit(c) && c != '.')
return false;
return true;
}
private class NullObject { }
}
一切都完美无缺。我已经覆盖了 TryGetMember 并且我正在返回基于 GetMemberBinder Name 属性的对象。但是,我遇到了一个问题。
当我执行以下代码时:
string s = "some_config_key";
string d = configuration.s;
它检索键 s 而不是 some_config_key 的值,这意味着它不会评估变量 s 的值。有解决办法吗?
谢谢。
【问题讨论】:
-
@user2864740 已编辑。对不起。
-
你为什么不也实现
this[string]属性,那么你可以写configuration[s] -
我也会使用索引器,就像@Dirk 建议的那样
标签: c# variables dynamictype