Lambda expression not returning expected MemberInfo
Take the type of the expression's (first) parameter, and say
Expression<Func<C, string>> c = x => x.B;
Type paramType = c.Parameters[0].Type; // first parameter of expression
var d = paramType.GetMember((c.Body as MemberExpression).Member.Name)[0];
C# Not all code paths return a valid in lambda expression of type func
Here you need to return something from all your path.
timeReports = timeReports.OrderByDescending(x => x.Date).ThenByDescending(x =>
{
var firstOrDefault = x.TimeReportDatas.FirstOrDefault();
if (firstOrDefault != null)
{
return firstOrDefault.StartHour;
}
else
{
return 0;
}
}).ToList();
Or more simpler way:
timeReports = timeReports.OrderByDescending(x => x.Date)
.ThenByDescending(x => (x.TimeReportDatas.FirstOrDefault() != null) ? x.TimeReportDatas.First().StartHour : 0)
.ToList();
Retrieving Property name from lambda expression
I found another way you can do it was to have the source and property strongly typed and explicitly infer the input for the lambda. Not sure if that is correct terminology but here is the result.
public static RouteValueDictionary GetInfo<T,P>(this HtmlHelper html, Expression<Func<T, P>> action) where T : class
{
var expression = (MemberExpression)action.Body;
string name = expression.Member.Name;
return GetInfo(html, name);
}
And then call it like so.
GetInfo((User u) => u.UserId);
and voila it works.
lambda search 'contains' not returning expected results
The Contains
method is case sensitive. Can it be that your input and comparison differs in casing? To get around that, you can use IndexOf
instead:
var filtered = masterDocs.Where(i =>
i.DisplayTitle.IndexOf(
searchStr, StringComparison.InvariantCultureIgnoreCase) >= 0);
Why is a member of base class different from the same member in derived class?
They differ in their ReflectedType
property:
The ReflectedType property retrieves the Type object that was used to obtain this instance of MemberInfo. This may differ from the value of the DeclaringType property if this MemberInfo object represents a member that is inherited from a base class.
So if you print out m1.ReflectedType
, it should print Human
. If you print out m2.ReflectedType
, it should print Man
.
EDIT: In terms of why the equality operator is implemented this way: it's always a delicate design decision to work out what ==
should mean, in the case where there may be distinguishable but not "primary" differences between objects. This is where providing different IEqualityComparer
implementations is useful, but of course that doesn't work for the operators themselves.
In general, if x == y
is true then it's quite unusual for x.Foo
to be different to y.Foo
for any property. I can't immediately think of any cases where that occurs in the framework.
Get the name of a method using an expression
x => x.DoSomething
In order to make this compilable I see only two ways:
- Go non-generic way and specify it's parameter as
Action<string, string>
- Specify
Action<string, string>
as your target delegate type by yourself:GetMethodInfo<IMyInteface>(x => new Action<string,string>(x.DoSomething))
if you are ok to go with second one, which allows you to omit arguments then you can write your GetMethodInfo
method as follows:
MemberInfo GetMethodInfo<T>(Expression<Func<T, Delegate>> expression)
{
var unaryExpression = (UnaryExpression) expression.Body;
var methodCallExpression = (MethodCallExpression) unaryExpression.Operand;
var methodInfoExpression = (ConstantExpression) methodCallExpression.Arguments.Last();
var methodInfo = (MemberInfo) methodInfoExpression.Value;
return methodInfo;
}
It works for your interface, but probably some generalization will be required to make this working with any method, that's up to you.
Having issues with this lambda code not returning a value for all situations
Your variable1
is a int
(a Value type) so when you pass it as argument, you actually passing its value, so inside your tally
lambda there will be another int
variable z
which is independent from variable1
. So, when you do z++
inside tally
, your variable1
is not changing.
If your tally
is defined near variable1
you may just use it inside your lambda:
var variable1 = 0;
DelegateName tally = (x, y) => { if (x == y) variable1++; };
foreach (var cellValue in cells)
tally(cellValue.ToString().SubString(0,1), "1");
Another way is a LINQ:
using System.Linq;
var variable1 = cells.Select(c => c.ToString().FirstOrDefault()).Count(c => c == '1');
// or even better (thx @RufusL)
var variable2 = cells.Count(c => c.ToString().StartsWith("1"));
Get property name and type using lambda expression
Here's enough of an example of using Expressions to get the name of a property or field to get you started:
public static MemberInfo GetMemberInfo<T, U>(Expression<Func<T, U>> expression)
{
var member = expression.Body as MemberExpression;
if (member != null)
return member.Member;
throw new ArgumentException("Expression is not a member access", "expression");
}
Calling code would look like this:
public class Program
{
public string Name
{
get { return "My Program"; }
}
static void Main()
{
MemberInfo member = ReflectionUtility.GetMemberInfo((Program p) => p.Name);
Console.WriteLine(member.Name);
}
}
A word of caution, though: the simple statment of (Program p) => p.Name
actually involves quite a bit of work (and can take measurable amounts of time). Consider caching the result rather than calling the method frequently.
Related Topics
How to Find Out When You'Ve Been Loaded via Xml Serialization
How to Return a File Using Web API
Http 404 Page Not Found in Web API Hosted in Iis 7.5
Force Gui Update from UI Thread
Could Not Load File or Assembly 'Microsoft.Reportviewer.Common, Version=11.0.0.0
Path.Combine Absolute with Relative Path Strings
Generic Base Class for Winform Usercontrol
How to Call a Variable in Code Behind to Aspx Page
Gps Socket Communication (Concox)
Date of Birth Validation Keeps Showing
How Abstraction and Encapsulation Differ
Optimal Way to Read an Excel File (.Xls/.Xlsx)
ASP.NET Asmx Web Service Returning Xml Instead of JSON
Exception When Addwithvalue Parameter Is Null
How to Capture the '#' Character on Different Locale Keyboards in Wpf/C#