【问题标题】:Track changes of an object contained in a Dictionary<TKey, TValue> and change its TKey accordingly跟踪 Dictionary<TKey, TValue> 中包含的对象的更改并相应更改其 TKey
【发布时间】:2011-05-11 13:40:20
【问题描述】:

我正在编写一个类库来与域 Active Directory 交互。在我的对象模型中,我有以下内容:

  1. 域;
  2. 组织单位;
  3. 组;
  4. 用户。

在我的 Domain 对象中,我有一个 Entries 属性和一个 Add() 方法。

public class Domain {
    // The ReadOnlyDictionary<TKey, TValue> is a custom wrapper over an IDictionary.
    public ReadOnlyDictionary<string, IDirectoryEntry> Entries { get; }

    public void Add(IDirectoryEntry entry) {
        Entries.Add(entry.Name, entry);
    }
}

现在,假设我有以下代码测试更改。

[Test()]
public void ChangeTesting {
    Domain domain = new Domain("LDAP://...");
    Group g = new Group("groupName");

    domain.Add(g);

    g.Name = "ChangedName";

    Assert.IsTrue(domain.ContainsKey("ChangedName"));
}

为了您的信息,我实现了INotifyPropertyChanged 接口来简化我的生活,但我似乎没有找到一种方法让它按我想要的方式工作。或许是我做的不对,至于不同方法的位置,我不知道。

如何让我的Domain 知道其中一个Entries 中发生的更改,以便TKey 的值也发生更改?

这是需要的,因为可能会添加一个条目,更改其名称同时添加一个具有实际内部条目的“旧”名称的新条目,并导致冲突等。最终导致测试失败.但我想让它像实际一样通过。

还有其他更好的方法或解决方法吗?

【问题讨论】:

  • 我认为最简单的解决方法是删除并再次添加一个项目。
  • 这也是我想到的。关键是对用户来说尽可能的简单,但最终还是给自己添麻烦也好! =) 谢谢你的意见! =)

标签: c# vb.net dictionary inotifypropertychanged


【解决方案1】:

这是一个真的糟糕的 hack,在多线程环境中它可能会惨遭失败,但这里是:

private Dictionary<IDirectoryEntry, PropertyChangedEventHandler> eventHandlers =
    new Dictionary<IDirectoryEntry, PropertyChangedEventHandler>();

public void Add(IDirectoryEntry entry) {
    string oldName = entry.Name;

    PropertyChangedEventHandler h;
    h = (o, args) => {
        if (args.PropertyName == "Name" &&
                entry.Name != oldName &&
                Entries[oldName] == entry) {
            entry.PropertyChanged -= h;
            Entries.Remove(oldName);
            Add(entry);
        }
    };

    eventHandlers[entry] = h;
    entry.PropertyChanged += h;

    Entries.Add(entry.Name, entry);
}

public void Remove(IDirectoryEntry entry) {
    if (Entries[entry.Name] == entry) {
        Entries.Remove(entry.Name);
        eventHandlers.Remove(entry);
    }
}

如果您期望并发活动,您可能希望在匿名方法中为每个处理程序 AND 指定 lock。 (这可能意味着从一个线程中删除一个条目并从另一个线程更改一个条目的名称!)

【讨论】:

  • 谢谢!是的,会有一个Remove 方法,以防用户不再希望将条目添加到他的域中。最后,它最终会从同一个字典中删除和添加。
  • 已更新。请注意我在最后添加的注释——如果您不修改它以正确锁定,多线程访问将终止此代码。
  • 当你说“这是一个真的糟糕的 hack”时,我知道这远非一个好的做法/方法,这可能会导致以后出现缺陷,赢了不是吗?以您谦逊的观点,我是否在这里过于复杂化了图书馆最终用户的一点点收益?对于域对象中的条目,我是否最好采用“自己动手”的方法?
  • @cdhowie: Dictionary&lt;TKey, TValue&gt; 本身是非线程安全的。你不会失去任何东西。
  • @SLaks:当然,我并不是说我的 hack 的线程安全性低于原始代码,只是两者都不是线程安全的(至少从修剪后的代码看起来是这样)遗嘱)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-14
  • 2011-01-16
  • 2011-04-11
  • 1970-01-01
相关资源
最近更新 更多