13

Given the following class:

class TestClass {
  public void SetValue(int value) { Value = value; }
  public int Value { get; set; }
}

I can do

TestClass tc = new TestClass();
Action<int> setAction = tc.SetValue;
setAction.Invoke(12);

which is all good. Is it possible to do the same thing using the property instead of the method? Preferably with something built in to .net.

Robert Höglund
  • 10,010
  • 13
  • 53
  • 70

3 Answers3

21

You could create the delegate using reflection :

Action<int> valueSetter = (Action<int>)Delegate.CreateDelegate(typeof(Action<int>), tc, tc.GetType().GetProperty("Value").GetSetMethod());

or create a delegate to an anonymous method which sets the property;

Action<int> valueSetter = v => tc.Value = v;

Edit: used wrong overload for CreateDelegate(), need to use the one that takes and object as target. Fixed.

Pop Catalin
  • 61,751
  • 23
  • 87
  • 115
  • Given that C# is supposed to be my first language I really wish I'd understand this stuff (creating a delegate using reflection) - sounds great – JohnIdol Nov 14 '08 at 14:04
  • 1
    And for .net 2.0 one could do Action valueSetter = delegate(int value) { tc.Value = value; } – Robert Höglund Nov 14 '08 at 14:18
  • @Robert, you can target .Net 2.0 using the C# 3.0 compiler, there's no reason to stick to the C# 2.0 compiler ;) – Pop Catalin Nov 14 '08 at 16:51
  • FWIW, I was curious, and benchmarked your two approaches given above (except since I'm targeting .Net 2.0, I used Action valueSetter = delegate(int v) { tc.Value = v; }; instead of the lambda you gave). The tradeoff you get for compile-time type- and name-checking (the anonymous delegate / lambda version) is that it takes twice as long, because the code calls a delegate which calls the property setter. The first approach directly calls the property setter, so while you don't get compile-time checking, you get twice the speed, which for my particular approach is significant. – Dathan Aug 25 '09 at 17:18
12

There are three ways of doing this; the first is to use GetGetMethod()/GetSetMethod() and create a delegate with Delegate.CreateDelegate. The second is a lambda (not much use for reflection!) [i.e. x=>x.Foo]. The third is via Expression (.NET 3.5).

The lambda is the easiest ;-p

    class TestClass
    {
        public int Value { get; set; }
    }
    static void Main()
    {
        Func<TestClass, int> lambdaGet = x => x.Value;
        Action<TestClass, int> lambdaSet = (x, val) => x.Value = val;

        var prop = typeof(TestClass).GetProperty("Value");
        Func<TestClass, int> reflGet = (Func<TestClass, int>) Delegate.CreateDelegate(
            typeof(Func<TestClass, int>), prop.GetGetMethod());
        Action<TestClass, int> reflSet = (Action<TestClass, int>)Delegate.CreateDelegate(
            typeof(Action<TestClass, int>), prop.GetSetMethod());
    }

To show usage:

        TestClass foo = new TestClass();
        foo.Value = 1;
        Console.WriteLine("Via property: " + foo.Value);

        lambdaSet(foo, 2);
        Console.WriteLine("Via lambda: " + lambdaGet(foo));

        reflSet(foo, 3);
        Console.WriteLine("Via CreateDelegate: " + reflGet(foo));

Note that if you want the delegate pointing to the specific instance, you can use closures for the lambda, or the overload of CreateDelegate that accepts and instance.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 2
    btw, I haven't posted an Expression example, as it tends to be verbose. However, some Expression posts are on my blog: http://marcgravell.blogspot.com/search/label/expression – Marc Gravell Nov 14 '08 at 13:13
  • Thnak you very much for this easy to understand example! – L.Butz Oct 10 '14 at 13:36
3

Properties are really wrappers around methods in .Net, so using reflection you should be able to get the delegate (set_PROPERTY and get_PROPERTY) and then execute them...

See System.Reflection.PropertyInfo

If has two methods which you can use to get/ set the value - GetGetMethod and GetSetMethod.

So you could write:

var propertyInfo = typeof (TestClass).GetProperty ("Value");

var setMethod = property.GetSetMethod (); // This will return a MethodInfo class.
Kieron
  • 26,748
  • 16
  • 78
  • 122
  • 2
    Even though the C# specification reserves methods get_P and set_P for any property P, it does not require implementations to use these methods for properties. This makes it an implementation detail. Do not rely on undocumented implementation details. – Tamas Czinege Nov 14 '08 at 13:05
  • 4
    By using the PropertyInfo class and the GetGet/SetMethod it's no longer an implementation problem. It's part of the framework at that point. – Kieron Nov 14 '08 at 13:19