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:
- Domain;
- Organizational Unit;
- Group;
- 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!)
精彩评论