c# FsCheck cannot convert lambda expression - c#

I'm trying to get a C# FsCheck generator to generate a series
of commands which are initialized with random strings. I came up with
the following solution:
public Gen<Command<A,B>> Next(B value)
{
var gen1 = Arb.Default.String().Generator;
var gen2 = Gen.two(gen1);
var gen3 = gen2.select((Command<A,B>)(s => new DerivedCommand(s.Item1,s.Item2)))
//DerivedCommand extends Command<A,B>
return Gen.OneOf(gen3);
}
However, VS cannot build this code:
Cannot convert lambda expression to type Command<A,B> because it is not a delegate type
I have searched solutions for this error message, but nothing I found helped.
I am using System.Linq and System.Data.Entity. Any suggestions for resolving this issue are much appreciated.

You're trying to cast (s => new DerivedCommand(s.Item1,s.Item2)), which is a lambda expression, to (Command<A,B>), which (I assume) is a class.
You probably need something like:
var gen3 = gen2.select(s => (Command<A,B>)(new DerivedCommand(s.Item1,s.Item2)));

Related

C# - Operator cannot be applied to operands of type 'XXX'?

I working a project .NET core 6.0 Console with Simple.OData.Client.
Just try the sample code - ODATA Batch Request and got error:
Operator '+=' cannot be applied to operands of type 'ODataBatch' and
'lambda expression'
Very sorry if I'm missing something obvious, but when I attempt to create a batch using the untyped syntax shown on the Wiki, I get an error that states Operator '+=' cannot be applied to operands of type 'ODataBatch' and 'lambda expression'. The code I'm using is the example code from the Wiki, shown below:
var batch = new ODataBatch(serviceUri);
batch += c => c.InsertEntryAsync(
"Products",
new Entry()
{
{ "ProductName", "Test1" },
{ "UnitPrice", 21m }
},
false);
await batch.ExecuteAsync();
I know I'm probably missing something simple and obvious here, but any help would be appreciated. I've tried a few things to make this work, but have failed to resolve the issue.
Thanks!
What does your Entry class look like?
InsertEntryAsync expects to receive a string, a IDictionary<string, object> and a bool. So for your code to work, Entry needs to be an IDictionary<string, object>.
What I think happens is c.InsertEntryAsync cannot be fully resolved because Entry is not a dictionary, and the lambda you write gets resolved as a lambda Expression instead of a Func<IODataClient, Task>. It needs to get resolved into the latter in order to use the + operator. See source
This code at least compiled for me:
var serviceUri = new Uri("asd");
var dict = new Dictionary<string, object>();
dict["ProductName"] = "Test1";
dict["UnitPrice"] = 21m;
var batch = new ODataBatch(serviceUri);
batch += c => c.InsertEntryAsync(
"Products",
dict,
false);
await batch.ExecuteAsync();

Exception trying to use a basic Expression created with LinqKit

I'm trying to force ef-core to paramerize values that it considers constants as described in this article by using LinqKit.
When trying to apply the PredicateBuilder example described on github, I get an exception. This is my code:
private async Task getWallets()
{
var query =
from w in _context.Wallets.AsExpandable()
where w.WalletItems.Any(hasItems().Compile())
select w;
var result = await query.ToListAsync();
}
private Expression<Func<WalletItem, bool>> hasItems()
{
var predicate = PredicateBuilder.New<WalletItem>();
var ids = new string[] { "A", "B" };
foreach (var id in ids)
{
predicate = predicate.Or(wi => wi.ExternalId == id);
}
return predicate;
}
When hitting ToListAsync() the following exception:
System.NotSupportedException: 'Could not parse expression 'w.WalletItems.Any(__Compile_0)': The given arguments did not match the expected arguments: Object of type 'System.Linq.Expressions.TypedParameterExpression' cannot be converted to type 'System.Linq.Expressions.LambdaExpression'.'
I am running the code in an ASP.NET Core 2.1 application (netcoreapp2.1) using the following packages:
Microsoft.EntityFrameworkCore.Relational (2.1.1)
Microsoft.EntityFrameworkCore.SqlServer (2.1.1)
LinqKit.Microsoft.EntityFrameworkCore (1.1.15)
Any help much appreciated.
What you are missing in the examples is the fact that all Expression<Func<..>> are either parameters or local variables. While the line
where w.WalletItems.Any(hasItems().Compile())
is not actually calling the hasItems method, but emits a MethodCallExpression (i.e. Expression.Call) to it inside the query expression tree, which is different type of expression not recognized by LINQKit Expand implementation, thus leading to unsupported expression by EF Core.
The solution is to put the method call result into a local variable and use that variable inside the query expression tree:
var hasItemsExpr = hasItems();
var query =
from w in _context.Wallets.AsExpandable()
where w.WalletItems.Any(hasItemsExpr.Compile())
select w;

