2008-11-14 10 views
13

Biorąc pod uwagę następujące klasy:Czy istnieje delegat dostępny dla właściwości w języku C#?

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

mogę zrobić

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

co jest dobre. Czy można zrobić to samo, korzystając z właściwości zamiast metody? Najlepiej z czymś wbudowanym w .net.

Odpowiedz

21

Można utworzyć delegata za pomocą refleksji:

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

lub stworzyć delegata do anonimowej metody, która ustawia właściwość;

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

Edytuj: użyte nieprawidłowe przeciążenie dla CreateDelegate(), należy użyć tego, który przyjmuje i obiekt jako cel. Naprawiony.

+0

Myślę, że to zadziała dla potrzeb, które mam. Dzięki! –

+0

Biorąc pod uwagę, że C# ma być moim pierwszym językiem, naprawdę chciałbym, aby zrozumiałem te rzeczy (tworzenie delegata za pomocą refleksji) - brzmi świetnie – JohnIdol

+1

A dla .net 2.0 można zrobić Działanie valueSetter = delegate (wartość int) {tc .Value = value; } –

3

Właściwości są naprawdę owijarki wokół metody w .NET, więc przy użyciu odbicia powinny być w stanie uzyskać delegata (set_PROPERTY i get_PROPERTY), a następnie wykonać je ...

Zobacz System.Reflection.PropertyInfo

Jeśli ma dwa metody, za pomocą których można uzyskać/ustawić wartość - GetGetMethod i GetSetMethod.

Więc można napisać:

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

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

Mimo że specyfikacja C# rezerwuje metody get_P i set_P dla dowolnej właściwości P, nie wymaga implementacji, aby zastosować te metody dla właściwości. To sprawia, że ​​jest to szczegół implementacji. Nie należy polegać na nieudokumentowanych szczegółach implementacji. –

+4

Korzystając z klasy PropertyInfo i GetGet/SetMethod, nie jest to już problem z implementacją. Jest to część struktury w tym momencie. – Kieron

+0

Kieron: Uczciwa. –

12

Istnieją trzy sposoby osiągnięcia tego celu; pierwszym jest użycie GetGetMethod()/GetSetMethod() i utworzenie delegata z Delegate.CreateDelegate. Drugi to lambda (niewiele użyteczne do refleksji!) [Tj. x => x.Foo]. Trzeci to Expression (.NET 3.5).

lambda jest najprostszym ;-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()); 
    } 

aby pokazać wykorzystania:

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

pamiętać, że jeśli chcesz delegata skierowaną do konkretnego przykładu, można użyć zamknięć do lambda lub przeciążenie CreateDelegate, które akceptuje i instancja.

+1

Czy mógłbyś opublikować przykłady? –

+2

btw, nie wysłałem przykład Wyrażenie, ponieważ zwykle jest verbose. Jednak niektóre posty Expression są na moim blogu: http://marcgravell.blogspot.com/search/label/expression –

+0

Przekonaj się o tym łatwo zrozumiałym przykładzie! –

Powiązane problemy