diff --git a/Source/Projections/Builder/KeySelectorBuilder.cs b/Source/Projections/Builder/KeySelectorBuilder.cs
index 1d82c3f6..a9f9e46d 100644
--- a/Source/Projections/Builder/KeySelectorBuilder.cs
+++ b/Source/Projections/Builder/KeySelectorBuilder.cs
@@ -14,13 +14,13 @@ public class KeySelectorBuilder
/// Select projection key from the .
///
/// A .
- public static KeySelector KeyFromEventSource() => KeySelector.EventSource;
+ public static KeySelector KeyFromEventSource => KeySelector.EventSource;
///
/// Select projection key from the .
///
/// A .
- public static KeySelector KeyFromPartitionId() => KeySelector.Partition;
+ public static KeySelector KeyFromPartitionId => KeySelector.Partition;
///
/// Select projection key from a property of the event.
@@ -46,4 +46,21 @@ public static KeySelector StaticKey(Key staticKey)
/// A .
public static KeySelector KeyFromEventOccurred(OccurredFormat occurredFormat)
=> KeySelector.Occurred(occurredFormat);
+
+ ///
+ /// Select projection key from a property of the event.
+ ///
+ /// The property on the event.
+ /// The date time format.
+ /// A .
+ public static KeySelector KeyFromPropertyAndEventOccurred(KeySelectorExpression selectorExpression, OccurredFormat occurredFormat)
+ => KeySelector.PropertyAndOccured(selectorExpression, occurredFormat);
+
+ ///
+ /// Select projection key from when an event occurred.
+ ///
+ /// The date time format.
+ /// A .
+ public static KeySelector KeyFromEventSourceIdAndOccurred(OccurredFormat occurredFormat)
+ => KeySelector.EventSourceAndOccured(occurredFormat);
}
diff --git a/Source/Projections/Builder/KeySelectorBuilder{TEvent}.cs b/Source/Projections/Builder/KeySelectorBuilder{TEvent}.cs
index 0d477c34..1c95ff28 100644
--- a/Source/Projections/Builder/KeySelectorBuilder{TEvent}.cs
+++ b/Source/Projections/Builder/KeySelectorBuilder{TEvent}.cs
@@ -3,6 +3,7 @@
using System;
using System.Linq.Expressions;
+using Dolittle.SDK.Events;
namespace Dolittle.SDK.Projections.Builder;
@@ -29,4 +30,18 @@ public KeySelector KeyFromProperty(Expression
throw new KeySelectorExpressionWasNotAMemberExpression();
}
+
+ ///
+ /// Select projection key from a property of the event.
+ ///
+ /// The property type.
+ /// The function for getting the projection key (id).
+ /// A .
+ /// Is thrown when the provided property expression is not a member expression.
+ public KeySelector KeyFromFunction(Func function)
+ {
+ if (function is null) throw new ArgumentNullException(nameof(function));
+
+ return KeySelector.ByFunction(function);
+ }
}
diff --git a/Source/Projections/IKeySelector.cs b/Source/Projections/IKeySelector.cs
new file mode 100644
index 00000000..eb541efe
--- /dev/null
+++ b/Source/Projections/IKeySelector.cs
@@ -0,0 +1,22 @@
+// Copyright (c) Dolittle. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using Dolittle.SDK.Events;
+
+namespace Dolittle.SDK.Projections;
+
+///
+/// Use this interface to define projection key selectors.
+/// Instances of this interface MUST be thread safe and stateless, as they are used as singletons.
+///
+/// The mapped event type
+public interface IKeySelector where TEvent : class
+{
+ ///
+ /// Map to a from an event and context.
+ ///
+ ///
+ ///
+ /// The projection key
+ Key Selector(TEvent @event, EventContext eventContext);
+}
diff --git a/Source/Projections/Internal/ProjectionsProcessor.cs b/Source/Projections/Internal/ProjectionsProcessor.cs
index f918eba9..29649ccc 100644
--- a/Source/Projections/Internal/ProjectionsProcessor.cs
+++ b/Source/Projections/Internal/ProjectionsProcessor.cs
@@ -103,28 +103,4 @@ protected override RetryProcessingState GetRetryProcessingStateFromRequest(Handl
///
protected override EventHandlerResponse CreateResponseFromFailure(ProcessorFailure failure)
=> new() { Failure = failure };
-
- static ProjectionEventSelector CreateProjectionEventSelector(EventSelector eventSelector)
- {
- static ProjectionEventSelector WithEventType(EventSelector eventSelector, Action callback)
- {
- var message = new ProjectionEventSelector();
- callback(message);
- message.EventType = eventSelector.EventType.ToProtobuf();
- return message;
- }
-
- return eventSelector.KeySelector.Type switch
- {
- KeySelectorType.EventSourceId => WithEventType(eventSelector, _ => _.EventSourceKeySelector = new EventSourceIdKeySelector()),
- KeySelectorType.PartitionId => WithEventType(eventSelector, _ => _.PartitionKeySelector = new PartitionIdKeySelector()),
- KeySelectorType.Property => WithEventType(eventSelector,
- _ => _.EventPropertyKeySelector = new EventPropertyKeySelector { PropertyName = eventSelector.KeySelector.Expression ?? string.Empty }),
- KeySelectorType.Static => WithEventType(eventSelector,
- _ => _.StaticKeySelector = new StaticKeySelector { StaticKey = eventSelector.KeySelector.StaticKey ?? string.Empty }),
- KeySelectorType.EventOccurred => WithEventType(eventSelector,
- _ => _.EventOccurredKeySelector = new EventOccurredKeySelector { Format = eventSelector.KeySelector.OccurredFormat ?? string.Empty }),
- _ => throw new UnknownKeySelectorType(eventSelector.KeySelector.Type)
- };
- }
}
diff --git a/Source/Projections/KeyFromEventOccurredAttribute.cs b/Source/Projections/KeyFromEventOccurredAttribute.cs
index d8040033..5ef71c99 100644
--- a/Source/Projections/KeyFromEventOccurredAttribute.cs
+++ b/Source/Projections/KeyFromEventOccurredAttribute.cs
@@ -2,7 +2,6 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
-using Dolittle.SDK.Projections.Builder;
namespace Dolittle.SDK.Projections;
@@ -15,7 +14,7 @@ public class KeyFromEventOccurredAttribute : Attribute, IKeySelectorAttribute
///
/// Initializes a new instance of the class.
///
- /// The name of the property.
+ /// The date time format.
public KeyFromEventOccurredAttribute(string occurredFormat) => OccurredFormat = occurredFormat;
///
@@ -24,5 +23,5 @@ public class KeyFromEventOccurredAttribute : Attribute, IKeySelectorAttribute
public OccurredFormat OccurredFormat { get; }
///
- public KeySelector KeySelector => KeySelectorBuilder.KeyFromEventOccurred(OccurredFormat);
+ public KeySelector KeySelector => KeySelector.Occurred(OccurredFormat);
}
diff --git a/Source/Projections/KeyFromEventSourceAndOccurredAttribute.cs b/Source/Projections/KeyFromEventSourceAndOccurredAttribute.cs
new file mode 100644
index 00000000..66bef526
--- /dev/null
+++ b/Source/Projections/KeyFromEventSourceAndOccurredAttribute.cs
@@ -0,0 +1,31 @@
+// Copyright (c) Dolittle. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+
+namespace Dolittle.SDK.Projections;
+
+///
+/// Decorates a projection method with the .
+///
+[AttributeUsage(AttributeTargets.Method)]
+public class KeyFromEventSourceAndOccurredAttribute : Attribute, IKeySelectorAttribute
+{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The name of the property.
+ /// The date time format.
+ public KeyFromEventSourceAndOccurredAttribute(string occurredFormat)
+ {
+ OccurredFormat = occurredFormat;
+ }
+
+ ///
+ /// Gets the .
+ ///
+ public OccurredFormat OccurredFormat { get; }
+
+ ///
+ public KeySelector KeySelector => KeySelector.EventSourceAndOccured(OccurredFormat);
+}
diff --git a/Source/Projections/KeyFromEventSourceAttribute.cs b/Source/Projections/KeyFromEventSourceAttribute.cs
index d281a591..b5ba216b 100644
--- a/Source/Projections/KeyFromEventSourceAttribute.cs
+++ b/Source/Projections/KeyFromEventSourceAttribute.cs
@@ -2,7 +2,6 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
-using Dolittle.SDK.Projections.Builder;
namespace Dolittle.SDK.Projections;
@@ -13,5 +12,5 @@ namespace Dolittle.SDK.Projections;
public class KeyFromEventSourceAttribute : Attribute, IKeySelectorAttribute
{
///
- public KeySelector KeySelector { get; } = KeySelectorBuilder.KeyFromEventSource();
-}
\ No newline at end of file
+ public KeySelector KeySelector => KeySelector.EventSource;
+}
diff --git a/Source/Projections/KeyFromFunctionAttribute.cs b/Source/Projections/KeyFromFunctionAttribute.cs
new file mode 100644
index 00000000..07062c5c
--- /dev/null
+++ b/Source/Projections/KeyFromFunctionAttribute.cs
@@ -0,0 +1,23 @@
+// Copyright (c) Dolittle. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+
+namespace Dolittle.SDK.Projections;
+
+static class KeySelectorInstance where TKeySelector : IKeySelector, new() where TEvent : class
+{
+ public static TKeySelector Mapper { get; } = new();
+ public static KeySelector Instance { get; } = KeySelector.ByFunction(Mapper.Selector);
+}
+
+///
+/// Decorates a projection method with the .
+///
+[AttributeUsage(AttributeTargets.Method)]
+public class KeyFromFunctionAttribute : Attribute, IKeySelectorAttribute
+ where TKeySelector : IKeySelector, new() where TEvent : class
+{
+ ///
+ public KeySelector KeySelector => KeySelectorInstance.Instance;
+}
diff --git a/Source/Projections/KeyFromPartitionAttribute.cs b/Source/Projections/KeyFromPartitionAttribute.cs
index 8f98fe85..b33ed1cb 100644
--- a/Source/Projections/KeyFromPartitionAttribute.cs
+++ b/Source/Projections/KeyFromPartitionAttribute.cs
@@ -2,7 +2,6 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
-using Dolittle.SDK.Projections.Builder;
namespace Dolittle.SDK.Projections;
@@ -13,5 +12,5 @@ namespace Dolittle.SDK.Projections;
public class KeyFromPartitionAttribute : Attribute, IKeySelectorAttribute
{
///
- public KeySelector KeySelector { get; } = KeySelectorBuilder.KeyFromPartitionId();
-}
\ No newline at end of file
+ public KeySelector KeySelector => KeySelector.Partition;
+}
diff --git a/Source/Projections/KeyFromPropertyAndOccurredAttribute.cs b/Source/Projections/KeyFromPropertyAndOccurredAttribute.cs
new file mode 100644
index 00000000..1b01fc79
--- /dev/null
+++ b/Source/Projections/KeyFromPropertyAndOccurredAttribute.cs
@@ -0,0 +1,37 @@
+// Copyright (c) Dolittle. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+
+namespace Dolittle.SDK.Projections;
+
+///
+/// Decorates a projection method with the .
+///
+[AttributeUsage(AttributeTargets.Method)]
+public class KeyFromPropertyAndOccurredAttribute : Attribute, IKeySelectorAttribute
+{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The name of the property.
+ /// The date time format.
+ public KeyFromPropertyAndOccurredAttribute(string propertyName, string occurredFormat)
+ {
+ Expression = propertyName;
+ OccurredFormat = occurredFormat;
+ }
+
+ ///
+ /// Gets the .
+ ///
+ public KeySelectorExpression Expression { get; }
+
+ ///
+ /// Gets the .
+ ///
+ public OccurredFormat OccurredFormat { get; }
+
+ ///
+ public KeySelector KeySelector => KeySelector.PropertyAndOccured(Expression, OccurredFormat);
+}
diff --git a/Source/Projections/KeyFromPropertyAttribute.cs b/Source/Projections/KeyFromPropertyAttribute.cs
index 16905e67..c7635a99 100644
--- a/Source/Projections/KeyFromPropertyAttribute.cs
+++ b/Source/Projections/KeyFromPropertyAttribute.cs
@@ -2,7 +2,6 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
-using Dolittle.SDK.Projections.Builder;
namespace Dolittle.SDK.Projections;
@@ -24,5 +23,5 @@ public class KeyFromPropertyAttribute : Attribute, IKeySelectorAttribute
public KeySelectorExpression Expression { get; }
///
- public KeySelector KeySelector => KeySelectorBuilder.KeyFromProperty(Expression);
+ public KeySelector KeySelector => KeySelector.Property(Expression);
}
diff --git a/Source/Projections/KeySelector.cs b/Source/Projections/KeySelector.cs
index 43c4191c..47a3717d 100644
--- a/Source/Projections/KeySelector.cs
+++ b/Source/Projections/KeySelector.cs
@@ -12,46 +12,71 @@ namespace Dolittle.SDK.Projections;
///
public class KeySelector
{
- KeySelector(KeySelectorType type, KeySelectorExpression expression, Key staticKey, OccurredFormat occurredFormat)
+ KeySelector(KeySelectorType type, KeySelectorExpression expression, Key staticKey, OccurredFormat occurredFormat, Func