如何动态(通过变量)访问动态对象的属性?

时间:2014-08-18 07:02:27

标签: c# variables dynamictype

我有一个名为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的值。有解决方法吗?

感谢。

1 个答案:

答案 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.
相关问题