public IAdapter <T> ReadOrUpdate <T>(DataId id) where T : class, IDataShape { return (_storage.TryGetValue(id, out var value) && value is T shape ? new Adapter <T>(shape, _modified) : null); }
public IAdapter <T> Create <T>(DataId idParent) where T : class, IDataShape { if (_factories.TryGetValue(typeof(T), out var factory)) { if (_storage.ContainsKey(idParent)) { var shape = factory(idParent, _idGenerator.Create()) as T; _storage.Add(shape.Id, shape); _modified.Add(shape); return(new Adapter <T>(shape, _modified)); } if (_storage.Count == 0 && idParent.IsWild) { var shape = factory(new DataId(), _idGenerator.Create()) as T; _storage.Add(shape.Id, shape); _modified.Add(shape); return(new Adapter <T>(shape, _modified)); } } return(null); }
public void Delete(DataId id) { // можно для каждого узла проверять рут ветки // и если он не совпадает с рутом репозитория - считать его удаленным // и вообще поудобнее все операции на специальной структуре данных можно было бы сделать // это увеличило бы производительность, но это отдельное и довольно большое задание и // в ТЗ про скорость ничего не написано, по этому будет вот так if (_storage.TryGetValue(id, out var shape)) { var set = new Queue <IDataShape>(); set.Enqueue(shape); while (set.Count > 0) { var item = set.Dequeue(); _deleted.Add(item); _modified.RemoveWhere(_ => _.Id.Equals(item.Id)); foreach (var child in _storage.Where(_ => _.Value.IdParent.Equals(item.Id))) { set.Enqueue(child.Value); } } } }
private static void Main(string[] args) { // пример использования // можно сделать какие нибудь расширения чтобы конфигурирование // было больше похоже на класическое флюент кодом c билдером в конце var repository = new Repository(); DataId root; var idChildren = new DataId[10]; using (var adapter = repository.Create <DataCircle>(new DataId())) { adapter.Get().Radius = 5d; root = adapter.Get().Id; } // create for (var index = 0; index < idChildren.Length; index++) { if (index % 3 == 0) { using (var adapter = repository.Create <DataCircle>(root)) { adapter.Get().Radius = 5d; idChildren[index] = adapter.Get().Id; } } else if (index % 3 == 1) { using (var adapter = repository.Create <DataSquare>(root)) { adapter.Get().Side = 5d; idChildren[index] = adapter.Get().Id; } } else if (index % 3 == 2) { using (var adapter = repository.Create <DataRectangle>(root)) { adapter.Get().Width = 5d; adapter.Get().Height = 5d; idChildren[index] = adapter.Get().Id; } } } // комит к стати тоже можно во что нибудь такое же обернуть repository.Commit(); // modify for (var index = 0; index < idChildren.Length; index++) { if (index % 3 == 0) { using (var adapter = repository.ReadOrUpdate <DataCircle>(idChildren[index])) { // не изменяется, не сохраняется adapter.Get().Radius = 5d; idChildren[index] = adapter.Get().Id; } } else if (index % 3 == 2) { using (var adapter = repository.ReadOrUpdate <DataRectangle>(idChildren[index])) { // изменяется, сохраняется adapter.Get().Width *= 2d; adapter.Get().Height = 5d; idChildren[index] = adapter.Get().Id; } } } repository.Commit(); // delete for (var index = 0; index < idChildren.Length; index++) { if (index % 3 == 0) { repository.Delete(idChildren[index]); } } repository.Commit(); }
public DataRectangle(DataId idSelf, DataId idParent) { Id = idSelf; IdParent = idParent; }
public DataSquare(DataId idSelf, DataId idParent) { Id = idSelf; IdParent = idParent; }
public DataCircle(DataId idSelf, DataId idParent) { Id = idSelf; IdParent = idParent; }