Mutating the expression tree of a predicate to target another type
It seems you're generating the parameter expression twice, in VisitMember() here:
var converted = Expression.MakeMemberAccess(
base.Visit(node.Expression),
activeRecordType.GetProperty(node.Member.Name));
...since base.Visit() will end up in VisitParameter I imagine, and in GetMany() itself:
var lambda = Expression.Lambda<Func<ActiveRecord.Widget, bool>>(
visitor.Visit(predicate.Body),
predicate.Parameters.Select(p => visitor.Visit(p));
If you're using a ParameterExpression in the body, it has to be the same instance (not just the same type and name) as the one declared for the Lambda.
I've had problems before with this kind of scenario, though I think the result was that I just wasn't able to create the expression, it would just throw an exception. In any case you might try reusing the parameter instance see if it helps.
Unit test for Expression tree in c#
This shall be simple, though I will use the Expression<Func<SpecFinderDataModel,bool>>
instead of LinqKit APIs, which is used internally, In the DoSearch
method, you need Expression<Func<SpecFinderDataModel,bool>>
as input, based on the method assuming following as the definition of the type SpecFinderDataModel
public class SpecFinderDataModel
{
public string ProductID {get; set;}
public string ISBN13 {get; set;}
public string Title {get; set;}
}
Now you need to simply test various options, as done in regular unit test, a sample:
// Initial Expression value constant false is the result
Expression<Func<SpecFinderDataModel, bool>> expr = c => false;
// SpecFinderDataModel Object
var sfd = new SpecFinderDataModel
{
ISBN13 = "",
ProductID = "Test A B C",
Title = ""
}
// Call DoSearch and supply the sfd for testing
var result = DoSearch(false,"Test",expr).Compile()(sfd);
// Assert the result in the unit test to understand
Assert.True(result,true);
Like this based on combinations of the DoSearch
parameters and test object sfd
, you can create any number of unit test cases to test your code
Expression vs Predicate issues
The delegates have different types:
public delegate bool Predicate<T>(T obj);
public delegate TResult Func<T, TResult>(T arg);
The Exists
method (and the Find
) expect Predicate<T>
. The Lambda expression compiles at runtime to Func<T, TResult>
.
Try the following:
var existsLambda = Expression.Lambda(typeof(Predicate<string>),
Expression.Equal(
Expression.Parameter(typeof(string), "s"),
Expression.Constant("cookie")),
Expression.Parameter(typeof(string), "s"));
You can also use the generic Lambda Function:
var existsLambda = Expression.Lambda<Predicate<string>>(Expression.Equal(
Expression.Parameter(typeof(string), "s"),
Expression.Constant("cookie")),
Expression.Parameter(typeof(string), "s"));
Related Topics
Read and Write File on Streamingassetspath
Asp.Net-Mvc: Razor '@' Symbol in Js File
Difference Between Namespace in C# and Package in Java
How Does MVC 4 List Model Binding Work
Variable Declaration in a C# Switch Statement
Standardoutput.Readtoend() Hangs
How to Encrypt Selected Properties When Serializing My Objects
Passing Dynamic Object to C# Method Changes Return Type
ASP.NET Core Return JSON with Status Code
Adding Distance to a Gps Coordinate
Invoke C# Code from JavaScript in a Document in a Webbrowser
Stroke Width Transform (Swt) Implementation (Java, C#...)
Send Email Using System.Net.Mail Through Gmail
Auto-Implemented Getters and Setters VS. Public Fields
How to Use .Net Reflection to Check for Nullable Reference Type
How to Implement Url Rewriting Similar to So
Entity Framework/Linq Expression Converting from String to Int