WPF purpose of `(arg) => true)` - c#

While reading this tutorial on Command Binding in DataTemplate, I saw this:
public DelegateCommand<string> AddBrand
{
get
{
return this.addBrand ?? (this.addBrand = new DelegateCommand<string>( this.ExecuteAddBrand, (arg) => true));
}
}
which is a function inside BrandsViewModel.cs to add a Brand. I have questions about the line below:
this.addBrand = new DelegateCommand<string>( this.ExecuteAddBrand, (arg) => true));
My understanding is that AddBrand is a command registered to the Add Brand button in the View, and this adds a delegate method to be called upon the click of the button. Specifically, this.ExecuteAddBrand is the method to be executed. However, what is the purpose of (arg) => true)? What does it even mean? Thanks!

The operator => is used when we want to write a lambda expression.
You can think it of as a normal method, where the things left to => are the parameters (the input) of the method and the thing right the => is that the method returns (output).
For instance
x=>x*x
If we input 3, we will get as output 9.
Lambda expressions are really usefull in LINQ.
For instance, say that we have a collection called customers of objects of type Customer, whose defintion is the following one:
public class Customer
{
public string FirstName {get; set; }
public string LastName {get; set; }
public int Age {get; set;}
}
Let then that we want to get the customers that have age greater than 18. Then we could do this like below:
var adults = from customer in customers
where customer.Age>18
select customer;
However, we could get also the same result, as below:
var adults = customers.Where(x => x.Age>18);
In the latter case, we pass in the Where method a lambda expression.
what is the purpose of (arg) => true)? What does it even mean?
Now in your case the above lambda accepts an argument called arg and always returns true.

That is a lambda that represents a method (or expression) that accepts one argument and always returns true regardless of the input. "Given string arg, return true".
Perhaps a clearer example is on a list:
var names = List<string>(...); // populate, etc
var containsA = names.FindAll(x => x.Contains("A"));
In the above, I'm using a lambda to express a "predicate" - essentially a filter condition; for any name, it returns true if the name contains an A. FindAll returns all the items that match the predicate. We could also do:
var everybody = names.FindAll(x => true);
var nobody = names.FindAll(x => false);
(although that is obviously a bit silly)
More specific to DelegateCommand: basically, the second parameter is canExecuteMethod, and it is basically saying "yes, it can always execute, regardless of the value". In the more general case, this can act as a filter on when it is/isn't appropriate to use the method. The canExecuteMethod parameter can also be omitted or passed as null, if that would be clearer.

Related

Access property of a generic type inside lambda expression

The title may be ambiguous, but let me explain.
I am working with MongoDb and with the c# driver for MongoDb, we can create a FilterDefinition<T> to create a filter to fetch data as follows :
var Filter = Builders<TestClass>.Filter.Eq(x => x.AnyProperty, Value);
I am trying to put this code inside a reusable generic method, so that i don't end up writing the same code again and again. I won't be including the entire function here, but inside the function, i am trying to do something as follows :
var Filter = Builders<T>.FIlter.Eq(x => x.AnyProperty, value);
Now the drawbacks are :
T is a generic type, meaning it doesn't have the property i am looking for. So, i try to get the type of T and get the property that i am looking for by name, as follows :
...FIlter.Eq(x => x.GetType().GetProperty(PropertyName), value)
This results in an exception :
Unable to determine the serialization information for x => x.GetType().GetProperty("UserName"). // UserName is the property name
So, my question is, what can i do here for the generic type, which would be equivalent of x => x.PropertyName inside the lambda expression ?
Update
Forgot to mention, i did try this :
var Filter = Builders<T>.FIlter.Eq("PropertName", value);
But it doesn't return the results from the database, where as this does :
var Filter = Builders<MyClass>.FIlter.Eq("PropertName", value);
I really wonder why!
Update 2
Definition of Filter.Eq is as follows :
public FilterDefinition<TDocument> Eq<TField>(FieldDefinition<TDocument, TField> field, TField value);
In the code
FIlter.Eq(x => x.GetType().GetProperty(PropertyName), value), my undersatnding is that Mongo driver is expecting an Expression, which is automatically created when you use the Metadata like in original case x => x.AnyProperty
In this case you need to explicitly supply MemberExpressionas follows
var parameterExpression = Expression.Parameter(typeof(T),"x");
var memberAccessExpression = Expression.MakeMemberAccess(parameterExpression, typeof(T).GetProperty("AnyProperty"));
Now you can supply to the FIlter.Eq value memberAccessExpression, in this case it will fail at run-time, if the AnyProperty is not part of type T, since its verified at the run-time.
In ExpressionTrees, this is the replacement of the x => x.AnyProperty
Edit 1:
Reviewing the Mongo DB Driver documents, following are the important details on the Definitions and Builders, there's an example as follows:
var builder = Builders<Widget>.Filter;
var filter = builder.Eq(widget => widget.X, 10) & builder.Lt(widget => widget.Y, 20);
Following is the definition of the FilterDefinitionBuilder.Eq, which expose the Eq and various other filters:
public FilterDefinition<TDocument> Eq<TField>(Expression<Func<TDocument, TField>> field,TField value)
In this case, we need a generic type TDocument, which is the main class and TField, which is the type of the field on which filter is applied, therefore code in your case would be:
var builder = Builders<T>.Filter;
// Use makeMemberAccessExpression created above
var filter = builder.Eq(Expression.Lambda<Func<T,string>>(makeMemberAccessExpression), "<stringValue>");
Important points:
As it can be seen in the Mongo documentation, we have 2 generic types, TDocument and TField, here you are working with just one, so with the above code it will be restricted to string as type for TField, until and unless you make that also generic, which is your choice, otherwise all your fields shall be of specific type that you supply, which is string in this case
More important is the value shall be of type TField that you supply else it will not work and will fail at compile time
There's another overload, Eq<TField>(FieldDefinition<TDocument, TField>, TField), which would work in a similar way, but since it expects FieldDefinition<TDocument, TField>, we need to supply the Expression<Func<TDocument,TField>> as part of the class, both overloads translates into similar code

