Skip to content

Commit 83952a8

Browse files
committed
First easy implementation for out and ref keyword + out test (Need improvement)
relative to #83
1 parent 341b932 commit 83952a8

File tree

2 files changed

+56
-2
lines changed

2 files changed

+56
-2
lines changed

CodingSeb.ExpressionEvaluator.Tests/ExpressionEvaluatorTests.cs

+24
Original file line numberDiff line numberDiff line change
@@ -2222,5 +2222,29 @@ public void EvaluateWithSubExpressionsVariables()
22222222
}
22232223

22242224
#endregion
2225+
2226+
#region method with out parameter
2227+
2228+
[Test]
2229+
public void MethodWithOutParameter()
2230+
{
2231+
ExpressionEvaluator evaluator = new ExpressionEvaluator();
2232+
2233+
evaluator.Variables["myDict"] = new Dictionary<string, object>
2234+
{
2235+
{ "ANumber", 10 },
2236+
};
2237+
2238+
evaluator.Variables["x"] = null;
2239+
2240+
evaluator.Evaluate<bool>("myDict.TryGetValue(\"ANumber\",out x)").ShouldBeTrue();
2241+
2242+
evaluator.Variables.ShouldContainKey("x");
2243+
evaluator.Variables["x"]
2244+
.ShouldBeOfType<int>()
2245+
.ShouldBe(10);
2246+
}
2247+
2248+
#endregion
22252249
}
22262250
}

CodingSeb.ExpressionEvaluator/ExpressionEvaluator.cs

+32-2
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ public partial class ExpressionEvaluator
5353
protected static readonly Regex lambdaExpressionRegex = new Regex(@"^(?>\s*)(?<args>((?>\s*)[(](?>\s*)([\p{L}_](?>[\p{L}_0-9]*)(?>\s*)([,](?>\s*)[\p{L}_][\p{L}_0-9]*(?>\s*))*)?[)])|[\p{L}_](?>[\p{L}_0-9]*))(?>\s*)=>(?<expression>.*)$", RegexOptions.Singleline | RegexOptions.Compiled);
5454
protected static readonly Regex lambdaArgRegex = new Regex(@"[\p{L}_](?>[\p{L}_0-9]*)", RegexOptions.Compiled);
5555
protected static readonly Regex initInNewBeginningRegex = new Regex(@"^(?>\s*){", RegexOptions.Compiled);
56+
protected static readonly Regex functionArgKeywordsRegex = new Regex(@"^\s*(?<keyword>out|ref)\s*(?<varName>[\p{L}_](?>[\p{L}_0-9]*))", RegexOptions.Compiled | RegexOptions.IgnoreCase);
5657

5758
// Depending on OptionInlineNamespacesEvaluationActive. Initialized in constructor
5859
protected string InstanceCreationWithNewKeywordRegexPattern { get { return @"^new(?>\s*)((?<isAnonymous>[{{])|((?<name>[\p{L}_][\p{L}_0-9"+ (OptionInlineNamespacesEvaluationActive ? @"\." : string.Empty) + @"]*)(?>\s*)(?<isgeneric>[<](?>[^<>]+|(?<gentag>[<])|(?<-gentag>[>]))*(?(gentag)(?!))[>])?(?>\s*)((?<isfunction>[(])|(?<isArray>\[)|(?<isInit>[{{]))?))"; } }
@@ -1894,7 +1895,28 @@ protected virtual bool EvaluateVarOrFunc(string expression, Stack<object> stack,
18941895
}
18951896
else
18961897
{
1897-
List<object> oArgs = funcArgs.ConvertAll(Evaluate);
1898+
int argIndex = 0;
1899+
List<OutOrRefArg> outOrRefArgs = new List<OutOrRefArg>();
1900+
1901+
List<object> oArgs = funcArgs.ConvertAll(arg =>
1902+
{
1903+
Match functionArgKeywordsMatch = functionArgKeywordsRegex.Match(arg);
1904+
object argValue;
1905+
1906+
if (functionArgKeywordsMatch.Success)
1907+
{
1908+
OutOrRefArg outOrRefArg = new OutOrRefArg() { Index = argIndex, VariableName = functionArgKeywordsMatch.Groups["varName"].Value };
1909+
outOrRefArgs.Add(outOrRefArg);
1910+
argValue = Evaluate(outOrRefArg.VariableName);
1911+
}
1912+
else
1913+
{
1914+
argValue = Evaluate(arg);
1915+
}
1916+
1917+
argIndex++;
1918+
return argValue;
1919+
});
18981920
BindingFlags flag = DetermineInstanceOrStatic(ref objType, ref obj, ref valueTypeNestingTrace);
18991921

19001922
if (!OptionStaticMethodsCallActive && (flag & BindingFlags.Static) != 0)
@@ -1942,7 +1964,9 @@ protected virtual bool EvaluateVarOrFunc(string expression, Stack<object> stack,
19421964

19431965
if (methodInfo != null)
19441966
{
1945-
stack.Push(methodInfo.Invoke(isExtention ? null : obj, oArgs.ToArray()));
1967+
object[] argsArray = oArgs.ToArray();
1968+
stack.Push(methodInfo.Invoke(isExtention ? null : obj, argsArray));
1969+
outOrRefArgs.ForEach(outOrRefArg => variables[outOrRefArg.VariableName] = argsArray[outOrRefArg.Index]);
19461970
}
19471971
else if (objType.GetProperty(varFuncName, StaticBindingFlag) is PropertyInfo staticPropertyInfo
19481972
&& (staticPropertyInfo.PropertyType.IsSubclassOf(typeof(Delegate)) || staticPropertyInfo.PropertyType == typeof(Delegate))
@@ -3643,6 +3667,12 @@ public void AssignValue()
36433667
protected class NullConditionalNullValue
36443668
{ }
36453669

3670+
protected class OutOrRefArg
3671+
{
3672+
public int Index { get; set; }
3673+
public string VariableName { get; set; }
3674+
}
3675+
36463676
protected class DelegateEncaps
36473677
{
36483678
private readonly InternalDelegate lambda;

0 commit comments

Comments
 (0)