Now one possibility is to pass the value by reference which is often something I don't like very much, but won't get into that too much right now, but since we are dealing with properties here the usual more elegant way is to create a wrapper or lambda function of some kind.
Now natrually before coding anything a quick google/SO search reveals some basic solutions and as one might expect involves some reflection as one CodeProject article here.
However I usually use dynamic reflection as a last resort as there is too much room for error here and referring to fields as strings just doesn't seem like the cleanest way. Also a super simple solution is by an SO post made here (scroll down a bit) which simply just uses a small wrapper class you specifiy the getter and setter using 2 lambda expressions. This is certainly clean and simple, which I like, however I tried to create a function even simpler and more concise which also uses the compiler to ensure correctness, so I came up with this.
So much like the first version to use some reflection except no strings but using expressions. First extracting the property info from the expression, a nice clean wrapper object to help with this from this SO post:
public static class PropertyHelper<T> public static PropertyInfo GetProperty<TValue>( Expression<Func<T, TValue>> selector) { Expression body = selector; if (body is LambdaExpression) { body = ((LambdaExpression)body).Body; } switch (body.NodeType) { case ExpressionType.MemberAccess: return (PropertyInfo)((MemberExpression)body).Member; break; default: throw new InvalidOperationException(); } } }
So taking that a little further, creating a helper class to generate a lambda getter and setter
public static class PropertyHelper { public static Func<TValue> GetPropertyGetter<T, TValue>(T value, Expression<Func<T, TValue>> selector) { var propInfo = (PropertyInfo)((MemberExpression)(selector).Body).Member; return () => (TValue)propInfo.GetValue(value, null); } public static Action<TValue> GetPropertySetter<T, TValue>(T value, Expression<Func<T, TValue>> selector) { var propInfo = (PropertyInfo)((MemberExpression)(selector).Body).Member; return v => propInfo.SetValue(value, v, null); } }
Small note: This requires you to use a lambda expression for the property any other expression will break it, I didn't add all the checks to make it more terse. So Then the usage would simply be:
var getter = PropertyHelper.GetPropertyGetter(world, w => w.Hello); var setter = PropertyHelper.GetPropertySetter(world, w => w.Hello);
And then you can get the property by calling:
getter(); setter("Hello");
Extending that a little further by adding a nice wrapper class:
public class PropertyWrapper<TValue> : IPropertyWrapper<TValue> { protected PropertyInfo _propInfo; protected object _instance; public PropertyWrapper(PropertyInfo propinfo, object instance) { _instance = instance; _propInfo = propinfo; } public object Instance { get { return _instance; } } public TValue Value { get { return (TValue)_propInfo.GetValue(_instance, null); } set { _propInfo.SetValue(_instance, value, null); } } }Then you can pass around the wrappers:
var wrapper = PropertyHelper.GetPropertyWrapper(world, w => w.Hello)Now you can easily use this in your generic method and manipulate any property:
private static void TestCondition(IPropertyWrapperDynamic objects are of course another way to do this however you then still are missing out on the compile time checking, so I haven't coded out this solution, but I think I'd still rather use this approach then reflection by string name method. So there you have it, this seems like a nice clean way to create property references, you can take it one more step further by creating an object extension method for this, but I usually try to avoid this as it can clutter up the code completion just a little bit too much. But if you can think of an even better cleaner way in C#condition) { condition.Value = false; Console.WriteLine(condition.Instance.Validate()); condition.Value = true; Console.WriteLine(condition.Instance.Validate()); }