@@ -1149,11 +1149,21 @@ pub fn autogen_csharp_reducer(ctx: &GenCtx, reducer: &ReducerDef, namespace: &st
11491149 write ! ( arg_types, "{}" , arg_type_str) . unwrap ( ) ;
11501150 }
11511151
1152+ let delegate_args = if !reducer. args . is_empty ( ) {
1153+ format ! ( ", {}" , func_arguments. clone( ) )
1154+ } else {
1155+ func_arguments. clone ( )
1156+ } ;
11521157 writeln ! (
11531158 output,
1154- "public static event Action<ClientApi.Event.Types.Status, Identity{arg_types}> On{func_name_pascal_case}Event ;"
1159+ "public delegate void {func_name_pascal_case}Handler(ReducerEvent reducerEvent{delegate_args}) ;"
11551160 )
1156- . unwrap ( ) ;
1161+ . unwrap ( ) ;
1162+ writeln ! (
1163+ output,
1164+ "public static event {func_name_pascal_case}Handler On{func_name_pascal_case}Event;"
1165+ )
1166+ . unwrap ( ) ;
11571167
11581168 writeln ! ( output) . unwrap ( ) ;
11591169
@@ -1208,7 +1218,7 @@ pub fn autogen_csharp_reducer(ctx: &GenCtx, reducer: &ReducerDef, namespace: &st
12081218 writeln ! ( output, "[ReducerCallback(FunctionName = \" {func_name}\" )]" ) . unwrap ( ) ;
12091219 writeln ! (
12101220 output,
1211- "public static void On{func_name_pascal_case}(ClientApi.Event dbEvent)"
1221+ "public static bool On{func_name_pascal_case}(ClientApi.Event dbEvent)"
12121222 )
12131223 . unwrap ( ) ;
12141224 writeln ! ( output, "{{" ) . unwrap ( ) ;
@@ -1224,11 +1234,7 @@ pub fn autogen_csharp_reducer(ctx: &GenCtx, reducer: &ReducerDef, namespace: &st
12241234 "var args = dbEvent.FunctionCall.CallInfo.{func_name_pascal_case}Args;"
12251235 )
12261236 . unwrap ( ) ;
1227- writeln ! (
1228- output,
1229- "On{func_name_pascal_case}Event(dbEvent.Status, Identity.From(dbEvent.CallerIdentity.ToByteArray())"
1230- )
1231- . unwrap ( ) ;
1237+ writeln ! ( output, "On{func_name_pascal_case}Event(dbEvent.FunctionCall.CallInfo" ) . unwrap ( ) ;
12321238 // Write out arguments one per line
12331239 {
12341240 indent_scope ! ( output) ;
@@ -1243,13 +1249,15 @@ pub fn autogen_csharp_reducer(ctx: &GenCtx, reducer: &ReducerDef, namespace: &st
12431249 }
12441250 }
12451251 writeln ! ( output, ");" ) . unwrap ( ) ;
1252+ writeln ! ( output, "return true;" ) . unwrap ( ) ;
12461253 }
12471254 // Closing brace for if event is registered
12481255 writeln ! ( output, "}}" ) . unwrap ( ) ;
1256+ writeln ! ( output, "return false;" ) . unwrap ( ) ;
12491257 }
1250-
12511258 // Closing brace for Event parsing function
12521259 writeln ! ( output, "}}" ) . unwrap ( ) ;
1260+ writeln ! ( output) . unwrap ( ) ;
12531261
12541262 writeln ! ( output, "[DeserializeEvent(FunctionName = \" {func_name}\" )]" ) . unwrap ( ) ;
12551263 writeln ! (
@@ -1286,7 +1294,7 @@ pub fn autogen_csharp_reducer(ctx: &GenCtx, reducer: &ReducerDef, namespace: &st
12861294
12871295 writeln ! ( output, "var argsGeneric = new ReducerArgs();" ) . unwrap ( ) ;
12881296 writeln ! ( output, "argsGeneric.{func_name_pascal_case}Args = args;" ) . unwrap ( ) ;
1289- writeln ! ( output, "dbEvent.FunctionCall.CallInfo = new ReducerEvent(ReducerType.{func_name_pascal_case}, dbEvent.Message, dbEvent.Status, argsGeneric);" ) . unwrap ( ) ;
1297+ writeln ! ( output, "dbEvent.FunctionCall.CallInfo = new ReducerEvent(ReducerType.{func_name_pascal_case}, \" {func_name} \" , dbEvent.Timestamp, Identity.From(dbEvent.CallerIdentity.ToByteArray()), dbEvent.Message, dbEvent.Status, argsGeneric);" ) . unwrap ( ) ;
12901298 }
12911299
12921300 // Closing brace for Event parsing function
@@ -1315,51 +1323,6 @@ pub fn autogen_csharp_reducer(ctx: &GenCtx, reducer: &ReducerDef, namespace: &st
13151323 writeln ! ( output, "}}" ) . unwrap ( ) ;
13161324 writeln ! ( output) . unwrap ( ) ;
13171325
1318- //ReducerArgs struct
1319- writeln ! ( output, "public partial struct ReducerArgs" ) . unwrap ( ) ;
1320- writeln ! ( output, "{{" ) . unwrap ( ) ;
1321- {
1322- indent_scope ! ( output) ;
1323- writeln ! ( output, "[System.Runtime.InteropServices.FieldOffset(0)]" ) . unwrap ( ) ;
1324- writeln ! (
1325- output,
1326- "public {func_name_pascal_case}ArgsStruct {func_name_pascal_case}Args;"
1327- )
1328- . unwrap ( ) ;
1329- }
1330- // Closing brace for struct ReducerArgs
1331- writeln ! ( output, "}}" ) . unwrap ( ) ;
1332- writeln ! ( output) . unwrap ( ) ;
1333-
1334- //ReducerEvent
1335- writeln ! ( output, "public partial class ReducerEvent" ) . unwrap ( ) ;
1336- writeln ! ( output, "{{" ) . unwrap ( ) ;
1337- {
1338- indent_scope ! ( output) ;
1339- writeln ! (
1340- output,
1341- "public {func_name_pascal_case}ArgsStruct {func_name_pascal_case}Args"
1342- )
1343- . unwrap ( ) ;
1344- writeln ! ( output, "{{" ) . unwrap ( ) ;
1345- {
1346- indent_scope ! ( output) ;
1347- writeln ! ( output, "get" ) . unwrap ( ) ;
1348- writeln ! ( output, "{{" ) . unwrap ( ) ;
1349- {
1350- indent_scope ! ( output) ;
1351- writeln ! ( output, "if (Reducer != ReducerType.{func_name_pascal_case}) throw new SpacetimeDB.ReducerMismatchException(Reducer.ToString(), \" {func_name_pascal_case}\" );" ) . unwrap ( ) ;
1352- writeln ! ( output, "return Args.{func_name_pascal_case}Args;" ) . unwrap ( ) ;
1353- }
1354- // Closing brace for struct ReducerArgs
1355- writeln ! ( output, "}}" ) . unwrap ( ) ;
1356- }
1357- // Closing brace for struct ReducerArgs
1358- writeln ! ( output, "}}" ) . unwrap ( ) ;
1359- }
1360- // Closing brace for struct ReducerArgs
1361- writeln ! ( output, "}}" ) . unwrap ( ) ;
1362-
13631326 if use_namespace {
13641327 output. dedent ( 1 ) ;
13651328 writeln ! ( output, "}}" ) . unwrap ( ) ;
@@ -1368,23 +1331,23 @@ pub fn autogen_csharp_reducer(ctx: &GenCtx, reducer: &ReducerDef, namespace: &st
13681331 output. into_inner ( )
13691332}
13701333
1371- pub fn autogen_csharp_globals ( items : & Vec < GenItem > , namespace : & str ) -> Vec < ( String , String ) > {
1372- let reducer_names : Vec < String > = items
1334+ pub fn autogen_csharp_globals ( items : & [ GenItem ] , namespace : & str ) -> Vec < ( String , String ) > {
1335+ let reducers : Vec < & ReducerDef > = items
13731336 . iter ( )
1374- . filter ( |item | {
1375- if let GenItem :: Reducer ( reducer) = item {
1376- reducer. name != "__init__"
1337+ . map ( |i | {
1338+ if let GenItem :: Reducer ( reducer) = i {
1339+ Some ( reducer)
13771340 } else {
1378- false
1379- }
1380- } )
1381- . map ( |item| {
1382- if let GenItem :: Reducer ( reducer) = item {
1383- reducer. name . to_case ( Case :: Pascal )
1384- } else {
1385- unreachable ! ( )
1341+ None
13861342 }
13871343 } )
1344+ . filter ( |r| r. is_some ( ) )
1345+ . flatten ( )
1346+ . filter ( |r| r. name != "__init__" )
1347+ . collect ( ) ;
1348+ let reducer_names: Vec < String > = reducers
1349+ . iter ( )
1350+ . map ( |reducer| reducer. name . to_case ( Case :: Pascal ) )
13881351 . collect ( ) ;
13891352
13901353 let use_namespace = true ;
@@ -1417,6 +1380,7 @@ pub fn autogen_csharp_globals(items: &Vec<GenItem>, namespace: &str) -> Vec<(Str
14171380 writeln ! ( output, "{{" ) . unwrap ( ) ;
14181381 {
14191382 indent_scope ! ( output) ;
1383+ writeln ! ( output, "None," ) . unwrap ( ) ;
14201384 for reducer in reducer_names {
14211385 writeln ! ( output, "{reducer}," ) . unwrap ( ) ;
14221386 }
@@ -1430,6 +1394,9 @@ pub fn autogen_csharp_globals(items: &Vec<GenItem>, namespace: &str) -> Vec<(Str
14301394 {
14311395 indent_scope ! ( output) ;
14321396 writeln ! ( output, "public ReducerType Reducer {{ get; private set; }}" ) . unwrap ( ) ;
1397+ writeln ! ( output, "public string ReducerName {{ get; private set; }}" ) . unwrap ( ) ;
1398+ writeln ! ( output, "public ulong Timestamp {{ get; private set; }}" ) . unwrap ( ) ;
1399+ writeln ! ( output, "public SpacetimeDB.Identity Identity {{ get; private set; }}" ) . unwrap ( ) ;
14331400 writeln ! ( output, "public string ErrMessage {{ get; private set; }}" ) . unwrap ( ) ;
14341401 writeln ! (
14351402 output,
@@ -1438,18 +1405,42 @@ pub fn autogen_csharp_globals(items: &Vec<GenItem>, namespace: &str) -> Vec<(Str
14381405 . unwrap ( ) ;
14391406 writeln ! ( output, "private ReducerArgs Args;" ) . unwrap ( ) ;
14401407 writeln ! ( output) . unwrap ( ) ;
1441- writeln ! ( output, "public ReducerEvent(ReducerType reducer, string errMessage, ClientApi.Event.Types.Status status, ReducerArgs args)" ) . unwrap ( ) ;
1408+ writeln ! ( output, "public ReducerEvent(ReducerType reducer, string reducerName, ulong timestamp, SpacetimeDB.Identity identity, string errMessage, ClientApi.Event.Types.Status status, ReducerArgs args)" ) . unwrap ( ) ;
14421409 writeln ! ( output, "{{" ) . unwrap ( ) ;
14431410 {
14441411 indent_scope ! ( output) ;
14451412 writeln ! ( output, "Reducer = reducer;" ) . unwrap ( ) ;
1413+ writeln ! ( output, "ReducerName = reducerName;" ) . unwrap ( ) ;
1414+ writeln ! ( output, "Timestamp = timestamp;" ) . unwrap ( ) ;
1415+ writeln ! ( output, "Identity = identity;" ) . unwrap ( ) ;
14461416 writeln ! ( output, "ErrMessage = errMessage;" ) . unwrap ( ) ;
14471417 writeln ! ( output, "Status = status;" ) . unwrap ( ) ;
14481418 writeln ! ( output, "Args = args;" ) . unwrap ( ) ;
14491419 }
14501420 // Closing brace for ctor
14511421 writeln ! ( output, "}}" ) . unwrap ( ) ;
14521422 writeln ! ( output) . unwrap ( ) ;
1423+ // Properties for reducer args
1424+ for reducer in & reducers {
1425+ let reducer_name = reducer. name . to_case ( Case :: Pascal ) ;
1426+ writeln ! ( output, "public {reducer_name}ArgsStruct {reducer_name}Args" ) . unwrap ( ) ;
1427+ writeln ! ( output, "{{" ) . unwrap ( ) ;
1428+ {
1429+ indent_scope ! ( output) ;
1430+ writeln ! ( output, "get" ) . unwrap ( ) ;
1431+ writeln ! ( output, "{{" ) . unwrap ( ) ;
1432+ {
1433+ indent_scope ! ( output) ;
1434+ writeln ! ( output, "if (Reducer != ReducerType.{reducer_name}) throw new SpacetimeDB.ReducerMismatchException(Reducer.ToString(), \" {reducer_name}\" );" ) . unwrap ( ) ;
1435+ writeln ! ( output, "return Args.{reducer_name}Args;" ) . unwrap ( ) ;
1436+ }
1437+ // Closing brace for struct ReducerArgs
1438+ writeln ! ( output, "}}" ) . unwrap ( ) ;
1439+ }
1440+ // Closing brace for struct ReducerArgs
1441+ writeln ! ( output, "}}" ) . unwrap ( ) ;
1442+ }
1443+ writeln ! ( output) . unwrap ( ) ;
14531444 writeln ! ( output, "public object[] GetArgsAsObjectArray()" ) . unwrap ( ) ;
14541445 writeln ! ( output, "{{" ) . unwrap ( ) ;
14551446 {
@@ -1458,34 +1449,29 @@ pub fn autogen_csharp_globals(items: &Vec<GenItem>, namespace: &str) -> Vec<(Str
14581449 writeln ! ( output, "{{" ) . unwrap ( ) ;
14591450 {
14601451 indent_scope ! ( output) ;
1461- for item in items {
1462- if let GenItem :: Reducer ( reducer ) = item {
1463- if reducer . name == "__init__" {
1464- continue ;
1465- }
1466- let reducer_name = reducer . name . to_case ( Case :: Pascal ) ;
1467- writeln ! ( output, "case ReducerType. {reducer_name}: " ) . unwrap ( ) ;
1468- writeln ! ( output, "{{" ) . unwrap ( ) ;
1452+ for reducer in & reducers {
1453+ let reducer_name = reducer . name . to_case ( Case :: Pascal ) ;
1454+ writeln ! ( output , "case ReducerType.{reducer_name}:" ) . unwrap ( ) ;
1455+ writeln ! ( output , "{{" ) . unwrap ( ) ;
1456+ {
1457+ indent_scope ! ( output ) ;
1458+ writeln ! ( output, "var args = {reducer_name}Args; " ) . unwrap ( ) ;
1459+ writeln ! ( output, "return new object[] {{" ) . unwrap ( ) ;
14691460 {
14701461 indent_scope ! ( output) ;
1471- writeln ! ( output, "var args = {reducer_name}Args;" ) . unwrap ( ) ;
1472- writeln ! ( output, "return new object[] {{" ) . unwrap ( ) ;
1473- {
1474- indent_scope ! ( output) ;
1475- for ( i, arg) in reducer. args . iter ( ) . enumerate ( ) {
1476- let arg_name = arg
1477- . name
1478- . clone ( )
1479- . unwrap_or_else ( || format ! ( "arg_{}" , i) )
1480- . to_case ( Case :: Pascal ) ;
1481- writeln ! ( output, "args.{arg_name}," ) . unwrap ( ) ;
1482- }
1462+ for ( i, arg) in reducer. args . iter ( ) . enumerate ( ) {
1463+ let arg_name = arg
1464+ . name
1465+ . clone ( )
1466+ . unwrap_or_else ( || format ! ( "arg_{}" , i) )
1467+ . to_case ( Case :: Pascal ) ;
1468+ writeln ! ( output, "args.{arg_name}," ) . unwrap ( ) ;
14831469 }
1484- writeln ! ( output, "}};" ) . unwrap ( ) ;
14851470 }
1486- // Closing brace for switch
1487- writeln ! ( output, "}}" ) . unwrap ( ) ;
1471+ writeln ! ( output, "}};" ) . unwrap ( ) ;
14881472 }
1473+ // Closing brace for switch
1474+ writeln ! ( output, "}}" ) . unwrap ( ) ;
14891475 }
14901476 writeln ! ( output, "default: throw new System.Exception($\" Unhandled reducer case: {{Reducer}}. Please run SpacetimeDB code generator\" );" ) . unwrap ( ) ;
14911477 }
@@ -1503,7 +1489,19 @@ pub fn autogen_csharp_globals(items: &Vec<GenItem>, namespace: &str) -> Vec<(Str
15031489 "[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit)]"
15041490 )
15051491 . unwrap ( ) ;
1506- writeln ! ( output, "public partial struct ReducerArgs {{ }}" ) . unwrap ( ) ;
1492+ writeln ! ( output, "public partial struct ReducerArgs" ) . unwrap ( ) ;
1493+ writeln ! ( output, "{{" ) . unwrap ( ) ;
1494+ {
1495+ indent_scope ! ( output) ;
1496+ for reducer in & reducers {
1497+ let reducer_name = reducer. name . to_case ( Case :: Pascal ) ;
1498+ writeln ! ( output, "[System.Runtime.InteropServices.FieldOffset(0)]" ) . unwrap ( ) ;
1499+ writeln ! ( output, "public {reducer_name}ArgsStruct {reducer_name}Args;" ) . unwrap ( ) ;
1500+ }
1501+ }
1502+ // Closing brace for struct ReducerArgs
1503+ writeln ! ( output, "}}" ) . unwrap ( ) ;
1504+ writeln ! ( output) . unwrap ( ) ;
15071505
15081506 if use_namespace {
15091507 output. dedent ( 1 ) ;
0 commit comments