Skip to content

Commit

Permalink
simplify IObjectBase interface
Browse files Browse the repository at this point in the history
  • Loading branch information
hahn-kev committed Oct 9, 2024
1 parent 8077a68 commit 77179a5
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 30 deletions.
6 changes: 1 addition & 5 deletions src/SIL.Harmony.Tests/Adapter/CustomObjectAdapterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,7 @@ public DateTimeOffset? DeletedAt
set => Obj.DeletedTime = value?.ToUnixTimeSeconds();
}

[JsonIgnore]
public string ObjectTypeName => Obj.TypeName;

[JsonIgnore]
public Type ObjectType => typeof(MyClass);
public string GetObjectTypeName() => Obj.TypeName;

[JsonIgnore]
public object DbObject => Obj;
Expand Down
11 changes: 11 additions & 0 deletions src/SIL.Harmony.Tests/ObjectBaseTestingHelpers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using SIL.Harmony.Entities;

namespace SIL.Harmony.Tests;

public static class ObjectBaseTestingHelpers
{
public static T Is<T>(this IObjectBase obj) where T : class
{
return (T) obj.DbObject;
}
}
8 changes: 2 additions & 6 deletions src/SIL.Harmony/Adapters/CustomAdapterProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,13 @@ IObjectBase IObjectAdapterProvider.Adapt(object obj)
}
}

// it's possible to implement this without a Common interface, but it would require the adapter to have 1 property for each object type
// it's possible to implement this without a Common interface
// but it would require the adapter to have 1 property for each object type in order to support deserialization
public interface ICustomAdapter<TSelf, TCommonInterface> : IObjectBase, IPolyType
where TSelf : class,
ICustomAdapter<TSelf, TCommonInterface>
{
public static abstract TSelf Create(TCommonInterface obj);
static string IPolyType.TypeName => TSelf.AdapterTypeName;
public static abstract string AdapterTypeName { get; }

T IObjectBase.Is<T>()
{
return (T)DbObject;
}
}
2 changes: 1 addition & 1 deletion src/SIL.Harmony/Changes/ChangeContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ internal ChangeContext(Commit commit, SnapshotWorker worker, CrdtConfig crdtConf
public async ValueTask<ObjectSnapshot?> GetSnapshot(Guid entityId) => await _worker.GetSnapshot(entityId);

public async ValueTask<bool> IsObjectDeleted(Guid entityId) => (await GetSnapshot(entityId))?.EntityIsDeleted ?? true;
public IObjectBase Adapt(object obj) => _crdtConfig.ObjectTypeListBuilder.AdapterProvider.Adapt(obj);
internal IObjectBase Adapt(object obj) => _crdtConfig.ObjectTypeListBuilder.AdapterProvider.Adapt(obj);
}
4 changes: 2 additions & 2 deletions src/SIL.Harmony/Db/CrdtRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ public async Task<object> GetObjectBySnapshotId(Guid snapshotId)
var snapshot = await Snapshots
.DefaultOrder()
.LastOrDefaultAsync(s => s.EntityId == objectId && (ignoreChangesAfter == null || s.Commit.DateTime <= ignoreChangesAfter));
return snapshot?.Entity.Is<T>();
return (T?) snapshot?.Entity.DbObject;
}

public IQueryable<T> GetCurrentObjects<T>() where T : class
Expand Down Expand Up @@ -228,7 +228,7 @@ private async ValueTask SnapshotAdded(ObjectSnapshot objectSnapshot)
if (!crdtConfig.Value.EnableProjectedTables) return;
if (objectSnapshot.IsRoot && objectSnapshot.EntityIsDeleted) return;
//need to check if an entry exists already, even if this is the root commit it may have already been added to the db
var existingEntry = await GetEntityEntry(objectSnapshot.Entity.ObjectType, objectSnapshot.EntityId);
var existingEntry = await GetEntityEntry(objectSnapshot.Entity.DbObject.GetType(), objectSnapshot.EntityId);
if (existingEntry is null && objectSnapshot.IsRoot)
{
//if we don't make a copy first then the entity will be tracked by the context and be modified
Expand Down
2 changes: 1 addition & 1 deletion src/SIL.Harmony/Db/ObjectSnapshot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public ObjectSnapshot(IObjectBase entity, Commit commit, bool isRoot) : this()
References = entity.GetReferences();
EntityId = entity.Id;
EntityIsDeleted = entity.DeletedAt.HasValue;
TypeName = entity.ObjectTypeName;
TypeName = entity.GetObjectTypeName();
CommitId = commit.Id;
Commit = commit;
IsRoot = isRoot;
Expand Down
34 changes: 19 additions & 15 deletions src/SIL.Harmony/Entities/IObjectBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,35 @@ public interface IObjectBase
Guid Id { get; }
DateTimeOffset? DeletedAt { get; set; }

public T Is<T>()
{
return (T)this;
}

public T? As<T>() where T : class, IObjectBase
{
return this as T;
}

/// <summary>
/// provides the references this object has to other objects, when those objects are deleted
/// <see cref="RemoveReference"/> will be called to remove the reference
/// </summary>
/// <returns></returns>
public Guid[] GetReferences();
/// <summary>
/// remove a reference to another object, in some cases this may cause this object to be deleted
/// </summary>
/// <param name="id">id of the deleted object</param>
/// <param name="commit">
/// commit where the reference was removed
/// should be used to set the deleted date for this object
/// </param>
public void RemoveReference(Guid id, Commit commit);

public IObjectBase Copy();
public string ObjectTypeName { get; }
public Type ObjectType { get; }
/// <summary>
/// the name of the object type, this is used to discriminate between different types of objects in the snapshots table
/// </summary>
/// <returns>a stable type name of this object, should not change over time</returns>
public string GetObjectTypeName();
[JsonIgnore]
public object DbObject { get; }
// static string IPolyType.TypeName => throw new NotImplementedException();
}

public interface IObjectBase<TThis> : IObjectBase, IPolyType where TThis : IPolyType
{
string IObjectBase.ObjectTypeName => TThis.TypeName;
Type IObjectBase.ObjectType => typeof(TThis);
string IObjectBase.GetObjectTypeName() => TThis.TypeName;
static string IPolyType.TypeName => typeof(TThis).Name;
[JsonIgnore]
object IObjectBase.DbObject => this;
Expand Down

0 comments on commit 77179a5

Please sign in to comment.