I have the following lambda
that works fine:
public interface IOhlcv : ITick
{
decimal Open { get; set; }
decimal High { get; set; }
decimal Low { get; set; }
decimal Close { get; set; }
decimal Volume { get; set; }
}
c1,c2,c3
are of type IList<IOhlcv>
This is the lambda
:
(c1, c2, c3) => c1.Close / c2.Close * c3.Close
If the lambda
were a string
representation of a lambda
,
string lambdaStr = "(c1, c2, c3) => c1.Close / c2.Close * c3.Close"
how do I compile
it to a real lambda
? NOTE: (lambdaStr can be created dynamically, e.g., c1, c2, c3 can be any number of parameters with operators between them)
I tried using https://github.com/dotnet/roslyn/wiki/Scripting-API-Samples#expr
Like this:
var options = ScriptOptions.Default.AddReferences(typeof(IOhlcv).Assembly);
var projection = await CSharpScript.EvaluateAsync<IList<decimal>>(projectionString, options);
but I can't get it to work:
Message = "(1,1): error CS1660: Cannot convert lambda expression to type 'IList<decimal>' because it is not a delegate type"
Edit 1
Even trying this
try
{
string lambdaStr = "(c1, c2, c3) => c1.Close / c2.Close * c3.Close";
var options = ScriptOptions.Default.AddReferences(typeof(IOhlcv).Assembly);
// this will be a delegate type and you will need to turn it into one that fits
dynamic projection = await CSharpScript.EvaluateAsync<dynamic>(lambdaStr, options);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
give this exception
:
'Microsoft.CodeAnalysis.Scripting.CompilationErrorException' in Microsoft.CodeAnalysis.Scripting.dll
Microsoft.CodeAnalysis.Scripting.CompilationErrorException: (1,1): error CS1660: Cannot convert lambda expression to type 'object' because it is not a delegate type
at Microsoft.CodeAnalysis.Scripting.ScriptBuilder.ThrowIfAnyCompilationErrors(DiagnosticBag diagnostics, DiagnosticFormatter formatter)
at Microsoft.CodeAnalysis.Scripting.ScriptBuilder.CreateExecutor[T](ScriptCompiler compiler, Compilation compilation, Boolean emitDebugInformation, CancellationToken cancellationToken)
at Microsoft.CodeAnalysis.Scripting.Script`1.GetExecutor(CancellationToken cancellationToken)
at Microsoft.CodeAnalysis.Scripting.Script`1.RunAsync(Object globals, Func`2 catchException, CancellationToken cancellationToken)
at Microsoft.CodeAnalysis.CSharp.Scripting.CSharpScript.RunAsync[T](String code, ScriptOptions options, Object globals, Type globalsType, CancellationToken cancellationToken)
at Microsoft.CodeAnalysis.CSharp.Scripting.CSharpScript.EvaluateAsync[T](String code, ScriptOptions options, Object globals, Type globalsType, CancellationToken cancellationToken)
at Trady.Form1.<ZipSeries>d__17.MoveNext() in C:\Users\idf\Form1.cs:line 281
Edit 2
This suggestion feels like something is getting closer, but no cigar:
try
{
var options = ScriptOptions.Default.AddReferences(typeof(IOhlcv).Assembly);
var projection = await CSharpScript.EvaluateAsync<Func<IOhlcv,IOhlcv,IOhlcv,decimal>>(projectionString, options);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
ex = {"(1,18): error CS1061: 'IOhlcv' does not contain a definition for 'close' and no accessible extension method 'close' accepting a first argument of type 'IOhlcv' could be found (are you missing a using directive or an assembly reference?)"}
Edit 3
There was a bug in code where ".close" is generated. When it is changed to ".Close" the code in Edit 2 works.
It still doesn't answer the question of how to create a lambda
that can take a variable number of parameters
since Func<IOhlcv,IOhlcv,IOhlcv,decimal>
is hardwired, but it is a step forward.
Can CSharpScript.EvaluateAsync
compile to a delegate
that takes a variable number of parameters?