|
committed a fix that calculates a checksum hash over target-type + argument types and throws away cached method reference in case the checksums don't match.
It still needs some performance testing! just made a performance comparison and added MethodNodeTests.PerformanceOfMethodEvaluationOnDifferentContextTypes()
Expression: "ToString('dummy', CultureInfo.InvariantCulture)" Runs: 10.000.000 Duration with hash-checking of arguments: 8.4s Duration without hash-checking arguments: 7.5s of course when it comes to really switching context, throwing away the cache and reparsing the methodnode gets expensive. Around ~10% slow down. I'm curious Martin, what is your reason for not using ExpressionEvaluator.GetValue?
In my scenario I had a validator that checks if a value is contained in a collection returned by a business layer method. The method returns an ICollection<DomainObject> which can be an empty array, a List<DomainObject>, or even a decorated collection depending on the context. The collection is passed to the validator as a parameter to test that it contains the value of a property on the current context.
Test Expression: #collection.Contains(SomeProperty) Since the actual concrete collection may be different, the validator test expression can fail when it tries to evaluate the Contains method. |
||||||||||||||||||||||||||||||||||||||
[Test]
public void TestMethodEvaluationOnDifferentArgumentTypes()
{
IExpression expression = Expression.Parse("Foo(#var1)");
MethodInvokationCases testContext = new MethodInvokationCases();
Hashtable args = new Hashtable();
args["var1"] = "myString";
Assert.AreEqual("myString", expression.GetValue(testContext, args));
args["var1"] = 12;
Assert.AreEqual(12, expression.GetValue(testContext, args));
}
class MethodInvokationCases
{
public string Foo(string stringArg) { return stringArg; }
public int Foo(int intArg) { return intArg; }
}
This means we not only must throw away the cached SafeMethod instance in case of different target types, but also in case of different argument types.