C#中的属性字典

时间:2013-01-12 04:23:14

标签: c# dictionary

我有一系列'代码',我想引用我班级的属性。但是,当我设置字典的值时,属性不会更新。下面的例子

public Foo() {
    this.CodeMap = new Dictionary<string, object>();
    this.CodeMap.Add("stat", this.Status);
    this.CodeMap.Add("ver", this.Version);
}

public int Status { get; set; }

public int Version { get; set; }

和调用代码

foo.CodeMap["stat"] = 27;
/* foo.Status is not set to 27 */

有没有办法在.NET中执行此操作。我相信错误的发生是因为字典值不是ref值,但我不确定这样做的最佳方法。我看到https://stackoverflow.com/a/10350484/450745,但这与我想要的相反。

5 个答案:

答案 0 :(得分:1)

  

我认为发生错误是因为字典值不是ref值,

不,因为你没有设置foo.Statusfoo.CodeMapfoo.Status不同。

如果要同步值,则应手动执行。您可以继承IDictionary<TKey,TValue>并覆盖Add方法。

喜欢

void Add(TKey key, TValue value)
{
   if (key is string && key.Equals("stat"))
   {
      this.stat = (int)value;
   }
}

答案 1 :(得分:1)

您的代码不起作用,因为您将{Key>“stat”添加到Dictionary,其中包含分配时状态所具有的任何值。当您稍后更新该Key的值时,它不会自动更新您的属性。您正在将某个时间点的属性值添加到Dictionary,而不是属性本身。

使用标准Dictionary无法实现您的目标。你有几个看起来并不可怕的选择。

可观察词典

请参阅此blog post和此stackoverflow thread

一般的想法是编写一个继承自IDictionary<TKey, TValue>INotifyCollectionChangedINotifyPropertyChanged的类。

这将为您提供一些钩子,您可以编写事件处理程序,理论上可以让您更新某些属性或其他任何您想要做的事情。

重构您的代码

如果您不喜欢上述内容,那么您可以稍微重构一下代码。

考虑一下:

public class Foo
{
    public Dictionary<string, object> CodeMap;

    public int Status
    {
        get 
        {
            int status;
            if (int.TryParse(CodeMap["stat"].ToString(), out status))
            {
                return status;
            }
            else
            {
                throw new Exception("Status has a non-numeric value");
            }
        }
        set 
        { 
            CodeMap["stat"] = value; 
        }
    }

    public Foo()
    {
        CodeMap = new Dictionary<string, object>();
    }
}

然后你可以拨打同一个电话:

Foo foo = new Foo();
foo.CodeMap["stat"] = 27;

Console.WriteLine(foo.Status.ToString());  // prints 27

希望这很有效,为什么会有效。现在,该属性实际引用了Dictionary。请注意,您无法像以前一样添加初始值,因为当getter尝试访问该Key时,您将获得KeyNotFoundException。我认为这是一个相当小的缺点。

答案 2 :(得分:1)

对于未来的观众,在简单的情况下,它足以使用Func&#39;&#39;&gt;&#39;&#39;

  public string TestProperty {get; set;}
  public Dictionary<int, Func<string>> dictionary;

  Constructor()
  {
    dictionary = new Dictionary<int, Func<string>>
    {
        {1, ()=>TestProperty }
    }
  }

当这样使用时:

  dictionary[1]() or dictionary[1].Invoke()

此时它返回属性的实际值。

答案 3 :(得分:0)

Dictionary不会更新先前value属性的值。当您存储foo.CodeMap["stat"] = 27; foo.CodeMap["stat"]的早期值(Status的值)被27覆盖时。

字典中的密钥(在您的情况下为“stat”)标识的位置是数据存储,即CodeMap["stat"]是数据的存储位置,而不是相反。您在此位置存储的任何内容都会覆盖以前的数据。

您应该详细说明您要解决的实际问题。您的问题不够明确,读者无法推断出实际需要/问题。

答案 4 :(得分:0)

另一种方法是使用ExpandoObject。 这是单向绑定到字典的示例:

public class Foo
{
    public Foo()
    {
        Properties = new ExpandoObject();
        Status = 0;
        Version = 0;
    }

    public dynamic Properties { get; set; }

    public IDictionary<string, object> CodeMap
    {
        get { return Properties; }
    }

    private int _status;
    public int Status
    {
        get { return _status; }
        set
        {
            _status = value;
            Properties.stat = _status;
        }
    }

    private int _version;
    public int Version
    {
        get { return _version; }
        set
        {
            _version = value;
            Properties.ver = _version;
        }
    }
}

使用:

var foo = new Foo
                {
                    Status = 1,
                    Version = 2
                };

Console.WriteLine(foo.CodeMap["stat"]);
Console.WriteLine(foo.CodeMap["ver"]);
Console.WriteLine(foo.Properties.stat);
Console.WriteLine(foo.Properties.ver);