7

I need to write a function that receives a property as a parameter and execute its getter.

If I needed to pass a function/delegate I would have used:

delegate RET FunctionDelegate<T, RET>(T t);

void func<T, RET>(FunctionDelegate function, T param, ...)
{
    ...
    return function.Invoke(param);
}

Is there a similar way to define a property so that I could invoke it's getter and/or setter in the function code?

Dror Helper
  • 30,292
  • 15
  • 80
  • 129

5 Answers5

12

You can also write something like:

static void Method<T, U>(this T obj, Expression<Func<T, U>> property)
        {
            var memberExpression = property.Body as MemberExpression;
            //getter
            U code = (U)obj.GetType().GetProperty(memberExpression.Member.Name).GetValue(obj, null);
            //setter
            obj.GetType().GetProperty(memberExpression.Member.Name).SetValue(obj, code, null);
        }

and example of invocation:

DbComputerSet cs = new DbComputerSet();
cs.Method<DbComputerSet, string>(set => set.Code);
  • There is also the possibility of a UnaryExpression which you have to account for. Look here: http://stackoverflow.com/a/2916344/265877 – Alex Jul 03 '12 at 21:34
9

You can use reflection, you can get a MethodInfo object for the get/set accessors and call it's Invoke method.

The code example assumes you have both a get and set accessors and you really have to add error handling if you want to use this in production code:

For example to get the value of property Foo of object obj you can write:

value = obj.GetType().GetProperty("Foo").GetAccessors()[0].Invoke(obj,null);

to set it:

obj.GetType().GetProperty("Foo").GetAccessors()[1].Invoke(obj,new object[]{value});

So you can pass obj.GetType().GetProperty("Foo").GetAccessors()[0] to your method and execute it's Invoke method.

an easier way is to use anonymous methods (this will work in .net 2.0 or later), let's use a slightly modified version of your code example:

delegate RET FunctionDelegate<T, RET>(T t);

void func<T, RET>(FunctionDelegate<T,RET> function, T param, ...)
{
    ...
    return function(param);
}

for a property named Foo of type int that is part of a class SomeClass:

SomeClass obj = new SomeClass();
func<SomeClass,int>(delegate(SomeClass o){return o.Foo;},obj);
Nir
  • 29,306
  • 10
  • 67
  • 103
3

Properties are simply syntactic sugar for methods.

I don't think you can modify a property such that it becomes some entity "whose getter you can call".

You can however create a method GetPropertyValue() and pass that around as if it were a delegate.

Martijn
  • 6,713
  • 3
  • 31
  • 38
  • 1
    That's a very good idea along the KISS principle. Unfortunatly at this point I cannot use it :( The problem is that the property I'm using is not part of my code. And writing a wrapper adds overhead I do not want at this point – Dror Helper Sep 21 '08 at 08:56
2

@Dror Helper,

I'm afraid you can't do it that way. Compiler generates get_PropertyName and set_PropertyName methods but they are not accessible without using Reflection. IMO best you can do is create function that takes System.Reflection.ProperyInfo and System.Object params and returns propInfo.GetValue(obj, null);

aku
  • 122,288
  • 32
  • 173
  • 203
1

Re: aku's answer:

Then you have to obtain that property info first. It seems "use reflection" is the standard answer to the harder C# questions, but reflection yields not-so-pretty hard-to-maintain code. Dror, why not just create a delegate that reads the property for you? It's a simple one-liner and is probably the quickest and prettiest solution to your problem.

Martijn
  • 6,713
  • 3
  • 31
  • 38
  • Yep, solution will involve Reflection anyway. You can create some helpful wrappers, but I prefer to have simpler code. Practice shows that complex reflection solutions are very fragile. – aku Sep 21 '08 at 10:18
  • 1
    Martijn - I already answered you regarding creating a wrapper - although it's a simple enough solution it is not what I need – Dror Helper Sep 21 '08 at 13:44