C# lambda convert - c#

Hello I am trying to create a filter-system for list's.
public void filter<T, E>(String fieldName, List<T> list, Func<T, E> rule)
{
IList<FilterDto> filters = GetFilter(fieldName);
foreach (FilterDto filter in filters)
{
if (filter != null)
{
if (filter.valueType == ValueType.NUMERIC)
{
list.Remove( this.filter(fieldName, Convert.ToDouble( o => rule(o) ) ) );
}
else if (filter.valueType == ValueType.DATE)
{
}
else if (filter.valueType == ValueType.TEXT)
{
}
else
{
Log("Unkown filter comparsion");
}
}
}
}
On this line:
list.Remove( this.filter(fieldName, Convert.ToDouble( o => rule(o) ) ) );
I get the error message:
Error CS1660: Cannot convert lambda expression to type 'bool' because it is not a delegate type
I have would do the real filtering on the methods something like that:
public bool filter(String fieldName, double? value)
public bool filter(String fieldName, int? value)
public bool filter(String fieldName, Date? value)

The bottom line is no overload of Convert.ToDouble() takes a lambda expression as an argument. The compiler is basically picking one of the overloads -- in this case the one that takes a bool -- and telling you it can't convert the lambda into a bool.
Are you trying to pass the return value from rule() to be converted? If so, just call rule() itself, and pass it whatever var you need to pass it (unclear from your question):
list.Remove( this.filter(fieldName, Convert.ToDouble(rule(yourVar))));

What you do does not make much sense. In your comedy (or tragedy - you choose) you have the following actors:
An IList<FilterDto>, the container of your filter objects.
The filter method who keeps everyone together.
A filter local variable who owes his existance to (1) and holds a grudge against (2), because it has the same name.
The Convert.ToDouble method who is a bit of a diva because it won't just accept anyone as its parameter's argument.
The Remove method, son of (1).
The o => rule(o) lambda expression.
Enter the IList (1). You iterate over it and create the filter (3) variable. Now comes the Remove method (5) which you call, probably to remove said filter (3), which you don't actually do; instead you remove the result of the filter method (2), which is unfortunate, because filter (2) does not have a result (alas it is void). However, filter(2) wants a Func<T, E> as its second argument (although not necessarily the same T and E as the original call to filter - the method). In comes the evil ToDouble (4), which has a result of double, which is not a Func<T, E> - hence your error. To make things worse, a o => rule(o) (6) makes its way into ToDouble's (4) argument list. This now is a Func<T, E>, although ToDouble (4) won't be able to do much with it, because even if it tries hard, it can't convert it into a double.
Now how to we cut this Gordian Knot?
Well, as I see it you might want to remove an item from the IList (1) in case a subsequent call to your filter rule is successful. My best guess (it has to be a guess because your question is not quite clear there) is that you intent something close to this:
T[] itemsToRemove = list.Where( o => rule(Convert.ToDouble(o)) ).ToArray();
foreach (T item in itemsToRemove) {
list.Remove(item);
}

I found my mistake... I have to use RemoveAll.
Like that:
list.RemoveAll(o => this.filter(filter, Convert.ToDouble((rule(o) as Double?))));

Related

Utilizing Funcs within expressions?

