2008-11-14 2 views
13

Учитывая следующий класс:Есть ли делегат для свойств в C#?

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

я могу сделать

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

что все хорошо. Можно ли сделать то же самое, используя свойство вместо метода? Предпочтительно с чем-то встроенным в .net.

ответ

21

Вы можете создать делегат с помощью отражения:

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

или создать делегат анонимный метод, который устанавливает свойство;

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

Редактировать: используется неправильная перегрузка для CreateDelegate(), необходимо использовать тот, который принимает и объект как цель. Исправлена.

3

Свойства действительно обертки вокруг методы в .Net, так с помощью отражения вы должны быть в состоянии получить делегат (set_PROPERTY и get_PROPERTY), а затем выполнить их ...

См System.Reflection.PropertyInfo

Если есть два методы, которые вы можете использовать для получения/установки значения - GetGetMethod и GetSetMethod.

Таким образом, вы могли бы написать:

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

var setMethod = property.GetSetMethod(); // This will return a MethodInfo class. 
+2

Несмотря на то, что спецификация C# резервирует методы get_P и set_P для любого свойства P, для использования этих методов для свойств не требуется реализация. Это делает его деталью реализации. Не полагайтесь на недокументированные детали реализации. – 2008-11-14 13:05:41

+4

С помощью класса PropertyInfo и GetGet/SetMethod он больше не является проблемой реализации. В данный момент это часть структуры. – Kieron 2008-11-14 13:19:06

+0

Kieron: достаточно справедливо. – 2008-11-14 13:31:32

12

Есть три способа сделать это; во-первых, использовать GetGetMethod()/GetSetMethod() и создать делегат с Delegate.CreateDelegate. Второй - лямбда (не очень полезно для отражения!) [Т. х => x.Foo]. Третий - через выражение (.NET 3.5).

лямбда является самым простым ;-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()); 
    } 

, чтобы показать использование:

 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)); 

Обратите внимание, что если вы хотите, делегат, указывающий на конкретный экземпляр, вы можете использовать затворы для лямбды , или перегрузка CreateDelegate, который принимает и экземпляр.

Смежные вопросы