Combine property selector expression tree and value to create a predicate for EF filtering - create filter from lambda selector and value

Given a simple class with arbitrary properties (for discussion lets say Id, Name, and Description)
and given an instance of that class, I want to find matching entries in the database by specifying the property to match
I'm trying to do something in this respect similar to the AddOrUpdate method of EF, but I need the entity returned to me for further processing.
var match = new SomeClass{Name="Whatever"};
var found = Context.SomeClass.Find(x=>x.Name, match);
public static T Find<T>(this DbSet<T> set, Expression<Func<T, object>> matchOn, T matchAgainst) where T : class {
var func = matchOn.Compile();
var valueToFind = func(matchAgainst);
var combinedExpression = //matchon + "=" + valueToFind;
var found = set.FirstOrDefault(combinedExpression);
return found;
}
That gives me the value of the property in the passed in object, but I need to now combine that value with the passed in expression and pass it to the db set.
IE, the code I'm effectively trying to run is set.FirstOrDefault(x=>x.Name==valueToFind) How do I take the matchon expression (which contains x=>x.Name) and combine that with the ==valueToFind to get the x=>x.Name==valueToFind from them?
How do I build the combined expression? (I realize the "string" code above is completely wrong, but I was trying to get across what I need the function to do, but I have no idea what that syntax would look like.)
For manually coded examples, it would be easy enough just to pass in a hardcoded lambda with the value set, but my use case involves running through a collection of objects and finding the match for each one, so the value will not be known until runtime, and the method must work against arbitrary types and various properties, so I can't hardcode the property name either.
If you have a property selector, and a value to compare to, you can get an expression tree like this:
public static Func<TEntity, bool> GetComparer<TEntity,TProperty>(
Expression<Func<TEntity,TProperty>> selector, TProperty value)
{
var propertyRef = selector.Body;
var parameter = selector.Parameters[0];
var constantRef = Expression.Constant(value);
var comparer
= Expression.Lambda<Func<TEntity, bool>>
(Expression.Equal(propertyRef, constantRef), parameter)
.Compile();
return comparer;
}
Sample usage:
var comparer = GetComparer<Person, string>(p => p.Name, "John");
var persons = Person.GetPersons();
var john = persons.FirstOrDefault(comparer);

How to replace the string value in extension method for lambda

I would like to replace "PKMvrMedsProductIssuesId" for something like x=>x.PKMvrMedsProductIssueId or anything that is not based on a string. Why? Because if the database people choose to rename the field my program would crash.
public static SelectList MvrMedsProductErrors(this SelectList Object)
{
MedicalVarianceEntities LinqEntitiesCtx = new MedicalVarianceEntities();
var ProductErrorsListBoxRaw =
(
from x in LinqEntitiesCtx.ViewLookUpProductIssuesErrorsNames
select x
);
Object = new SelectList(ProductErrorsListBoxRaw, "PKMvrMedsProductIssuesId", "MvrMedsProductIssuesErrorsNames");
return Object;
}
You're using a SelectList. In order to call that constructor, you must have a string. Any change we could propose will still result in a string (from somewhere) being passed into that constructor.
The good news is: that string can come from anywhere. It can come from config, from the database... where ever you like.
I don't know the exact context here (what exactly "PKMvrMedsProductIssuesId" is) , but you can for example use such helper method:
public static string GetPropertyAsString<T>(Expression<Func<T, object>> expression)
{
return GetPropertyInfo(expression).Name;
}
To use an expression to get string:
GetPropertyAsString<MyType>(x => x.MyTypeProperty);
('MyTypeProperty' is your 'PKMvrMedsProductIssuesId' any 'MyType' one of your types where you may have your property defined)

