diff --git a/src/JasperFx/Events/CodeGeneration/CreateDocumentMethodCollection.cs b/src/JasperFx/Events/CodeGeneration/CreateDocumentMethodCollection.cs
new file mode 100644
index 0000000..37fe696
--- /dev/null
+++ b/src/JasperFx/Events/CodeGeneration/CreateDocumentMethodCollection.cs
@@ -0,0 +1,35 @@
+namespace JasperFx.Events.CodeGeneration;
+
+///
+/// This would be a helper for the open ended EventProjection
+///
+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");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/JasperFx/Events/CodeGeneration/CreateMethodFrame.cs b/src/JasperFx/Events/CodeGeneration/CreateMethodFrame.cs
new file mode 100644
index 0000000..f4d0990
--- /dev/null
+++ b/src/JasperFx/Events/CodeGeneration/CreateMethodFrame.cs
@@ -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
+ TrySetArgument(parent.SpecificEvent);
+
+ // Replace any arguments to the specific T event type
+ TrySetArgument(parent.DataOnly);
+ }
+
+ public override IEnumerable 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});");
+ }
+}
diff --git a/src/JasperFx/Events/CodeGeneration/NewGeneratedProjection.cs b/src/JasperFx/Events/CodeGeneration/NewGeneratedProjection.cs
index 113243c..a81a39b 100644
--- a/src/JasperFx/Events/CodeGeneration/NewGeneratedProjection.cs
+++ b/src/JasperFx/Events/CodeGeneration/NewGeneratedProjection.cs
@@ -4,8 +4,45 @@
namespace JasperFx.Events.CodeGeneration;
-/*
+
+public interface IStore
+{
+ TOptions Options { get; }
+ GenerationRules GenerationRules { get; }
+ IEventGraph Events { get; }
+}
+
+public class GeneratedEventProjection : NewGeneratedProjection
+ where TStore : IStore
+{
+ 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 : ICodeFile
+ where TStore : IStore
{
private readonly Type _projectionType;
private bool _hasGenerated;
@@ -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().InitializeSynchronously(rules, store.Options.EventGraph, null);
+ this.As().InitializeSynchronously(rules, store.Events, null);
if (!needsSettersGenerated())
{
@@ -98,4 +135,3 @@ void generateIfNecessaryLocked()
}
-*/
\ No newline at end of file
diff --git a/src/JasperFx/Events/CodeGeneration/ProjectMethodCall.cs b/src/JasperFx/Events/CodeGeneration/ProjectMethodCall.cs
new file mode 100644
index 0000000..c7246d8
--- /dev/null
+++ b/src/JasperFx/Events/CodeGeneration/ProjectMethodCall.cs
@@ -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
+
+ TrySetArgument(parent.SpecificEvent);
+
+ // Replace any arguments to the specific T event type
+ TrySetArgument(parent.DataOnly);
+ }
+}
diff --git a/src/JasperFx/Events/CodeGeneration/ProjectMethodCollection.cs b/src/JasperFx/Events/CodeGeneration/ProjectMethodCollection.cs
new file mode 100644
index 0000000..9b2e65b
--- /dev/null
+++ b/src/JasperFx/Events/CodeGeneration/ProjectMethodCollection.cs
@@ -0,0 +1,36 @@
+using JasperFx.Core.Reflection;
+
+namespace JasperFx.Events.CodeGeneration;
+
+///
+/// This would be a helper for the open ended EventProjection
+///
+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);
+ }
+}
diff --git a/src/JasperFx/Events/IEventGraph.cs b/src/JasperFx/Events/IEventGraph.cs
index 7c03ae5..6843205 100644
--- a/src/JasperFx/Events/IEventGraph.cs
+++ b/src/JasperFx/Events/IEventGraph.cs
@@ -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; }