Background
I have an example of a test that passes but an error that happens down the pipeline and I'm not sure why. I'd like to figure out what's going on but I'm new to Expression construction and don't want to make any assumptions.
This is for a search filtering mechanism. It uses ServiceStack's PredicateBuilder implementation. I essentially have a list of values that I pass in, and I want it to construct an expression tree. I had previously done this just with Func<T<bool>> but realized that I needed to wind up with Expression<Func<T<bool>>>. Bummer.
The Goal
Search filters built from Re-usable search filter types, which built out of Funcs and Expressions that allows me to pass in a field name from an object along with values I should match on and wind up with something that we can run a Where() statement against.
The Code / Issue
The generic "nullable bool" filter I'm trying -- sets up the acceptable items and returns a func that is meant to help filter:
public class NullableBoolFilter : IGenericSearchFilter<bool?>
{
public Func<bool?, bool> GetFilterFunc(string valuesToProcess)
{
var acceptableValues = new List<bool?>();
if (string.IsNullOrWhiteSpace(valuesToProcess))
{
// all values acceptable
acceptableValues = new List<bool?>{true, false, null};
}
else
{
if (!valuesToProcess.Contains("0") && !valuesToProcess.Contains("1"))
{
throw new ArgumentException("Invalid Nullable boolean filter attribute specified");
}
if (valuesToProcess.Contains("0"))
{
acceptableValues.Add(false);
}
if (valuesToProcess.Contains("1"))
{
acceptableValues.Add(true);
}
}
Func<bool?, bool> returnFunc = delegate(bool? item) { return acceptableValues.Any(x=>x == item); };
return returnFunc;
}
}
Then I have another filter, which inherits from the NullableBoolFilter and attempts to use the Func:
public class ClaimsReportIsMDLFilter : NullableBoolFilter, ISearchFilter<vSEARCH_ClaimsReport>
{
public Expression<Func<vSEARCH_ClaimsReport, bool>> GetExpression(string valuesToProcess)
{
var theFunc = base.GetFilterFunc(valuesToProcess);
Expression<Func<vSEARCH_ClaimsReport, bool>> mdlMatches = item => theFunc(item.IsMDL);
var predicate = PredicateBuilder.False<vSEARCH_ClaimsReport>();
predicate = predicate.Or(mdlMatches);
return predicate;
}
}
The following test passes:
public class ClaimsReportIsMDLFilterTests
{
// ReSharper disable InconsistentNaming
private readonly vSEARCH_ClaimsReport ItemWithMDL = new vSEARCH_ClaimsReport { IsMDL = true };
private readonly vSEARCH_ClaimsReport ItemWithoutMDL = new vSEARCH_ClaimsReport { IsMDL = false };
private readonly vSEARCH_ClaimsReport ItemWithNullMDL = new vSEARCH_ClaimsReport { IsMDL = null };
// ReSharper restore InconsistentNaming
[Fact]
public void WithSearchValueOf1_HidesNonMDLAndNull()
{
var sut = this.GetCompiledExpressionForValues("1");
sut.Invoke(ItemWithMDL).Should().BeTrue();
sut.Invoke(ItemWithoutMDL).Should().BeFalse();
sut.Invoke(ItemWithNullMDL).Should().BeFalse();
}
private Func<vSEARCH_ClaimsReport, bool> GetCompiledExpressionForValues(string searchValue)
{
return new ClaimsReportIsMDLFilter().GetExpression(searchValue).Compile();
}
}
The Problem
When I actually attempt to run this, I receive the error:
variable 'param' of type 'vSEARCH_ClaimsReport' referenced from scope '', but it is not defined
It makes sense to me why this might occur -- at the time it's evaluated, I don't have a real object to pass into the Func. However, I'm confused as to why my tests might pass but this doesn't in actual usage.
Questions
Why might my tests pass but I still receive this error?
How the heck should I begin trying to fix this?
Is there a remotely easy way to take that Func and turn it into an Expression that I can pass a field into?
Do I need to abandon the generic filter idea and have each class manually add expressions to the PredicateBuilder based on input passed in? That's doable, but it seems like the work could be reduced more.
Why might my tests pass [...]
Because your test is simply compiling the expression down into the code that it represents and invoking it. It doesn't need to actually parse the expression tree and look at what the code it represents is doing, it just runs it and ensures that the output is right.
Why might [...] I still receive this error?
Because when you're actually using it, it's not just executing the code; rather it is looking through the expression tree to try to determine what the code is doing so that it can be translated into something else, not so that it can be run as C# code.
Your expression is doing nothing but calling a delegate. There is no way for someone traversing the expression tree to see inside the delegate and know what it's doing. Knowing that you're calling another method isn't something that can be translated into another language.
How the heck should I begin trying to fix this?
You need to generate an Expression from the start, rather than generating a Func and then just creating an Expression that calls it.
Is there a remotely easy way to take that Func and turn it into an Expression that I can pass a field into?
No. You'd need to pull out the IL code of the function, decompile that into C# code, then build up Expression objects to represent that code. That's pretty much just not going to happen.
You're pretty much going to need to have GetFilterFunc return an Expression, to get this to work. Fortunately, this is quite easy to do, given what you have. You simply need to change the method signature and to replace the last two lines with the following:
return item => acceptableValues.Any(x => x == item);
And voila. The lambda can be compiled into an Expression object, rather than a delegate, based on context, so if the return type of the method is an Expression<Func<bool?,bool>> that's what you'll get.
Now, to use this in GetExpression. First off, the PredicateBuilder isn't really doing anything. Adding an OR FALSE to your expression changes nothing meaningful about it. All of that can go. All that leaves us with is using an Expression<Func<bool?,bool>> and changing it into an Expression<Func<vSEARCH_ClaimsReport, bool>> by pulling out a boolean property. To do this is a bit more work for expressions than for delegates. Rather than just invoking the expression, we need to do a tad more work to compose them. We'll want to write a method to do this operation:
public static Expression<Func<TFirstParam, TResult>>
Compose<TFirstParam, TIntermediate, TResult>(
this Expression<Func<TFirstParam, TIntermediate>> first,
Expression<Func<TIntermediate, TResult>> second)
{
var param = Expression.Parameter(typeof(TFirstParam), "param");
var newFirst = first.Body.Replace(first.Parameters[0], param);
var newSecond = second.Body.Replace(second.Parameters[0], newFirst);
return Expression.Lambda<Func<TFirstParam, TResult>>(newSecond, param);
}
And this relies on the use of the following method to replace all instances of one expression with another:
public static Expression Replace(this Expression expression,
Expression searchEx, Expression replaceEx)
{
return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
}
internal class ReplaceVisitor : ExpressionVisitor
{
private readonly Expression from, to;
public ReplaceVisitor(Expression from, Expression to)
{
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node)
{
return node == from ? to : base.Visit(node);
}
}
What this is doing is replacing all instances of the second expression's parameter with the body of the first expression, effectively inlining that expression into the second. The rest is simply replacing all of the parameters with a new single parameter and wrapping it back up into a lambda.
Now that we have that, our method is quite easy:
public Expression<Func<vSEARCH_ClaimsReport, bool>> GetExpression(
string valuesToProcess)
{
Expression<Func<vSEARCH_ClaimsReport, bool?>> selector =
item => item.IsMDL;
return selector.Compose(base.GetFilterFunc(valuesToProcess));
}