Expression Tree parsing, variables ends up as constants

So I'm working on a project where I need to parse an expression tree. I got most of the things working, but I've run into a bit of a problem.
I've been looking at the other questions on StackOverflow on Expression Trees, but can't seem to find an answer to my question, so here goes.
My problem is the difference (or lack of) between constants and variables. Let me start off with an example:
user => user.Email == email
This is clearly not a constant but a variable, but this ends up being a ConstantExpression somewhere in the expression tree. If you take a look at the expression itself, it looks a bit odd:
Expression = {value(stORM.Web.Security.User+<>c__DisplayClassa)}
If we take another example:
task => task.Status != TaskStatus.Done && t.Status != TaskStatus.Failed
Here I'm using an ENUM (TaskStatus).
So my problem is that in the tree parsing I seem to end up with a ConstantExpression in both cases, and I really need to be able to tell them apart. These are just examples, so what I'm asking is a generic way of telling these two types of expression from each other, so I can handle then in 2 different ways in my parsing.
EDIT: okay, my examples might not be clear, so I'll try again. First example:
User user = db.Search < User > (u => u.Email == email);
I'm trying to find a user with the given e-mail address. I'm parsing this into a stored procedure, but that's besides the point I guess.
Second example:
IList < Task > tasks = db.Search(t => t.Status != TaskStatus.Done && t.Status != TaskStatus.Failed);
And here I'm trying to locate all tasks with a status different from Done and Failed.
Again this is being parsing into a stored procedure. In the first example my code needs to determine that the stored procedure needs a input parameter, the value of the email variable. In the second example I don't need any input parameters, I just need to create the SQL for selecting task with a status different from Done and Failed.
Thanks again
So from the point of view of expression the value is a constant. It can not be changed by the expression.
What you have is a potentially open closure - i.e. the value can change between executions of the expression, but not during it. So it is a "constant". This is a paradigm difference between the world of functional programming and un-functional :) programming.
Consider
int a =2;
Expression<Func<int, int>> h = x=> x+ a;
Expression<Func<int, int>> j = x => x +2;
a = 1;
the term a is a member access into an anonymous class that wraps up and access the a variable on the stack. The first node is a MemberAccess node then underneath that - the expression is a constant.
For the code above:
((SimpleBinaryExpression)(h.Body)).Right
{value(WindowsFormsApplication6.Form1+<>c__DisplayClass0).a}
CanReduce: false
DebugView: ".Constant<WindowsFormsApplication6.Form1+<>c__DisplayClass0>(WindowsFormsApplication6.Form1+<>c__DisplayClass0).a"
Expression: {value(WindowsFormsApplication6.Form1+<>c__DisplayClass0)}
Member: {Int32 a}
NodeType: MemberAccess
Type: {Name = "Int32" FullName = "System.Int32"}
And the constant underneath that:
((MemberExpression)((SimpleBinaryExpression)(h.Body)).Right).Expression
{value(WindowsFormsApplication6.Form1+<>c__DisplayClass0)}
CanReduce: false
DebugView: ".Constant<WindowsFormsApplication6.Form1+<>c__DisplayClass0>(WindowsFormsApplication6.Form1+<>c__DisplayClass0)"
NodeType: Constant
Type: {Name = "<>c__DisplayClass0" FullName = "WindowsFormsApplication6.Form1+<>c__DisplayClass0"}
Value: {WindowsFormsApplication6.Form1.}
}
}
The plain old 2 comes out to a:
((SimpleBinaryExpression)(j.Body)).Right
{2}
CanReduce: false
DebugView: "2"
NodeType: Constant
Type: {Name = "Int32" FullName = "System.Int32"}
Value: 2
So I don't know if that helps you or not. You can kind of tell by looking at the parent node - or the type of object being accessed by the parent node.
Adding as a result of your clarification -
so when you say
user => user.Email == email
You mean look for all users with an email equal to a passed in parameter - however that link expression means something quite different.
what you want to say is
Expression<Func<User, string, bool>> (user, email) => user.Email == email
This way the email will now be a parameter. If you don't like that there is one other thing you can do.
The second example will work just fine - no extra params are needed consts will be consts.
t => t.Status != TaskStatus.Done && t.Status != TaskStatus.Failed
Edit: adding another way:
So one of the things that you had to do to get your code working was declare a string email outside the lambda - that is kind of clunky.
You could better identify parameters by conventionally putting them in a specific place - like a static class. Then when going through the Lambda you don't have to look at some horrible cloture object - but a nice static class of your making.
public static class Parameter
{
public static T Input<T>(string name)
{
return default(T);
}
}
Then your code looks like this:
Expression<Func<User, bool>> exp = x => x.Email == Parameter.Input<String>("email");
You can then traverse the tree - when you come to a call to to the Parameter static class you can look at the type and the name (in the arguments collection) and off you go....
The name is a bit unfortunate, it is not actually a constant.
It simply refers to a value outside the Expression.
A captured variable (the first case with email) is typically a ConstantExpression representing the capture class instance, with a MemberExpression to a FieldInfo for the "variable" - as if you had:
private class CaptureClass {
public string email;
}
...
var obj = new CaptureClass();
obj.email = "foo#bar.com";
Here, obj is the constant inside the expression.
So: if you see a MemberExpression (of a field) to a ConstantExpression, it is probably a captured variable. You could also check for CompilerGeneratedAttribute on the capture-class...
A literal constant will typically just be a ConstantExpression; in fact, it would be hard to think of a scenario where you use a constant's member, unless you could something like:
() => "abc".Length
but here .Length is a property (not a field), and the string probably doesn't have [CompilerGenerated].
Just check the Type of the ConstantExpression. Any 'constant' ConstantExpression has a primitive type.

