C# Reflection Expression Linq
I'm having some problems with C# dynamic generated lambda expressions.
Considering the following scenario:
public class Person {
public long Id { get; set; }
public string Name { get; set; }
}
List<Person> persons = new List<Person> () {
new Person { Id = 1, Name = "Foo" },
new Person { Id = 2, Name = "Bar" },
new Person { Id = 3, Name = "Baz" },
new Person { Id = 4, Name = null },
};
Now, doing the follow code
ParameterExpression param = Expression.Parameter(typeof(Person), "arg");
Expression prop = Expression.Property(param, "Name");
Expression value = Expression.Constant("bar");
Type type = prop.Type;
MethodInfo toLower = typeof(String).GetMethod("ToLower", Type.EmptyTypes);
Expression expLower = Expression.Call(prop, toLower);
Expression clausule = Expression.Call(expLower, type.GetMethod("Contains", new { type }), value);
Expression notNull = Expression.NotEqual(prop, Expression.Constant(null));
clausule = Expression.And(notNull, clausule);
var exp = Expression.Lambda<Func<T, bool>>(clausule, param);
The above code generate the following exp.
//arg => ((arg.Name != null) And (arg.Name.ToLower().Contains("bar")))
Now, trying to apply that to my list.
The filter below works
var filteredListThatWorks = persons.Where(arg => arg.Name != null && arg.Name.ToLower().Contains("bar")).ToList();
The one below throws exception of Null object ( because of Id 4 name)
var filteredListThatGivesExp = persons.Where(exp.Compile()).ToList();
The same expression, when generated by lambda, throws exp, when manually inputed, works.
Anyone knows a way to solve that ?
Br,
c# lambda reflection
add a comment |
I'm having some problems with C# dynamic generated lambda expressions.
Considering the following scenario:
public class Person {
public long Id { get; set; }
public string Name { get; set; }
}
List<Person> persons = new List<Person> () {
new Person { Id = 1, Name = "Foo" },
new Person { Id = 2, Name = "Bar" },
new Person { Id = 3, Name = "Baz" },
new Person { Id = 4, Name = null },
};
Now, doing the follow code
ParameterExpression param = Expression.Parameter(typeof(Person), "arg");
Expression prop = Expression.Property(param, "Name");
Expression value = Expression.Constant("bar");
Type type = prop.Type;
MethodInfo toLower = typeof(String).GetMethod("ToLower", Type.EmptyTypes);
Expression expLower = Expression.Call(prop, toLower);
Expression clausule = Expression.Call(expLower, type.GetMethod("Contains", new { type }), value);
Expression notNull = Expression.NotEqual(prop, Expression.Constant(null));
clausule = Expression.And(notNull, clausule);
var exp = Expression.Lambda<Func<T, bool>>(clausule, param);
The above code generate the following exp.
//arg => ((arg.Name != null) And (arg.Name.ToLower().Contains("bar")))
Now, trying to apply that to my list.
The filter below works
var filteredListThatWorks = persons.Where(arg => arg.Name != null && arg.Name.ToLower().Contains("bar")).ToList();
The one below throws exception of Null object ( because of Id 4 name)
var filteredListThatGivesExp = persons.Where(exp.Compile()).ToList();
The same expression, when generated by lambda, throws exp, when manually inputed, works.
Anyone knows a way to solve that ?
Br,
c# lambda reflection
1
also keep in mind - when you usevar filteredListThatGivesExp = persons.Where(exp.Compile()).ToList();
, that is being compiled to a delegate, not an expression tree; if you want truly equivalent code, you should perhaps usepersons.AsQueryable().Where(...)
, which forces it to use the expression-tree API
– Marc Gravell♦
Nov 23 '18 at 10:49
add a comment |
I'm having some problems with C# dynamic generated lambda expressions.
Considering the following scenario:
public class Person {
public long Id { get; set; }
public string Name { get; set; }
}
List<Person> persons = new List<Person> () {
new Person { Id = 1, Name = "Foo" },
new Person { Id = 2, Name = "Bar" },
new Person { Id = 3, Name = "Baz" },
new Person { Id = 4, Name = null },
};
Now, doing the follow code
ParameterExpression param = Expression.Parameter(typeof(Person), "arg");
Expression prop = Expression.Property(param, "Name");
Expression value = Expression.Constant("bar");
Type type = prop.Type;
MethodInfo toLower = typeof(String).GetMethod("ToLower", Type.EmptyTypes);
Expression expLower = Expression.Call(prop, toLower);
Expression clausule = Expression.Call(expLower, type.GetMethod("Contains", new { type }), value);
Expression notNull = Expression.NotEqual(prop, Expression.Constant(null));
clausule = Expression.And(notNull, clausule);
var exp = Expression.Lambda<Func<T, bool>>(clausule, param);
The above code generate the following exp.
//arg => ((arg.Name != null) And (arg.Name.ToLower().Contains("bar")))
Now, trying to apply that to my list.
The filter below works
var filteredListThatWorks = persons.Where(arg => arg.Name != null && arg.Name.ToLower().Contains("bar")).ToList();
The one below throws exception of Null object ( because of Id 4 name)
var filteredListThatGivesExp = persons.Where(exp.Compile()).ToList();
The same expression, when generated by lambda, throws exp, when manually inputed, works.
Anyone knows a way to solve that ?
Br,
c# lambda reflection
I'm having some problems with C# dynamic generated lambda expressions.
Considering the following scenario:
public class Person {
public long Id { get; set; }
public string Name { get; set; }
}
List<Person> persons = new List<Person> () {
new Person { Id = 1, Name = "Foo" },
new Person { Id = 2, Name = "Bar" },
new Person { Id = 3, Name = "Baz" },
new Person { Id = 4, Name = null },
};
Now, doing the follow code
ParameterExpression param = Expression.Parameter(typeof(Person), "arg");
Expression prop = Expression.Property(param, "Name");
Expression value = Expression.Constant("bar");
Type type = prop.Type;
MethodInfo toLower = typeof(String).GetMethod("ToLower", Type.EmptyTypes);
Expression expLower = Expression.Call(prop, toLower);
Expression clausule = Expression.Call(expLower, type.GetMethod("Contains", new { type }), value);
Expression notNull = Expression.NotEqual(prop, Expression.Constant(null));
clausule = Expression.And(notNull, clausule);
var exp = Expression.Lambda<Func<T, bool>>(clausule, param);
The above code generate the following exp.
//arg => ((arg.Name != null) And (arg.Name.ToLower().Contains("bar")))
Now, trying to apply that to my list.
The filter below works
var filteredListThatWorks = persons.Where(arg => arg.Name != null && arg.Name.ToLower().Contains("bar")).ToList();
The one below throws exception of Null object ( because of Id 4 name)
var filteredListThatGivesExp = persons.Where(exp.Compile()).ToList();
The same expression, when generated by lambda, throws exp, when manually inputed, works.
Anyone knows a way to solve that ?
Br,
c# lambda reflection
c# lambda reflection
asked Nov 23 '18 at 10:38
Lucas FreitasLucas Freitas
4502928
4502928
1
also keep in mind - when you usevar filteredListThatGivesExp = persons.Where(exp.Compile()).ToList();
, that is being compiled to a delegate, not an expression tree; if you want truly equivalent code, you should perhaps usepersons.AsQueryable().Where(...)
, which forces it to use the expression-tree API
– Marc Gravell♦
Nov 23 '18 at 10:49
add a comment |
1
also keep in mind - when you usevar filteredListThatGivesExp = persons.Where(exp.Compile()).ToList();
, that is being compiled to a delegate, not an expression tree; if you want truly equivalent code, you should perhaps usepersons.AsQueryable().Where(...)
, which forces it to use the expression-tree API
– Marc Gravell♦
Nov 23 '18 at 10:49
1
1
also keep in mind - when you use
var filteredListThatGivesExp = persons.Where(exp.Compile()).ToList();
, that is being compiled to a delegate, not an expression tree; if you want truly equivalent code, you should perhaps use persons.AsQueryable().Where(...)
, which forces it to use the expression-tree API– Marc Gravell♦
Nov 23 '18 at 10:49
also keep in mind - when you use
var filteredListThatGivesExp = persons.Where(exp.Compile()).ToList();
, that is being compiled to a delegate, not an expression tree; if you want truly equivalent code, you should perhaps use persons.AsQueryable().Where(...)
, which forces it to use the expression-tree API– Marc Gravell♦
Nov 23 '18 at 10:49
add a comment |
1 Answer
1
active
oldest
votes
And
is &
; you want to use AndAlso
(&&
):
clausule = Expression.AndAlso(notNull, clausule);
When in doubt, sharplab.io is an excellent tool here; if I use:
Expression<Func<Person, bool>> filter
= arg => arg.Name != null && arg.Name.ToLower().Contains("bar");
it tells me that it compiles to be equivalent to:
// ...
BinaryExpression body = Expression.AndAlso(left, Expression.Call(instance, method, obj));
// ...
(note that it has to lie about some of the instructions though, as it compiles to things that can't actually be expressed in raw C#)
see it in action
You deserve a cookie Sir! 4 more mins to mark as Correct. Thank you very much
– Lucas Freitas
Nov 23 '18 at 10:49
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53445071%2fc-sharp-reflection-expression-linq%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
And
is &
; you want to use AndAlso
(&&
):
clausule = Expression.AndAlso(notNull, clausule);
When in doubt, sharplab.io is an excellent tool here; if I use:
Expression<Func<Person, bool>> filter
= arg => arg.Name != null && arg.Name.ToLower().Contains("bar");
it tells me that it compiles to be equivalent to:
// ...
BinaryExpression body = Expression.AndAlso(left, Expression.Call(instance, method, obj));
// ...
(note that it has to lie about some of the instructions though, as it compiles to things that can't actually be expressed in raw C#)
see it in action
You deserve a cookie Sir! 4 more mins to mark as Correct. Thank you very much
– Lucas Freitas
Nov 23 '18 at 10:49
add a comment |
And
is &
; you want to use AndAlso
(&&
):
clausule = Expression.AndAlso(notNull, clausule);
When in doubt, sharplab.io is an excellent tool here; if I use:
Expression<Func<Person, bool>> filter
= arg => arg.Name != null && arg.Name.ToLower().Contains("bar");
it tells me that it compiles to be equivalent to:
// ...
BinaryExpression body = Expression.AndAlso(left, Expression.Call(instance, method, obj));
// ...
(note that it has to lie about some of the instructions though, as it compiles to things that can't actually be expressed in raw C#)
see it in action
You deserve a cookie Sir! 4 more mins to mark as Correct. Thank you very much
– Lucas Freitas
Nov 23 '18 at 10:49
add a comment |
And
is &
; you want to use AndAlso
(&&
):
clausule = Expression.AndAlso(notNull, clausule);
When in doubt, sharplab.io is an excellent tool here; if I use:
Expression<Func<Person, bool>> filter
= arg => arg.Name != null && arg.Name.ToLower().Contains("bar");
it tells me that it compiles to be equivalent to:
// ...
BinaryExpression body = Expression.AndAlso(left, Expression.Call(instance, method, obj));
// ...
(note that it has to lie about some of the instructions though, as it compiles to things that can't actually be expressed in raw C#)
see it in action
And
is &
; you want to use AndAlso
(&&
):
clausule = Expression.AndAlso(notNull, clausule);
When in doubt, sharplab.io is an excellent tool here; if I use:
Expression<Func<Person, bool>> filter
= arg => arg.Name != null && arg.Name.ToLower().Contains("bar");
it tells me that it compiles to be equivalent to:
// ...
BinaryExpression body = Expression.AndAlso(left, Expression.Call(instance, method, obj));
// ...
(note that it has to lie about some of the instructions though, as it compiles to things that can't actually be expressed in raw C#)
see it in action
answered Nov 23 '18 at 10:43
Marc Gravell♦Marc Gravell
793k19821612565
793k19821612565
You deserve a cookie Sir! 4 more mins to mark as Correct. Thank you very much
– Lucas Freitas
Nov 23 '18 at 10:49
add a comment |
You deserve a cookie Sir! 4 more mins to mark as Correct. Thank you very much
– Lucas Freitas
Nov 23 '18 at 10:49
You deserve a cookie Sir! 4 more mins to mark as Correct. Thank you very much
– Lucas Freitas
Nov 23 '18 at 10:49
You deserve a cookie Sir! 4 more mins to mark as Correct. Thank you very much
– Lucas Freitas
Nov 23 '18 at 10:49
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53445071%2fc-sharp-reflection-expression-linq%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
also keep in mind - when you use
var filteredListThatGivesExp = persons.Where(exp.Compile()).ToList();
, that is being compiled to a delegate, not an expression tree; if you want truly equivalent code, you should perhaps usepersons.AsQueryable().Where(...)
, which forces it to use the expression-tree API– Marc Gravell♦
Nov 23 '18 at 10:49