DynamicExpresso.SetFunction not working with method overload

923 Views Asked by At

I'm using Dynamic Expresso for expression evaluation and works like a charm. Actually setting up custom functions, but seems like there is a something wrong with a method overload.

I've actually got two Round methods:

First one with one argument:

public static decimal Round(decimal userNumber)
{
    return Math.Round(userNumber);
}

Second one with two arguments:

public static decimal Round(decimal userNumber, int decimals)
{
    return Math.Round(userNumber, decimals);
}

Delegates got declared and Interpreter.SetFunction is called with no errors as well:

Func<decimal, decimal> roundFunction1 = (userNumber) => Round(userNumber);
Func<decimal, int, decimal> roundFunction2 = (userNumber, decimals) => Round(userNumber, decimals);

interpreter.SetFunction("ROUND", roundFunction1);
interpreter.SetFunction("ROUND", roundFunction2);

Variables are correctly passed and I've checked many times already that the parameter I'm passing is, in fact, a decimal.

The evaluation expression I pass, finally contains the following string, which has nothing wrong since the Interpreter.SetVariable(property.Key, property.Value) is inserting an "ImporteTotal" and a 666.66:

ROUND(ImporteTotal)

So, the exception I get when the evaluation gets done is:

Argument list incompatible with delegate expression (at index 0).

Note that I'm actually setting lots of functions which uses even DateTimes, int, strings and so on even combined, overloads as well! All of them work perfectly, but seems that deleting any of those overloads helps it working. In case both of them are "imported" on Dynamic Expresso, it complains.

Any ideas?

Many thanks.

UPDATE-EDIT:

I reviewed the UnitTesting Davide provided through pastebin and seems I got it failing.

This unit testing seems that is failing.

[Test]
public static void TestInterpreter()
{
    var interpreter = new Interpreter();

    Func<decimal, decimal> roundFunction1 = (userNumber) => Round(userNumber);
    Func<decimal, int, decimal> roundFunction2 = (userNumber, decimals) => Round(userNumber, decimals);
    Func<string, string, int> charindexFunction1 = (toFind, userString) => Charindex(toFind, userString);
    Func<string, string, int, int> charindexFunction2 = (toFind, userString, offset) => Charindex(toFind, userString, offset);

    interpreter.SetFunction("ROUND", roundFunction1);
    interpreter.SetFunction("ROUND", roundFunction2);
    interpreter.SetFunction("CHARINDEX", charindexFunction1);
    interpreter.SetFunction("CHARINDEX", charindexFunction2);

    var importe = 666.66M;
    interpreter.SetVariable("ImporteTotal", importe);

    var textoAlbaran = "ALBARAN-01";
    interpreter.SetVariable("Albaran", textoAlbaran);

    Assert.AreEqual(Round(importe), interpreter.Eval("ROUND(ImporteTotal)"));
    Assert.AreEqual(Round(importe, 1), interpreter.Eval("ROUND(ImporteTotal, 1)"));
    Assert.AreEqual(Charindex("BARAN", textoAlbaran), interpreter.Eval("CHARINDEX(\"BARAN\", Albaran"));
    Assert.AreEqual(Charindex("BARAN", textoAlbaran, 2), interpreter.Eval("CHARINDEX(\"BARAN\", Albaran, 2)"));
}

public static decimal Round(decimal userNumber)
{
    return Math.Round(userNumber);
}

public static decimal Round(decimal userNumber, int decimals)
{
    return Math.Round(userNumber, decimals);
}

public static int Charindex(string toFind, string userString)
{
    return userString.IndexOf(toFind);
}

public static int Charindex(string toFind, string userString, int offset)
{
    return userString.IndexOf(toFind, offset);
}
1

There are 1 best solutions below

1
On BEST ANSWER

Starting with DynamicExpresso 2.5.0, it's possible to register multiple methods with the same name (ie. overloads):

Func<decimal, decimal> roundFunction1 = (userNumber) => Math.Round(userNumber);
Func<decimal, int, decimal> roundFunction2 = (userNumber, decimals) => Math.Round(userNumber, decimals);

var interpreter = new Interpreter();
interpreter.SetFunction("ROUND", roundFunction1);
interpreter.SetFunction("ROUND", roundFunction2);

Assert.AreEqual(3.13M, interpreter.Eval("ROUND(3.12789M, 2)"));
Assert.AreEqual(3M, interpreter.Eval("ROUND(3.12789M)"));