Skip to content

Commit

Permalink
bind dynamic properties and methods of concrete class, add late bindi…
Browse files Browse the repository at this point in the history
…ng on object (#156)
  • Loading branch information
israellot authored Jun 23, 2021
1 parent b9fab54 commit 4aabda0
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 7 deletions.
4 changes: 3 additions & 1 deletion src/DynamicExpresso.Core/Interpreter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ public Interpreter(InterpreterOptions options)
{
var caseInsensitive = options.HasFlag(InterpreterOptions.CaseInsensitive);

_settings = new ParserSettings(caseInsensitive);
var lateBindObject = options.HasFlag(InterpreterOptions.LateBindObject);

_settings = new ParserSettings(caseInsensitive, lateBindObject);

if ((options & InterpreterOptions.SystemKeywords) == InterpreterOptions.SystemKeywords)
{
Expand Down
6 changes: 5 additions & 1 deletion src/DynamicExpresso.Core/InterpreterOptions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;

namespace DynamicExpresso
{
Expand All @@ -23,6 +23,10 @@ public enum InterpreterOptions
/// </summary>
CaseInsensitive = 8,
/// <summary>
/// Allow treating expressions of type Object as dynamic
/// </summary>
LateBindObject = 16,
/// <summary>
/// Load all default configurations: PrimitiveTypes + SystemKeywords + CommonTypes
/// </summary>
Default = PrimitiveTypes | SystemKeywords | CommonTypes,
Expand Down
6 changes: 4 additions & 2 deletions src/DynamicExpresso.Core/Parsing/Parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1384,9 +1384,11 @@ private static bool IsDynamicType(Type type)
return typeof(IDynamicMetaObjectProvider).IsAssignableFrom(type);
}

private static bool IsDynamicExpression(Expression instance)
private bool IsDynamicExpression(Expression instance)
{
return instance != null && instance.NodeType == ExpressionType.Dynamic;
return instance != null &&
(instance.NodeType == ExpressionType.Dynamic ||
(_arguments.Settings.LateBindObject && instance.Type == typeof(object)));
}

private static Type GetNonNullableType(Type type)
Expand Down
16 changes: 14 additions & 2 deletions src/DynamicExpresso.Core/Parsing/ParserSettings.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Reflection;

Expand All @@ -10,10 +10,12 @@ internal class ParserSettings
private readonly Dictionary<string, ReferenceType> _knownTypes;
private readonly HashSet<MethodInfo> _extensionMethods;

public ParserSettings(bool caseInsensitive)
public ParserSettings(bool caseInsensitive,bool lateBindObject)
{
CaseInsensitive = caseInsensitive;

LateBindObject = lateBindObject;

KeyComparer = CaseInsensitive ? StringComparer.InvariantCultureIgnoreCase : StringComparer.InvariantCulture;

KeyComparison = CaseInsensitive ? StringComparison.InvariantCultureIgnoreCase : StringComparison.InvariantCulture;
Expand All @@ -27,6 +29,8 @@ public ParserSettings(bool caseInsensitive)
AssignmentOperators = AssignmentOperators.All;

DefaultNumberType = DefaultNumberType.Default;


}

public IDictionary<string, ReferenceType> KnownTypes
Expand All @@ -50,6 +54,12 @@ public bool CaseInsensitive
private set;
}

public bool LateBindObject
{
get;
private set;
}

public DefaultNumberType DefaultNumberType
{
get;
Expand All @@ -73,5 +83,7 @@ public AssignmentOperators AssignmentOperators
get;
set;
}


}
}
39 changes: 38 additions & 1 deletion test/DynamicExpresso.UnitTest/DynamicTest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Microsoft.CSharp.RuntimeBinder;
using Microsoft.CSharp.RuntimeBinder;
using NUnit.Framework;
using System;
using System.Dynamic;
Expand Down Expand Up @@ -242,6 +242,43 @@ public void Math_with_dynamic_properties()
Assert.AreEqual(500 % dyn.Foo, interpreter.Eval("500 % dyn.Foo"));
}

public class ClassWithObjectProperties
{
public object Foo => 100;
public object Bar() => 100;
}

[Test]
public void ObjectLateBinding()
{


var classWithObjectProperties = new ClassWithObjectProperties();


Assert.Throws<ParseException>(() => {

var noLateBindingInterpreter = new Interpreter();
var noLateBindingDel = noLateBindingInterpreter.ParseAsDelegate<Func<ClassWithObjectProperties, int>>("d.Foo+d.Bar()", new[] { "d" });
var noLateBindingResult = noLateBindingDel.Invoke(classWithObjectProperties);

});


var lateBindingInterpreter = new Interpreter(InterpreterOptions.Default|InterpreterOptions.LateBindObject);
var lateBindingInterpreterDel = lateBindingInterpreter.ParseAsDelegate<Func<ClassWithObjectProperties, int>>("d.Foo+d.Bar()", new[] { "d" });
var lateBindingResult = lateBindingInterpreterDel.Invoke(classWithObjectProperties);
Assert.AreEqual((dynamic)classWithObjectProperties.Foo + (dynamic)classWithObjectProperties.Bar(), lateBindingResult);


lateBindingInterpreter.SetVariable("d", classWithObjectProperties);
var evalResult = lateBindingInterpreter.Eval("d.Foo+d.Bar()");
Assert.IsTrue(evalResult.GetType() == typeof(int));
Assert.AreEqual((dynamic)classWithObjectProperties.Foo + (dynamic)classWithObjectProperties.Bar(), evalResult);

}


[Test]
public void Bitwise_with_dynamic_properties()
{
Expand Down

0 comments on commit 4aabda0

Please sign in to comment.