Expressions with dynamic return types (dynamic keyword)

My ultimate goal here is to make a generic version of IQueryable<T>.OrderBy() that takes a string parameter and an optional sort direction. Something like these:
return myList.OrderBy("Property1");
return myList.Orderby("Property1", SortOrder.Descending);
(The use case would be a website passing in a field the list would sort by.)
To that end, I've been trying to come up with a way of creating the following expression:
obj => obj.PropertyName
I've found a few places in StackOverflow that could help me, and they've gotten me quite close (this one in particular). Butt it doesn't quite get me all the way there. Specifically I keep getting the dreaded
Expression of type 'System.Int64' cannot be used for return type 'System.Object' for value types. I thought I could get away with return dynamic here, but that seems to have fallen over. I could do a Convert, but that seems like it should be unnecessary.
My code for generating the property selector is as follows:
public static Expression<Func<T, dynamic>> GeneratePropertySelector<T>(string propertyName)
{
var objectType = typeof(T);
var property = objectType.GetProperty(propertyName);
ParameterExpression arg = Expression.Parameter(objectType, "obj");
MemberExpression propertyExpression = Expression.Property(arg, propertyName);
// Here is the line that dies
var selectorExpression = Expression.Lambda<Func<T, dynamic>>(propertyExpression, new ParameterExpression[] { arg });
return selectorExpression;
}
And then usage inside the extension method implementation would be:
var ordered = myList.OrderBy(GeneratePropertySelector("Property1"));
For a string property, this works fine; for an int property, error.
Does anyone know how to get around this? I would have thought that dynamic would have helped here, but I'm at a loss. And given my use case, I'm trying to avoid something like this:
return myList.Orderby<int>("MyIntProperty");

Runtime errors might occur when converting lambda expression to parameter type system.linq.expressions

