using System; using System.Collections.Generic; using System.Text; namespace ln.collections { public class ObjectIdentityCache { Dictionary objectsByIdentity = new Dictionary(); Dictionary identitiesByObject = new Dictionary(); Func IdGetter; public ObjectIdentityCache(Func idGetter) { if (idGetter == null) throw new ArgumentNullException(nameof(idGetter)); IdGetter = idGetter; } public object this[object identity] => objectsByIdentity[identity]; public void Update(object o) { if (identitiesByObject.TryGetValue(o, out object knownObject) && (!object.Equals(o, knownObject))) throw new ArgumentException("another instance already known with this identity", nameof(o)); if (!object.ReferenceEquals(null, knownObject)) { object knownIdentity = identitiesByObject[knownObject]; object objectIdentity = IdGetter(knownObject); if (!object.Equals(knownIdentity, objectIdentity)) { objectsByIdentity.Remove(knownIdentity); objectsByIdentity.Add(knownIdentity, knownObject); identitiesByObject[knownObject] = objectIdentity; } } else { object objectIdentity = IdGetter(o); objectsByIdentity.Add(objectIdentity, o); identitiesByObject.Add(o, objectIdentity); } } public void RemoveObject(object o) { if (identitiesByObject.TryGetValue(o, out object objectIdentity)) { identitiesByObject.Remove(o); objectsByIdentity.Remove(objectIdentity); } } public void RemoveIdentity(object objectIdentity) { if (objectsByIdentity.TryGetValue(objectIdentity, out object o)) { objectsByIdentity.Remove(objectIdentity); identitiesByObject.Remove(o); } } } }