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.
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With