Skip to content

Commit

Permalink
New EventProjection code generation
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremydmiller committed Nov 16, 2024
1 parent c3caa32 commit d9c93a3
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
namespace JasperFx.Events.CodeGeneration;

/// <summary>
/// This would be a helper for the open ended EventProjection
/// </summary>
public class CreateDocumentMethodCollection: MethodCollection
{
private readonly Type _operationsType;
public static readonly string MethodName = "Create";
public static readonly string TransformMethodName = "Transform";



public CreateDocumentMethodCollection(Type projectionType, Type operationsType): base(new[] { MethodName, TransformMethodName },
projectionType, null)
{
_operationsType = operationsType;
_validArgumentTypes.Add(operationsType);
}

public override IEventHandlingFrame CreateEventTypeHandler(Type aggregateType,
IStorageMapping aggregateMapping,
MethodSlot slot)
{
return new CreateMethodFrame(_operationsType, slot);
}

protected override void validateMethod(MethodSlot method)
{
if (method.ReturnType == typeof(void))
{
method.AddError("The return value must be a new document");
}
}
}
45 changes: 45 additions & 0 deletions src/JasperFx/Events/CodeGeneration/CreateMethodFrame.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System.Reflection;
using JasperFx.CodeGeneration;
using JasperFx.CodeGeneration.Frames;
using JasperFx.CodeGeneration.Model;

namespace JasperFx.Events.CodeGeneration;

internal class CreateMethodFrame: MethodCall, IEventHandlingFrame
{
private readonly Type _operationsType;
private static int _counter;

private Variable _operations;

public CreateMethodFrame(Type operationsType, MethodSlot slot): base(slot.HandlerType, (MethodInfo)slot.Method)
{
_operationsType = operationsType;
EventType = Method.GetEventType(null);
ReturnVariable.OverrideName(ReturnVariable.Usage + ++_counter);
}

public Type EventType { get; }

public void Configure(EventProcessingFrame parent)
{
// Replace any arguments to IEvent<T>
TrySetArgument(parent.SpecificEvent);

// Replace any arguments to the specific T event type
TrySetArgument(parent.DataOnly);
}

public override IEnumerable<Variable> FindVariables(IMethodVariables chain)
{
foreach (var variable in base.FindVariables(chain)) yield return variable;

_operations = chain.FindVariable(_operationsType);
}

public override void GenerateCode(GeneratedMethod method, ISourceWriter writer)
{
base.GenerateCode(method, writer);
writer.WriteLine($"{_operations.Usage}.Store({ReturnVariable.Usage});");
}
}
44 changes: 40 additions & 4 deletions src/JasperFx/Events/CodeGeneration/NewGeneratedProjection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,45 @@

namespace JasperFx.Events.CodeGeneration;

/*

public interface IStore<TOptions>
{
TOptions Options { get; }
GenerationRules GenerationRules { get; }
IEventGraph Events { get; }
}

public class GeneratedEventProjection<TOperations, TStore, TDatabase, TOptions> : NewGeneratedProjection<TOperations, TStore,
TDatabase, TOptions>
where TStore : IStore<TOptions>
{
private readonly ProjectMethodCollection _projectMethods;
private readonly CreateDocumentMethodCollection _createMethods;

public GeneratedEventProjection(Type projectionType) : base(projectionType)
{
_projectMethods = new ProjectMethodCollection(projectionType, typeof(TOperations));
_createMethods = new CreateDocumentMethodCollection(projectionType, typeof(TOperations));
}

protected override void assembleTypes(GeneratedAssembly assembly, TOptions options)
{
throw new NotImplementedException();
}

protected override bool tryAttachTypes(Assembly assembly, TOptions options)
{
throw new NotImplementedException();
}

protected override bool needsSettersGenerated()
{
throw new NotImplementedException();
}
}

public abstract class NewGeneratedProjection<TOperations, TStore, TDatabase, TOptions> : ICodeFile
where TStore : IStore<TOptions>
{
private readonly Type _projectionType;
private bool _hasGenerated;
Expand Down Expand Up @@ -71,9 +108,9 @@ private void generateIfNecessary(TStore store)
void generateIfNecessaryLocked()
{
StoreOptions = store.Options;
var rules = store.Options.CreateGenerationRules();
var rules = store.GenerationRules;
rules.ReferenceTypes(GetType());
this.As<ICodeFile>().InitializeSynchronously(rules, store.Options.EventGraph, null);
this.As<ICodeFile>().InitializeSynchronously(rules, store.Events, null);

if (!needsSettersGenerated())
{
Expand All @@ -98,4 +135,3 @@ void generateIfNecessaryLocked()


}
*/
25 changes: 25 additions & 0 deletions src/JasperFx/Events/CodeGeneration/ProjectMethodCall.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System.Reflection;
using JasperFx.CodeGeneration.Frames;

namespace JasperFx.Events.CodeGeneration;

internal class ProjectMethodCall: MethodCall, IEventHandlingFrame
{
public ProjectMethodCall(MethodSlot slot): base(slot.HandlerType, (MethodInfo)slot.Method)
{
EventType = Method.GetEventType(null);
Target = slot.Setter;
}

public Type EventType { get; }

public void Configure(EventProcessingFrame parent)
{
// Replace any arguments to IEvent<T>

TrySetArgument(parent.SpecificEvent);

// Replace any arguments to the specific T event type
TrySetArgument(parent.DataOnly);
}
}
36 changes: 36 additions & 0 deletions src/JasperFx/Events/CodeGeneration/ProjectMethodCollection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using JasperFx.Core.Reflection;

namespace JasperFx.Events.CodeGeneration;

/// <summary>
/// This would be a helper for the open ended EventProjection
/// </summary>
public class ProjectMethodCollection: MethodCollection
{
private readonly Type _operationsType;
public static readonly string MethodName = "Project";


public ProjectMethodCollection(Type projectionType, Type operationsType): base(MethodName, projectionType, null)
{
_operationsType = operationsType;
_validArgumentTypes.Add(operationsType);
_validReturnTypes.Add(typeof(void));
_validReturnTypes.Add(typeof(Task));
}

protected override void validateMethod(MethodSlot method)
{
if (method.Method.GetParameters().All(x => x.ParameterType != _operationsType))
{
method.AddError($"{_operationsType.FullNameInCode()} is a required parameter");
}
}

public override IEventHandlingFrame CreateEventTypeHandler(Type aggregateType,
IStorageMapping aggregateMapping,
MethodSlot slot)
{
return new ProjectMethodCall(slot);
}
}
4 changes: 3 additions & 1 deletion src/JasperFx/Events/IEventGraph.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#nullable enable
using JasperFx.CodeGeneration;

namespace JasperFx.Events;

public interface IEventGraph
public interface IEventGraph : ICodeFileCollection
{
IEvent BuildEvent(object eventData);
EventAppendMode AppendMode { get; set; }
Expand Down

0 comments on commit d9c93a3

Please sign in to comment.