Lambda Expression Not Returning Expected Memberinfo

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:

  1. Go non-generic way and specify it's parameter as Action<string, string>
  2. 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



Leave a reply



Submit