我有一个名为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
的值。有解决方法吗?
感谢。
答案 0 :(得分:2)
C#动态功能部分编译,如属性/方法访问。要理解这一点,我们举一个例子。
dynamic myVar = new { a=1, b="test" };
myVar.a += 1;
这里C#类型系统在编译时不会测试属性的有效性,只是在运行时执行代码,如果找不到属性,它将通过运行时错误。
因此,在您的代码中,属性访问已经被编译为访问名为&#34; s&#34;在动态对象&#34;配置&#34;。
在C#no-way中,即使在动态类型语言(如python或javascript)中也无法做到这一点。
你必须这样使用。
dynamic configuration = getConfig("path/to/file");
var myobj = configuration as IDictionary<string,object>;
string s = "config_key";
var value = myobj[s]; // this is correct.