RSCG – corecraft

RSCG – corecraft
 
 

name corecraft
nuget https://www.nuget.org/packages/corecraft/
link https://github.com/AlexNav73/CoreCraft
author

Decomposing properties and class into Domain Models. Seems however too complicated to use

 

This is how you can use corecraft .

The code that you start with is


<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
	<PropertyGroup>
		<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
		<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
	</PropertyGroup>
	<ItemGroup>
	  <None Remove="Person.model.json" />
	</ItemGroup>
	<ItemGroup>
	  <AdditionalFiles Include="Person.model.json">
	    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
	  </AdditionalFiles>
	</ItemGroup>
	<ItemGroup>
	  <PackageReference Include="CoreCraft" Version="0.6.0" />
	  <PackageReference Include="CoreCraft.Generators" Version="0.6.0">
	    <PrivateAssets>all</PrivateAssets>
	    <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
	  </PackageReference>
	</ItemGroup>
</Project>


The code that you will use is


<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
	<PropertyGroup>
		<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
		<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
	</PropertyGroup>
	<ItemGroup>
	  <None Remove="Person.model.json" />
	</ItemGroup>
	<ItemGroup>
	  <AdditionalFiles Include="Person.model.json">
	    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
	  </AdditionalFiles>
	</ItemGroup>
	<ItemGroup>
	  <PackageReference Include="CoreCraft" Version="0.6.0" />
	  <PackageReference Include="CoreCraft.Generators" Version="0.6.0">
	    <PrivateAssets>all</PrivateAssets>
	    <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
	  </PackageReference>
	</ItemGroup>
</Project>



using CoreCraft;
using CoreCraft.ChangesTracking;
using CoreCraft.Subscription;
using Json2Code.Person;
using Json2Code.Person.Entities;
var model = new DomainModel(new[] { new Json2Code.Person.PersonShardModelShard() });

// Subscribe to Items collection change events 
using var subscription = model.For<IPersonShardChangesFrame>()
    .With(x => x.Persons)
    .Subscribe(OnItemChanged);

// Observe changes
void OnItemChanged(Change<ICollectionChangeSet<Person, PersonProperties>> changes)
{
    foreach (var c in changes.Hunk)
    {
        Console.WriteLine($"Entity [{c.Entity}] has been {c.Action}ed.");
        Console.WriteLine($"   Old data: {c.OldData}");
        Console.WriteLine($"   New data: {c.NewData}");
    }
}


await model.Run<IMutablePersonShardModelShard> (
    (shard, _) =>
    {
        shard.Persons.Add(new() { FirstName = "A", LastName = "B" });
        //shard.Persons.Remove(shard.Persons.First());
    });
await model.Run<IMutablePersonShardModelShard>(
    (shard, _) =>
    {        
        shard.Persons.Modify(shard.Persons.First(), p => p with { FirstName = "C" });
    });

await model.Run<IMutablePersonShardModelShard>(
    (shard, _) =>
    {
        shard.Persons.Remove(shard.Persons.First());
    });



Console.WriteLine("Press any key to exit...");
Console.ReadKey();



{
  "shards": [
    {
      "name": "PersonShard",
      "entities": [
        {
          "name": "Person",
          "properties": [
            {
              "name": "FirstName",
              "type": "string",
              "defaultValue": "\"Andrei\""
            },
            {
              "name": "LastName",
              "type": "string",
              "defaultValue": "\"Ignat\""
            }
          ]
        }
      ],
      "collections": [
        {
          "name": "Persons",
          "entityType": "Person"
        }
      ],
      "relations": []
    }
  ]
}

 

The code that is generated is


//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by the tool.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

#nullable enable

