diff --git a/Directory.Build.props b/Directory.Build.props
index d15ef0e..5f5b29b 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -9,7 +9,7 @@
Simpra
ALTA Software llc.
Copyright © 2024 ALTA Software llc.
- 1.0.12
+ 1.0.13
diff --git a/src/AltaSoft.Simpra/Visitor/SimpraParserVisitor.cs b/src/AltaSoft.Simpra/Visitor/SimpraParserVisitor.cs
index 989ccef..316616c 100644
--- a/src/AltaSoft.Simpra/Visitor/SimpraParserVisitor.cs
+++ b/src/AltaSoft.Simpra/Visitor/SimpraParserVisitor.cs
@@ -263,6 +263,14 @@ public Expression VisitIndexAccess(SimpraParser.IndexAccessContext context)
objectType = left.Type;
}
+ // Handle IDictionary (including Dictionary<,>)
+ var isDictionary = objectType.IsIReadOnlyDictionaryT();
+
+ if (isDictionary)
+ {
+ return HandleDictionaryIndexAccess(context, objectType, index, left);
+ }
+
// Handle indexable types (e.g., List)
var defaultIndexer = objectType
.GetProperties()
@@ -552,4 +560,21 @@ public Expression VisitArray(SimpraParser.ArrayContext context)
{
return NewSimpraList(context.exp().Select(Visit), context);
}
+
+ private static Expression HandleDictionaryIndexAccess(SimpraParser.IndexAccessContext context, Type objectType, Expression index, Expression left)
+ {
+ var keyType = objectType.GetGenericArguments()[0];
+ var valueType = objectType.GetGenericArguments()[1];
+ var tryGetValueMethod = objectType.GetMethod("TryGetValue", [keyType, valueType.MakeByRefType()])!;
+
+ var keyExpr = index.Type != keyType ? Expression.Convert(index, keyType) : index;
+ var valueVar = Expression.Variable(valueType, "dictValue");
+
+ var tryGetValueCall = Expression.Call(left, tryGetValueMethod, keyExpr, valueVar);
+
+ var defaultValue = Expression.Default(valueType);
+ var block = Expression.Block([valueVar], Expression.Condition(tryGetValueCall, valueVar, defaultValue));
+
+ return ConvertToSimpraType(block, false, context);
+ }
}
diff --git a/tests/AltaSoft.Simpra.tests/Models/TestModel.cs b/tests/AltaSoft.Simpra.tests/Models/TestModel.cs
index 3478df2..24f9f89 100644
--- a/tests/AltaSoft.Simpra.tests/Models/TestModel.cs
+++ b/tests/AltaSoft.Simpra.tests/Models/TestModel.cs
@@ -30,6 +30,9 @@ public class TestModel : BaseModel, ITransferModel
public required Transfer? Transfer { get; set; }
public required Customer Customer { get; set; }
public required string Remittance { get; set; }
+ public Dictionary? Countries { get; set; }
+
+ public Dictionary? DictionaryOfObjects { get; set; }
public ColorX ColorX { get; set; } = ColorX.Green;
public ColorM ColorM { get; set; } = ColorM.Green;
diff --git a/tests/AltaSoft.Simpra.tests/SimpraExpressionTests.cs b/tests/AltaSoft.Simpra.tests/SimpraExpressionTests.cs
index 695fc1b..7943ac6 100644
--- a/tests/AltaSoft.Simpra.tests/SimpraExpressionTests.cs
+++ b/tests/AltaSoft.Simpra.tests/SimpraExpressionTests.cs
@@ -4,6 +4,60 @@ namespace AltaSoft.Simpra.Tests;
public class SimpraExpressionTests
{
+
+ [Fact]
+ public void DictionaryIndexer_MissingKey_ReturnsDefaultValueForProperty()
+ {
+ const string expressionCode =
+ """
+ return DictionaryOfObjects['test'].Id
+ """;
+
+ var simpra = new Simpra();
+ var model = GetTestModel();
+ model.DictionaryOfObjects = new Dictionary { { "Georgia", new Customer
+ {
+ Id = 1,
+ Status = 10
+ }} };
+
+ var result = simpra.Execute(model, new TestFunctions(), expressionCode);
+ Assert.Equal(0, result);
+
+ }
+
+ [Fact]
+ public void CallGetValueFromDictionaryWhenKeyDoesNotExist_ShouldReturnDefault()
+ {
+ const string expressionCode =
+ """
+ return Countries['test'] is 'Test'
+ """;
+
+ var simpra = new Simpra();
+ var model = GetTestModel();
+ model.Countries = new Dictionary { { "Georgia", "Test" } };
+ var result = simpra.Execute(model, new TestFunctions(), expressionCode);
+ Assert.False(result);
+
+ }
+
+ [Fact]
+ public void CallGetValueFromDictionaryWhenKeyExist_ShouldReturnValue()
+ {
+ const string expressionCode =
+ """
+ return Countries['Georgia'] is 'Test'
+ """;
+
+ var simpra = new Simpra();
+ var model = GetTestModel();
+ model.Countries = new Dictionary { { "Georgia", "Test" } };
+ var result = simpra.Execute(model, new TestFunctions(), expressionCode);
+ Assert.True(result);
+
+ }
+
[Fact]
public void CallInterfaceFunctionFromSimpra_ShouldReturnCorrectValue()
{