Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a delegate available for properties in C#?

Tags:

c#

.net

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.

like image 204
Robert Höglund Avatar asked Nov 14 '08 12:11

Robert Höglund


People also ask

What is C# delegate?

C# delegates are similar to pointers to functions, in C or C++. A delegate is a reference type variable that holds the reference to a method. The reference can be changed at runtime. Delegates are especially used for implementing events and the call-back methods. All delegates are implicitly derived from the System.

What is the difference between func string string and delegate?

The basic difference between Func and Action delegates is that while the former is used for delegates that return value, the latter can be used for those delegates in which you don't have any return value.

Why we use delegates in C#?

Delegates in C# are similar to function pointers in C++, but C# delegates are type safe. You can pass methods as parameters to a delegate to allow the delegate to point to the method. Delegates are used to define callback methods and implement event handling, and they are declared using the “delegate” keyword.


2 Answers

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.

like image 195
Pop Catalin Avatar answered Sep 18 '22 21:09

Pop Catalin


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.

like image 34
Marc Gravell Avatar answered Sep 19 '22 21:09

Marc Gravell