Get actual return type from a Expression<Func<T, object>> instance

I have a method that accepts a Expression<Func<T, object>> instance. I want to get at the actual data type being returned by a specific expression instance, rather than object.
I can get it to work for direct property references, so if I pass in the expression x => x.IntegerProperty I can get a Type reference for an integer. This approach requires converting it to a MemberExpression.
However, I can't get it to work for arbitrary expressions. For instance, if the expression is x => x.IntegerProperty.ToString() I want to get a Type reference for a string. I can't compile this to a MemberExpression, and if I just .Compile() it and check the return type I get "object".
How can I look at the specific expression instance and derive the actual return type?
Something like this might do the trick. It probably doesn't cover every possibility, but it's a start.
public static Type GetObjectType<T>(Expression<Func<T, object>> expr)
{
if ((expr.Body.NodeType == ExpressionType.Convert) ||
(expr.Body.NodeType == ExpressionType.ConvertChecked))
{
var unary = expr.Body as UnaryExpression;
if (unary != null)
return unary.Operand.Type;
}
return expr.Body.Type;
}
While not impossible, this is particularly difficult. It would require walking the expression tree and doing some potentially complex logic. For example, what would you want to see if I passed in the following expression?
Func<bool, object> expr = switch => switch ? 1 : "False";
This method could either return an int or a string.
Now, you might be able to make more headway by offloading some of this logic on the compiler. You could change your method parameter from Func<T, object> to Func<T, TReturn> and use typeof(TReturn) within the method to determine what the compiler decided the return type of the expression was.
Of course, in the case of my example, you'll still be working against object. But, your example of x => x.IntegerProperty.ToString() will yield string, which is what you're looking for.
Bit of a cheeky way (and it involves actually invoking the Func), but you can do this:
using System;
class Program
{
static Func<T,object> MakeFunc<T>()
{
return x => 23;
}
static Type GetReturnType<T>(Func<T,object> f)
{
return f(default(T)).GetType();
}
static void Main(string[] args)
{
Type t = GetReturnType(MakeFunc<string>());
Console.WriteLine(t);
}
}
It's not guaranteed to work in all situations, I should add - particularly if the default(T) isn't a valid parameter to the Func. But it's a potential starting point at least.