namespace Json2Code.Person
{
    using CoreCraft.Core;
    using CoreCraft.ChangesTracking;
    using CoreCraft.Persistence;
    using Json2Code.Person.Entities;

    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("C# Source Generator", "1.0.0.0")]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    public interface IPersonShardModelShard : IModelShard
    {
        ICollection<Person, PersonProperties> Persons { get; }

    }

    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("C# Source Generator", "1.0.0.0")]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    public interface IMutablePersonShardModelShard : IModelShard
    {
        IMutableCollection<Person, PersonProperties> Persons { get; }

    }

    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("C# Source Generator", "1.0.0.0")]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute()]
    internal static class PersonShardModelShardInfo
    {
        public static readonly CollectionInfo PersonsInfo = new("PersonShard", "Persons", new PropertyInfo[] { new("FirstName", typeof(string), false), new("LastName", typeof(string), false) });

    }

    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("C# Source Generator", "1.0.0.0")]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute()]
    internal sealed partial class PersonShardModelShard : IPersonShardModelShard
    {
        public const string PersonsId = "Json2Code.Person.PersonShard.Persons";

        public PersonShardModelShard()
        {
            Persons = new Collection<Person, PersonProperties>(
                PersonsId,
                static id => new Person(id),
                static () => new PersonProperties());

        }

        internal PersonShardModelShard(IMutablePersonShardModelShard mutable)
        {
            Persons = ((IMutableState<ICollection<Person, PersonProperties>>)mutable.Persons).AsReadOnly();

        }

        public ICollection<Person, PersonProperties> Persons { get; init; } = null!;

    }

    internal sealed partial class PersonShardModelShard : IReadOnlyState<IMutablePersonShardModelShard>
    {
        public IMutablePersonShardModelShard AsMutable(global::System.Collections.Generic.IEnumerable<IFeature> features)
        {
            var persons = (IMutableCollection<Person, PersonProperties>)Persons;


            foreach (var feature in features)
            {
                persons = feature.Decorate(this, persons);

            }

            return new MutablePersonShardModelShard()
            {
                Persons = persons,

            };
        }
    }

    internal sealed partial class PersonShardModelShard : ICanBeSaved
    {
        public void Save(IRepository repository)
        {
            repository.Save(PersonShardModelShardInfo.PersonsInfo, Persons);

        }
    }

    internal sealed partial class PersonShardModelShard : IFeatureContext
    {
        IChangesFrame IFeatureContext.GetOrAddFrame(IMutableModelChanges modelChanges)
        {
            return modelChanges.Register(static () => new PersonShardChangesFrame());
        }
    }

    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("C# Source Generator", "1.0.0.0")]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    public interface IPersonShardChangesFrame : IChangesFrame
    {
        ICollectionChangeSet<Person, PersonProperties> Persons { get; }

    }

    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("C# Source Generator", "1.0.0.0")]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute()]
    internal sealed class PersonShardChangesFrame : IPersonShardChangesFrame, IChangesFrameEx, ICanBeSaved
    {
        public PersonShardChangesFrame()
        {
            Persons = new CollectionChangeSet<Person, PersonProperties>(PersonShardModelShard.PersonsId);

        }

        public ICollectionChangeSet<Person, PersonProperties> Persons { get; private set; }


        ICollectionChangeSet<TEntity, TProperty>? IChangesFrame.Get<TEntity, TProperty>(ICollection<TEntity, TProperty> collection)
        {
            if (Persons.Id == collection.Id) return Persons as ICollectionChangeSet<TEntity, TProperty>;

            throw new System.InvalidOperationException("Unable to find collection's changes set");
        }

        IRelationChangeSet<TParent, TChild>? IChangesFrame.Get<TParent, TChild>(IRelation<TParent, TChild> relation)
        {

            throw new System.InvalidOperationException($"Unable to find relation's change set");
        }

        IChangesFrame IChangesFrame.Invert()
        {
            return new PersonShardChangesFrame()
            {
                Persons = Persons.Invert(),

            };
        }

        public void Apply(IModel model)
        {
            var modelShard = model.Shard<IMutablePersonShardModelShard>();

            Persons.Apply(modelShard.Persons);
        }

        public bool HasChanges()
        {
            return Persons.HasChanges();
        }

        public IChangesFrame Merge(IChangesFrame frame)
        {
            var typedFrame = (PersonShardChangesFrame)frame;

            return new PersonShardChangesFrame()
            {
                Persons = Persons.Merge(typedFrame.Persons),

            };
        }

        public void Save(IRepository repository)
        {
            repository.Save(PersonShardModelShardInfo.PersonsInfo, Persons);

        }

    }

    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("C# Source Generator", "1.0.0.0")]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute()]
    internal sealed class MutablePersonShardModelShard : IMutablePersonShardModelShard, IMutableState<IPersonShardModelShard>, ICanBeLoaded
    {
        public IMutableCollection<Person, PersonProperties> Persons { get; init; } = null!;


        public IPersonShardModelShard AsReadOnly()
        {
            return new PersonShardModelShard(this);
        }

        public void Load(IRepository repository)
        {
            repository.Load(PersonShardModelShardInfo.PersonsInfo, Persons);

        }
    }

}

namespace Json2Code.Person.Entities
{
    using CoreCraft.Core;

    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("C# Source Generator", "1.0.0.0")]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute()]
    public sealed record Person(global::System.Guid Id) : Entity(Id)
    {
        internal Person() : this(global::System.Guid.NewGuid())
        {
        }
    }

    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("C# Source Generator", "1.0.0.0")]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute()]
    public sealed partial record PersonProperties : Properties
    {
        public PersonProperties()
        {
            FirstName = "Andrei";
            LastName = "Ignat";
        }

        public string FirstName { get; init; }
        public string LastName { get; init; }

#if NET5_0_OR_GREATER
        public override PersonProperties ReadFrom(IPropertiesBag bag)
#else
        public override Properties ReadFrom(IPropertiesBag bag)
#endif
        {
            return new PersonProperties()
            {
                FirstName = bag.Read<string>("FirstName"),
                LastName = bag.Read<string>("LastName"),
            };
        }

        public override void WriteTo(IPropertiesBag bag)
        {
            bag.Write("FirstName", FirstName);
            bag.Write("LastName", LastName);
        }

    }


}

Code and pdf at

https://ignatandrei.github.io/RSCG_Examples/v2/docs/corecraft