I have the following method:
public IEnumerable<OrderLines> RetrieveOrderLines(Expression<Func<OrderLines,
bool>> expression)
{
return _context.OrderLines.Where(expression);
}
This method is used from a test project (C#):
var testLine = repo.RetrieveOrderLines(x => x.I_ID == 1
&& x.T_ID == 2).Single();
And our production project which is VB.Net also accesses this method like this:
Dim line As OrderLines = repo.RetrieveConsumptionLines(Function(x) x.I_ID = InvId
And x.T_ID = tId).Single()
The C# test is working fine, I am not getting any error or warning, but the line in VB is highlighted and re-sharper is giving me the following warning:
runtime errors might occur when converting lambda expression to parameter
type system.linq.expressions.expression(Of System.Func(Of OrderLines, Boolean))
any idea why and is there are solution or a better way of doing this? I am new to Lambda expressions so any advice is appreciated.
Thanks.

Best and shortest way to evaluate mathematical expressions

There are many algorithms to evaluate expressions, for example:
By Recursive Descent
Shunting-yard algorithm
Reverse Polish notation
Is there any way to evaluate any mathematical expression using C# .net reflection or other modern .net technology?
Further to Thomas's answer, it's actually possible to access the (deprecated) JScript libraries directly from C#, which means you can use the equivalent of JScript's eval function.
using Microsoft.JScript; // needs a reference to Microsoft.JScript.dll
using Microsoft.JScript.Vsa; // needs a reference to Microsoft.Vsa.dll
// ...
string expr = "7 + (5 * 4)";
Console.WriteLine(JScriptEval(expr)); // displays 27
// ...
public static double JScriptEval(string expr)
{
// error checking etc removed for brevity
return double.Parse(Eval.JScriptEvaluate(expr, _engine).ToString());
}
private static readonly VsaEngine _engine = VsaEngine.CreateEngine();
It's certainly possible. The CodeSnippetCompileUnit class does basically this.
I wrote you some example usage code. You'll need to include these namespaces:
System.CodeDom.Compiler;
System.CodeDom;
Microsoft.CSharp;
System.Reflection;
Here's the code:
string source = #"
class MyType
{
public static int Evaluate(<!parameters!>)
{
return <!expression!>;
}
}
";
string parameters = "int a, int b, int c";
string expression = "a + b * c";
string finalSource = source.Replace("<!parameters!>", parameters).Replace("<!expression!>", expression);
CodeSnippetCompileUnit compileUnit = new CodeSnippetCompileUnit(finalSource);
CodeDomProvider provider = new CSharpCodeProvider();
CompilerParameters parameters = new CompilerParameters();
CompilerResults results = provider.CompileAssemblyFromDom(parameters, compileUnit);
Type type = results.CompiledAssembly.GetType("MyType");
MethodInfo method = type.GetMethod("Evaluate");
// The first parameter is the instance to invoke the method on. Because our Evaluate method is static, we pass null.
int result = (int)method.Invoke(null, new object[] { 4, -3, 2 });
Replace 'parameters' and 'expression' by whatever, and you've got yourself a general expression evaluator.
If you get a FileNotFoundException in results.CompiledAssembly, then the snippet failed to compile.
You might also want to take a look at the System.CodeDom.CodeSnippetExpression class. It's used for more specifically reading expressions, but an expression by itself can't be compiled, so you would need to use more CodeDom to build a working class and method around it. This is useful if you want to be able to programmatically manipulate what kind of class you're generating. CodeSnippetCompileUnit is nice to generate an entire working class at once (and simpler for an example) but to manipulate it you would have to do inconvenient string manipulations.
Although using compiler services is a simple and efficient solution, it raises serious security issues if the expression is entered by a user, because it could execute virtually anything.
There's another very simple solution that is much more secure : take advantage of the JScript Eval function. You just need to follow these steps :
Create a js file named JsMath.js :
class JsMath
{
static function Eval(expression : String) : double
{
return eval(expression);
};
}
Compile it into a class library :
jsc /t:library JsMath.js
Reference the JsMath library in your C# project, and use it like that :
double result = JsMath.Eval(expression);
For me Vici.Parser works extremely well: check it out here , it's the most flexible expression parser I've found so far.
(we've used it to set up 'human-readable' business rules, with data provided by an SQL server database)
Examples are available and there's a very good support by the developer (check the website's forum).
ncalc is the best. you can find it in codeplex also in nugget.
NCalc is a mathematical expressions evaluator in .NET. NCalc can parse any expression and evaluate the result, including static or dynamic parameters and custom functions.
I think this is the best way of all. Petar Repac's answer is amazing.
Using the 'expression' argument of the DataColumn object solves incredibly and easily the topic:
static double Evaluate(string expression)
{
var loDataTable = new DataTable();
var loDataColumn = new DataColumn("Eval", typeof(double), expression);
loDataTable.Columns.Add(loDataColumn);
loDataTable.Rows.Add(0);
return (double)(loDataTable.Rows[0]["Eval"]);
}
You can use Math-Expression-Evaluator library which implements Shunting Yard algorithm that I am author of. It supports simple expressions such as 2.5+5.9, 17.89-2.47+7.16, 5/2/2+1.5*3+4.58, expressions with parentheses (((9-6/2)*2-4)/2-6-1)/(2+24/(2+4)) and expressions with variables:
var a = 6;
var b = 4.32m;
var c = 24.15m;
var engine = new ExpressionEvaluator();
engine.Evaluate("(((9-a/2)*2-b)/2-a-1)/(2+c/(2+4))", new { a, b, c});
You can also pass parameters as named variables:
dynamic dynamicEngine = new ExpressionEvaluator();
var a = 6;
var b = 4.5m;
var c = 2.6m;
dynamicEngine.Evaluate("(c+b)*a", a: 6, b: 4.5, c: 2.6);
It supports .Net Standard 2.0 so can be used from .Net Core as well as .Net Full Framework projects and it doesn't have any external dependencies.
To dynamically compile code using the new Roslyn API's, and load the assembly in a .net core project;
string finalSource = ...;
IEnumerable<Assembly> references = ...;
var compilation = CSharpCompilation.Create("Dynamic",
new[] {
SyntaxFactory.ParseSyntaxTree(
finalSource,
CSharpParseOptions.Default
.WithLanguageVersion(LanguageVersion.Latest)
) },
references.Select(a => MetadataReference.CreateFromFile(a.Location)),
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
.WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default)
);
using var ms = new MemoryStream();
var e = compilation.Emit(ms);
if (!e.Success)
throw new Exception("Compilation failed");
ms.Seek(0, SeekOrigin.Begin);
var context = new AssemblyLoadContext(null, true);
var assembly = context.LoadFromStream(ms);
Note that along with any other types required by the source you are compiling. In order to load the compiled assembly within the same process, references will need to include;
AppDomain.CurrentDomain.GetAssemblies().Where(a => a.GetName().Name == "netstandard").Single(),
typeof(object).Assembly

Categories