1

I want to pass a property to a function such that the function knows both the value of the property and the name of the property. This is so I can return errors that match the property names.

I currently have code like this:

var userNameField = personField.GetChildField(f => f.UserName, nameof(personField.Value.UserName));

many times repeated, so the 2nd parameter is the name of the property inside the lambda of the 1st parameter.

Is it possible to automate this parameter so:

  1. The duplicate code is gone
  2. The string name of the property is calculated at compile-time, not run-time for every call

Ideally I would like my code to simply look like:

var userNameField = personField.GetChildField(f => f.UserName);

I have got this working using reflection using Expression<Func... i.e. ((MemberExpression) getPropertyFunc.Body).Member.Name; but this is too slow, in particular compiling the expression into a function which I can use to fetch the property value.

Similarly, I have read through the ideas here: Get name of property as a string

Is there any way of populating the property name from the GetChildField function at compile time? Or encoding it into the model somehow?

Michael Parker
  • 7,180
  • 7
  • 30
  • 39
  • If compiling the expression is too slow, have you tried caching the result of that compilation? It wouldn't make the first call any faster, but subsequent calls could benefit. Also, since you seem to accept only expressions of the form `x => x.Property`, have you tried getting the property through reflection instead of compiling the expression? – Kris Vandermotten Aug 03 '17 at 23:56
  • Is it possible to cache the result of the compilation? I call the method that compiles the expression with many different expressions across the codebase so it would need to be cached on a per call basis. Your second point is correct though. I have managed to improve the performance by removing the compilation and getting the property through reflection, however it's still not ideal as the property name is still calculated at runtime (I believe.. unless the compiler does something funky). – Michael Parker Aug 06 '17 at 11:09
  • Did you ever solve this? I have the same problem. – Franklin Dec 09 '19 at 13:50
  • No I didn't. I did manage to optimise the code to avoid the expensive code path but ultimately it was still using reflection and was the primary cause of slowdown. However, the service was deemed fast enough so further optimisation wasn't needed. Unfortunately I've changed jobs and left the code behind in my previous company but my comment above summarises the approach i believe. (I can't remember further details, sorry) – Michael Parker Dec 10 '19 at 15:00

2 Answers2

0

It is possible by following:

Item model=new Item();    
var propertyInfo = model.GetType();    
var value=propertyInfo.GetProperty("IrrA").GetValue(model, null).ToString();
Balagurunathan Marimuthu
  • 2,927
  • 4
  • 31
  • 44
  • Didn't the OP asked for no reflection solution? – kuskmen Jul 29 '17 at 07:26
  • @kuskmen Actually no, OP did not ask for a no reflection solution. OP only stated that compiling an expression was too slow. This might be faster than compiling the expression (or not - I did not test). – Kris Vandermotten Aug 04 '17 at 00:00
  • I asked for a solution that calculated the property name at compile time, not run time. However, this solution is faster than compiling the expression. – Michael Parker Aug 06 '17 at 11:11
-1

According to the Roslyn documentation found here the nameof operator is evaluated at compile-time per the first line under the "Semantics" section that reads

The nameof expression is a constant. In all cases, nameof(...) is evaluated at compile-time to produce a string. Its argument is not evaluated at runtime, and is considered unreachable code (however it does not emit an "unreachable code" warning).