33using System ;
44using System . Collections . Concurrent ;
55using System . Collections . Generic ;
6- using System . Collections . ObjectModel ;
76using System . Linq ;
87using System . Linq . Expressions ;
98using System . Reflection ;
1211
1312class SagaMapper
1413{
15- static readonly ConcurrentDictionary < Type , SagaMapper > sagaMappers = new ConcurrentDictionary < Type , SagaMapper > ( ) ;
14+ static readonly ConcurrentDictionary < Type , SagaMapper > sagaMappers = new ( ) ;
1615
1716 readonly SagaMetadata metadata ;
18- readonly IReadOnlyDictionary < Type , Func < QueuedSagaMessage , object > > mappings ;
17+ readonly IReadOnlyDictionary < Type , SagaMapping > mappings ;
1918 readonly SagaMetadata . CorrelationPropertyMetadata correlationProperty ;
2019 readonly PropertyInfo correlationPropertyInfo ;
2120 readonly ConcurrentDictionary < ( Type messageType , string methodName ) , MethodInfo > handlerMethods ;
@@ -65,50 +64,55 @@ public SagaMessage GetMessageMetadata(Type messageType)
6564
6665 public object GetMessageMappedValue ( QueuedSagaMessage message )
6766 {
68- if ( mappings . TryGetValue ( message . Type , out var mapping ) )
67+ if ( ! mappings . TryGetValue ( message . Type , out var mapping ) )
6968 {
70- return mapping ( message ) ;
69+ throw new Exception ( "No mapped value found from message, could not look up saga data." ) ;
7170 }
7271
73- throw new Exception ( "No mapped value found from message, could not look up saga data." ) ;
72+ return mapping . IsCustomFinder ? throw new NotSupportedException ( "Testing saga invocations with a custom saga finder is currently not supported" ) : mapping . Map ( message ) ;
7473 }
7574
76- public void SetCorrelationPropertyValue ( IContainSagaData sagaEntity , object value )
77- => correlationPropertyInfo . SetValue ( sagaEntity , value ) ;
75+ public void SetCorrelationPropertyValue ( IContainSagaData sagaEntity , object value ) => correlationPropertyInfo . SetValue ( sagaEntity , value ) ;
7876
7977 public Task InvokeHandlerMethod < TSaga > ( TSaga saga , string methodName , QueuedSagaMessage message , TestableMessageHandlerContext context )
8078 {
8179 var key = ( message . Type , methodName ) ;
8280 var handlerMethodInfo = handlerMethods . GetOrAdd ( key , newKey =>
8381 {
84- var handlerTypes = new Type [ ] { newKey . messageType , typeof ( IMessageHandlerContext ) } ;
82+ var handlerTypes = new [ ] { newKey . messageType , typeof ( IMessageHandlerContext ) } ;
8583 return typeof ( TSaga ) . GetMethod ( newKey . methodName , BindingFlags . NonPublic | BindingFlags . Public | BindingFlags . Instance , null , handlerTypes , null ) ;
8684 } ) ;
8785
8886 var invokeTask = handlerMethodInfo . Invoke ( saga , [ message . Message , context ] ) as Task ;
8987 return invokeTask ;
9088 }
9189
92- class MappingReader : IConfigureHowToFindSagaWithMessage , IConfigureHowToFindSagaWithMessageHeaders
90+ class MappingReader : IConfigureHowToFindSagaWithMessage , IConfigureHowToFindSagaWithMessageHeaders , IConfigureHowToFindSagaWithFinder , IConfigureSagaNotFoundHandler
9391 {
94- readonly Dictionary < Type , Func < QueuedSagaMessage , object > > mappings = [ ] ;
92+ readonly Dictionary < Type , SagaMapping > mappings = [ ] ;
9593
9694 void IConfigureHowToFindSagaWithMessage . ConfigureMapping < TSagaEntity , TMessage > ( Expression < Func < TSagaEntity , object > > sagaEntityProperty , Expression < Func < TMessage , object > > messageProperty )
9795 {
9896 Func < TMessage , object > compiledExpression = messageProperty . Compile ( ) ;
9997 object GetValueFromMessage ( QueuedSagaMessage message ) => compiledExpression ( ( TMessage ) message . Message ) ;
100- mappings . Add ( typeof ( TMessage ) , GetValueFromMessage ) ;
98+ mappings . Add ( typeof ( TMessage ) , new SagaMapping ( GetValueFromMessage , false ) ) ;
10199 }
102100
103101 void IConfigureHowToFindSagaWithMessageHeaders . ConfigureMapping < TSagaEntity , TMessage > ( Expression < Func < TSagaEntity , object > > sagaEntityProperty , string headerName )
104102 {
105- object GetValueFromMessage ( QueuedSagaMessage message )
106- => message . Headers . GetValueOrDefault ( headerName ) ;
103+ object GetValueFromMessage ( QueuedSagaMessage message ) => message . Headers . GetValueOrDefault ( headerName ) ;
104+ mappings . Add ( typeof ( TMessage ) , new SagaMapping ( GetValueFromMessage , false ) ) ;
105+ }
106+
107+ void IConfigureHowToFindSagaWithFinder . ConfigureMapping < TSagaEntity , TMessage , TFinder > ( ) => mappings . Add ( typeof ( TMessage ) , new SagaMapping ( null , true ) ) ;
107108
108- mappings . Add ( typeof ( TMessage ) , GetValueFromMessage ) ;
109+ public void ConfigureSagaNotFoundHandler < TNotFoundHandler > ( ) where TNotFoundHandler : ISagaNotFoundHandler
110+ {
111+ // Do nothing, framework doesn't explicitly test not found handlers
109112 }
110113
111- public IReadOnlyDictionary < Type , Func < QueuedSagaMessage , object > > GetMappings ( ) =>
112- new ReadOnlyDictionary < Type , Func < QueuedSagaMessage , object > > ( mappings ) ;
114+ public IReadOnlyDictionary < Type , SagaMapping > GetMappings ( ) => mappings . AsReadOnly ( ) ;
113115 }
116+
117+ record SagaMapping ( Func < QueuedSagaMessage , object > Map , bool IsCustomFinder ) ;
114118}
0 commit comments