Skip to content

Commit

Permalink
Implement a id for each generated model to further reduce boilerplate…
Browse files Browse the repository at this point in the history
… code
  • Loading branch information
halgari committed Jun 4, 2024
1 parent cb212b8 commit 6e52241
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 4 deletions.
70 changes: 68 additions & 2 deletions src/NexusMods.MnemonicDB.SourceGenerator/Template.weave
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using TransparentValueObjects;

namespace {{= model.Namespace}};
using __ABSTRACTIONS__ = NexusMods.MnemonicDB.Abstractions;
Expand Down Expand Up @@ -143,14 +144,26 @@ public partial class {{= model.Name}} {
return model.Id;
}

/// <summary>
/// Implicit conversion from the model to the model id.
/// </summary>
public static implicit operator {{= model.Name}}Id({{= model.Name}}.New model) {
return model.{{= model.Name}}Id;
}

/// <summary>
/// The entity id of the model as a model id.
/// </summary>
public {{= model.Name}}Id {{= model.Name}}Id => {{= model.Name}}Id.From(Id);

/// <inheritdoc />
public __ABSTRACTIONS__.EntityId Id { get; private set; }

#region Attributes
{{each attr in model.Attributes}}
{{= attr.Comments}}
{{if attr.IsReference && !attr.IsCollection}}
public required {{= attr.HighLevelType.ToDisplayString()}} {{= attr.ContextualName}} { get; init; }
public required {{= attr.ReferenceType.ToDisplayString()}}Id {{= attr.ContextualName}} { get; init; }
{{elif attr.IsReference && attr.IsCollection}}
public required {{= attr.HighLevelType.ToDisplayString()}}[] {{= attr.ContextualName}} { get; init; }
{{elif attr.IsMarker}}
Expand Down Expand Up @@ -198,6 +211,9 @@ public partial class {{= model.Name}} {
/// </summary>
public __ABSTRACTIONS__.EntityId Id { get; }

/// <inheritdoc />
public {{= model.Name}}Id {{= model.Name}}Id => {{= model.Name}}Id.From(Id);

/// <summary>
/// The database that the entity is associated with.
/// </summary>
Expand Down Expand Up @@ -268,6 +284,8 @@ public partial class {{= model.Name}} {
public __SEGMENTS__.ValueEntities<{{= attr.ReferenceType.ToDisplayString()}}.ReadOnly> {{= attr.Name}} => __SEGMENTS__.ValuesExtensions.AsModels<{{= attr.ReferenceType.ToDisplayString()}}.ReadOnly>({{= attr.FieldName}}.Get(this), Db);
{{elif attr.IsMarker}}
public bool Is{{= attr.ContextualName}} => {{= attr.FieldName}}.Contains(this);
{{elif attr.IsReference}}
public {{= attr.ReferenceType.ToDisplayString()}}Id {{= attr.ContextualName}} => {{= attr.ReferenceType.ToDisplayString()}}Id.From({{= attr.FieldName}}.Get(this));
{{else}}
public {{= attr.HighLevelType.ToDisplayString()}} {{= attr.ContextualName}} => {{= attr.FieldName}}.Get(this);
{{/if}}
Expand Down Expand Up @@ -297,11 +315,59 @@ public partial class {{= model.Name}} {
return model.Id;
}


public static implicit operator {{= model.Name}}Id({{= model.Name}}.ReadOnly? model) {
return {{= model.Name}}Id.From(model!.Value.Id);
}
}
}

/// <summary>
/// A value object representing the id of a {{= model.Name}} entity.
/// </summary>
public readonly partial struct {{= model.Name}}Id : IEquatable<{{= model.Name}}Id>, IEquatable<__ABSTRACTIONS__.EntityId>
{
public readonly EntityId Value;

public {{= model.Name}}Id(EntityId id) => Value = id;

/// <summary>
/// Constructs a new {{= model.Name}}Id from the given entity id.
/// </summary>
public static {{= model.Name}}Id From(__ABSTRACTIONS__.EntityId id) => new {{= model.Name}}Id(id);

/// <summary>
/// Constructs a new {{= model.Name}}Id from the given ulong.
/// </summary>
public static {{= model.Name}}Id From(ulong id) => new {{= model.Name}}Id(__ABSTRACTIONS__.EntityId.From(id));

public static implicit operator EntityId({{= model.Name}}Id id) => id.Value;
public static implicit operator {{= model.Name}}Id(EntityId id) => {{= model.Name}}Id.From(id);


public bool Equals({{= model.Name}}Id other)
{
if (other == null) return false;
return Value.Value == other.Value.Value;
}


public bool Equals(__ABSTRACTIONS__.EntityId other)
{
if (other == null) return false;
return Value.Value == other.Value;
}

public override string ToString()
{
return "{{= model.Name}}Id:" + Value.Value.ToString("x");
}

public static bool operator ==({{= model.Name}}Id left, {{= model.Name}}Id right) => left.Equals(right);

public static bool operator !=({{= model.Name}}Id left, {{= model.Name}}Id right) => !left.Equals(right);
}


public static class {{= model.Name}}Extensions {
public static __DI__.IServiceCollection Add{{= model.Name}}Model(this __DI__.IServiceCollection services) {
{{each attr in model.Attributes}}
Expand Down
4 changes: 2 additions & 2 deletions tests/NexusMods.MnemonicDB.Tests/DbTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -245,12 +245,12 @@ public async Task CanGetChildEntities()

var loadoutWritten = loadout.Remap(result);

loadoutWritten.Mods.Count().Should().Be(2);
loadoutWritten.Mods.Count.Should().Be(2);
loadoutWritten.Mods.Select(m => m.Name).Should().BeEquivalentTo(["Test Mod 1", "Test Mod 2"]);

var firstMod = loadoutWritten.Mods.First();
firstMod.Loadout.Id.InPartition(PartitionId.Entity).Should().BeTrue("LoadoutId should in the entity partition");
firstMod.LoadoutId.Should().Be(loadoutWritten.Id);
firstMod.LoadoutId.Should().BeEquivalentTo(loadoutWritten.LoadoutId);
firstMod.Db.Should().Be(newDb);
loadout.Name.Should().Be("Test Loadout");
firstMod.Loadout.Name.Should().Be("Test Loadout");
Expand Down

0 comments on commit 6e52241

Please sign in to comment.