How to get the string (of source-code) that generated a lambda-expression?

(for LISP hackers in short: I'm looking for the LISP-quote equivalent in C#)
I'm trying to write a meaningful ToString-method for a class which has a Func as member. Experiened API-users can set this member via setter-method like
myClassObject.SetFunction( (x) => x*x );
Now, when I use the ToString-method on the member it only returns
System.Func<double,double>
which is not very helpful. What would be helpful is
"(x) => x*X"
Is there any (preferable easy) way to do that?
Thanks for any help or comments.
Edit: corrected some typos
Expression<Func<double,double>> expr = x => x * x;
string s = expr.ToString(); // "x => (x * x)"
If you're willing to store your delegate as an expression, you can achieve what you want. The code would look something like this:
private Expression<Func<double, double>> myFunc;
private Func<double, double> cachedDelegate;
public void SetFunc(Expression<Func<double,double>> newFunc)
{
this.myFunc = newFunc;
this.cachedDelegate = null;
}
public double ExecFunc(double x)
{
if (this.myFunc != null)
{
if (this.cachedDelegate != null)
{
return this.cachedDelegate(x);
}
else
{
this.cachedDelegate = this.myFunc.Compile();
return this.cachedDelegate(x);
}
}
return 0.0;
}
public string GetFuncText()
{
if (this.myFunc != null)
{
return this.myFunc.ToString();
}
return "";
}
In order to actually use the lambda expression, you have to compile it first. Storing it in a delegate means you only take that hit once.
Also, this approach means that users have to use a lambda, since method groups aren't convertible to Expression<Func<>>. That's not a huge concern, though, since instead of passing MyMethod, a user could pass x => MyMethod(x).
The calling code would look something like this:
myObject.SetFunc(x => 2*x);
Console.WriteLine(myObject.GetFuncText());
One final note is that the above sample is not thread-safe, so if you expect to have the methods called from multiple threads, some sort of synchronization would be appropriate.
None that I know of since that string has never entered the system, only IL was somehow generated and stored with a reference... you would need to "decompile" the IL to some meaningful string...
With CodeExpression there is possibility to call GenerateCodeFromExpression via an instance of CodeDomProvider which has built-in implementations for C# / VB / JScript... but I would be surprised if that met your needs...
Another option: With Expression you could use ToString() - this works with LambdaExpression too since that is just a descendant.

Getting the values of method parameters inside expression trees

I'm messing around with expression trees, but I'm little stuck.
I have this expression:
Expression<Func<IX, int>> expr = i => i.GetAll(1, b, method());
Where :
int b = 2;
public static int method()
{
return 3;
}
public interface IX
{
int GetAll(int a, int b, int c);
}
Now I want to get name of the method and values of parameters for this method. Name of the method is easy, but parameter values are harder part. I know I can parse them myself, but I would need to handle all cases (ConstantExpression, MemberExpression, MethodCallExpression and maybe more I'm not aware of). So I was thinking if there was "general" way to get their values. eg 1, 2, 3.
You can get the arguments of the MethodCallExpression in question
and create compiled Func<object>s from them (boxing value-types if necessary), which can then be evaluated.
E.g.:
var args = from arg in ((MethodCallExpression)expr.Body).Arguments
let argAsObj = Expression.Convert(arg, typeof(object))
select Expression.Lambda<Func<object>>(argAsObj, null)
.Compile()();
This will obviously blow up if the expression's body is not a method-call expression or if any of the arguments to the method cannot be evaluated as is (e.g. if they depend on the argument to the expression).
Obviously, you can do a better job if you know the types of the arguments to the method beforehand. For your specific example, this should work:
var args = from arg in ((MethodCallExpression)expr.Body).Arguments
select Expression.Lambda<Func<int>>(arg, null)
.Compile()();
Can you not just get all the parameters and then compile and execute them? I don't see how it would be possible to get all the values without executing if they can be method calls.

Particulars about Action delegate in C#

1) What is the real definition for Action delegate? some definitions describe it is as polymorphic conditional map , some say it *Applied decision Table *.
(You may ask what will you achieve by knowing definition , if i know it i can understand its real purpose).
2) Thanks Binary Worrier,Andrew Hare of stackoverflow for giving nice examples.
When i declare
string[] words = "This is as easy as it looks".Split(' ');
`Array.ForEach(words, p => Console.WriteLine(p));`
i can understand what it actually does.But when i declare ,How does C# interpret when i
declare
Dictionary<SomeEnum, Action<User>> methodList =
new Dictionary<SomeEnum, Action<User>>()
methodList.Add(SomeEnum.One, DoSomething);
methodList.Add(SomeEnum.Two, DoSomethingElse);
Does it store collections of Actions in dictionary ?.unfortunately as the example was incomplete i did not get it.
3) What is the functional difference between Action , Function ,Predicate delagets?
It's just another delegate. Action<T> is declared like this:
void Action<T>(T item)
It's just "something which acts on a single item". There are generic overloads with more type parameters and normal parameters. In itself, an Action<T> isn't an applied decision table or anything like that - it's just a delegate which can do "something" with an item.
The dictionary example is just a dictionary with enum values as keys, and actions as values - so you can look up what to do based on the enum value, and then pass in a User reference for it to act on.
As for Func vs Action vs Predicate: Func is like Action, but returning a value. Predicate is similar, but always returns bool, and there aren't the range of generic overloads, just Predicate<T> to determine if an item "matches" the predicate.
Action, Func and Predicate have different signatures:
void Action<...>(...)
T Func<..., T>(...)
bool Predicate<T>(T)
Action<...> is the same as Func<..., void>
Predicate<T> is the same as Func<T, bool>
1) the Action delegates
(Action, Action<T>, Action<T, T2> ...)
are general purpose delegate to avoid the creation of to many delegate in your application. The idea is :
//- Action => void method with 0 args
//- Action<T> => void method with 1 arg of type T
//- Action<T, T2> => void method with 2 args of type T et T2
//...
2) that dictionary stores for each 'SomeEnum' values, a method wicth match this signature :
void MethodExample (User arg);
Here is an example :
public Init() {
deleteUserMethodsByStatus = new Dictionary<SomeEnum, Action<User>>();
deleteUserMethodsByStatus.Add(UserStatus.Active, user => { throw new BusinessException("Cannot delete an active user."); });
deleteUserMethodsByStatus.Add(UserStatus.InActive, DoUserDeletion});
}
//This is how you could use this dictionary
public void DeleteUser(int userId) {
User u = DaoFactory.User.GetById(userId);
deleteUserMethodsByStatus[u.Status](u);
}
//the actual deletion process
protected internal DoUserDeletion(User u) {
DaoFactory.User.Delete(u);
}
3) Difference between Action , Function ,Predicate :
- an action is a void method(no return value)
- a function is a non void method (has a return value)
- a predicate must return a boolean value and take 1 argument (it basically answere yes or no to question that take 1 argument)
I hope this help.

Categories