Retrieving an Expression from a property and adding it to an expression tree

I've tried to simplify this example, as the actual code I'm playing with is more complex. So while this example may seem silly, bear with me. Let's say I'm working with the AdventureWorks database and I decide I want to add a property called Blarg to the Product table that returns an expression that contains code I would like to use in several places:
public partial class Product
{
public Expression<Func<Product, string>> Blarg
{
get { return product => product.ProductModelID.HasValue ? "Blarg?" : "Blarg!"; }
}
}
What I want to do is create an expression expression tree, have it get the Expression from Product.Blarg, and group by the result. Something like this:
var productParameter = Expression.Parameter(typeof(Product), "product");
// The Problem
var groupExpression = Expression.Lambda<Func<Product, string>>(
Expression.Invoke(
Expression.Property(productParameter, "Blarg"),
productParameter),
productParameter);
using (AdventureWorksDataContext db = new AdventureWorksDataContext())
{
var result = db.Products.GroupBy(groupExpression).ToList();
// Throws ArgumentException: "The argument 'value' was the wrong type.
// Expected 'System.Delegate'.
// Actual 'System.Linq.Expressions.Expression`1[System.Func`2[LINQ_Test.Product,System.String]]'."
}
Obviously groupExpression is incorrect (see the code comment for the exception), but I'm not sure how I should be doing it. What I thought I was saying is "get the Expression from the product.Blarg, execute it, and return the string result." I guess that's not what I'm actually saying there, though. I'm still trying to figure out expression trees. Any idea how I could pull this off?
When you call Expression.Invoke, the first argument must be an existing LambdaExpression - it can't be an Expression to a LambdaExpression. Or in other words: it isn't going to evaluate Product.Blarg per row and use a different sub-expression each time.
Instead, you would retrieve this lambda first, perhaps making it static and accessing it via reflection if you only know it by name:
var lambda = (LambdaExpression) typeof(Product)
.GetProperty("Blarg").GetValue(null,null);
And pass lambda in as the argument to Expression.Invoke; here's a fully working LINQ-to-Objects example showing this (via AsQueryable()):
using System;
using System.Linq;
using System.Linq.Expressions;
public partial class Product
{
public static Expression<Func<Product, string>> Blarg
{
get { return product => product.ProductModelID.HasValue ? "Blarg?" : "Blarg!"; }
}
public int? ProductModelID { get; set; }
static void Main()
{
var lambda = (LambdaExpression)typeof(Product)
.GetProperty("Blarg").GetValue(null, null);
var productParameter = Expression.Parameter(typeof(Product), "product");
// The Problem
var groupExpression = Expression.Lambda<Func<Product, string>>(
Expression.Invoke(
lambda,
productParameter),
productParameter);
var data = new[] {
new Product { ProductModelID = 123},
new Product { ProductModelID = null},
new Product { ProductModelID = 456},
};
var qry = data.AsQueryable().GroupBy(groupExpression).ToList();
}
}
var qry = data.AsQueryable().GroupBy(Blarg).ToList();
That works, same as Marc's code.
Note: Blarg is already correct, there is no reason to 're-invoke' it.

Categories