开发者

Track changes of an object contained in a Dictionary<TKey, TValue> and change its TKey accordingly

I am writing a class library to interact with a domain Active Directory. In my object model, I have the following:

  1. Domain;
  2. Organizational Unit;
  3. Group;
  4. User.

In my Domain object, I have an Entries property and an Add() method.

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);
    }
}

Now, let's suppose I have the following code testing for changes.

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

    domain.Add(g);

    g.Name = "ChangedName";

开发者_C百科    Assert.IsTrue(domain.ContainsKey("ChangedName"));
}

For your information, I implemented the INotifyPropertyChanged interface to ease my life, but I don't seem to find a way to make it work the way I want. Perhaps am I not doing things right somehow, as for the location of different methods, I don't know.

How can I make my Domain aware of a change that occured within one of its Entries, so that the TKey value is also changed?

That is wanted because one could possibly add an entry, change its name meanwhile adding a new entry with the "old" name of the actual within entry, and cause a conflict, etc. In the end, causing the test to fail. But I'd like to make it pass like it actually is.

Is there another better approach or workaround?


This is a really bad hack, and it will probably fail miserably in a multithreaded environment, but here goes:

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);
    }
}

You will probably want to lock on something for each handler AND inside the anonymous method if you expect concurrent activity. (This could mean removing an entry from one thread and changing the name of an entry from another!)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