2012-05-21 10 views
6

Próbuję wykonać następujące czynności:Dynamiczny wysyłka do klasy pochodnej w C#

public abstract BaseClass { 

    public virtual void ReceiveEvent(Event evt) 
    { 
     ProcessEvent(evt as dynamic); 
    } 

    private void ProcessEvent(object evt) 
    { 
     LogManager.Log(@"Received an event that is not being processed! 
         Dispatch fallback"); 
    } 
} 

public DerivedClass: BaseClass { 

    private void ProcessEvent(SpecificEvent evt) 
    { 
     LogManager.Log("Processing Event"); 
    } 
} 

SpecificEvents hit metody rezerwowej zamiast jednego w klasie pochodnej. Używam dynamicznej wysyłki w ramach tej samej klasy przez cały czas i uważam ją za naprawdę użyteczną/czystą. Czy nie będzie działać z klasami pochodnymi, jak pokazano w powyższym przykładzie?

EDYCJA: Wydaje się, że w odpowiedziach występuje pewne zamieszanie. Zasadniczo używam w wykonaniu przez cały czas:

public class SomeClass{ 

    public void DoSomethingDispatcher(SomeObject obj) 
    { 
     ProcessObject(obj as dynamic); 
    } 

    private void DoSomething(SomeObjectType1 obj) 
    { 

    } 

    private void DoSomething(SomeObjectType2 obj) 
    { 

    } 

    private void DoSomething(SomeObjectType3 obj) 
    { 

    } 

    private void DoSomething(object obj) //fallback 
    { 

    } 
} 

działa świetnie na kiedy nie znasz dokładny typ wcześniej i nie chcesz używać wielki switch. Zastanawiasz się, czy można to zaimplementować z dziedziczeniem, w którym klasa podstawowa przechowuje metodę rezerwową, a klasa pochodna zawiera wszystkie bardziej szczegółowe metody.

+0

Moje przypuszczenie jest, że ReceiveEvent jest wywoływana na BaseClass zamiast DerivedClass. Czy próbowałeś przesłonić ReceiveEvent w DerivedClass? Jest wirtualny, więc możesz zrobić "publiczne nadpisanie void ReceiveEvent (Event evt)" Oto kilka informacji na temat metod wirtualnych: http://msdn.microsoft.com/en-us/library/aa645767%28v=vs.71%29. aspx – Davio

Odpowiedz

4

To nie działa, ponieważ nawet jeśli evt jest przekazywany dynamicznie, ProcessEvent nie jest deklarowany jako wirtualny. Oznacza to, że po wywołaniu wywołania ProcessEvent jest ono połączone z jedyną implementacją metody znalezionej w klasie bazowej, a te w klasach pochodnych nigdy nie zostaną wykonane. Ponadto nie można po prostu zadeklarować swojego ProcessEvent jako wirtualnego, ponieważ podpis będzie różny w klasach pochodnych.

Aby Twój kod do pracy zgodnie z oczekiwaniami, można po prostu zastąpić ReceiveEvent w klasach pochodnych pozostawiając ją dokładnie tak samo:

public override void ReceiveEvent(Event evt) 
    { 
     ProcessEvent(evt as dynamic); 
    } 

Jeśli chcesz zarządzać nieobsłużone zdarzenia w klasie bazowej, wystarczy zmienić modyfikator zdarzenia Process w klasie bazowej na chroniony (w przeciwnym razie nie można go wykonać po wywołaniu przez zastąpioną wersję ReceiveEvents).

+0

Tak, tak to mam teraz napisane. Domyślam się, że to najbliższe rozwiązanie. Miałem nadzieję, że mogę przenieść awarię do klasy bazowej, ale wydaje się, że nie jest to możliwe w oparciu o sposób, w jaki opisujesz proces kompilacji. Twoje zdrowie. –

+0

Och właśnie zauważyłem ostatni akapit. Spróbuję tego! –

1

Jaki jest typ Twojego "evta", gdy trafi w ProcessEvent?

Można spojrzeć na Using Type dynamic:

typ to typ statyczny, ale obiekt typu dynamiki omija statycznej kontroli typów. W większości przypadków działa tak, jak ma obiekt typu .

Tak więc, evt nie jest SpecificEvent.

+0

Używam dynamicznego. –

+0

Po pierwsze, dynamiczny będzie traktowany jako obiekt. Wówczas twoje dziedzictwo wydaje się niepoprawne, bez "wirtualnego"/"abstrakcyjnego"/"przesłonięcia" lub nawet "nowego" sposobu. Możesz spróbować umieścić wirtualne w metodach ProcessEvent w BaseClass i przesłonić w DerivedClass. – kerrubin

3

Jeśli metoda nie jest virtual/abstract w klasie bazowej, a metoda nie jest oznaczona jako klasa override, nigdy nie będzie działać.

Również, nie rozumiem użycia tutaj dynamic.

+0

dynamic jest tutaj używany jako dobry sposób trasowania nieznanych typów obiektów do ich odpowiednich programów obsługi, bez użycia instrukcji switch –

1

Aby uzyskać oczekiwane zachowanie należy zastąpić metodę wirtualną:

public DerivedClass: BaseClass 
{ 
    private override void ReceiveEvent(Event evt) 
    { 
     // Process your event here. 
    } 
} 

Z tym kodem, ReceiveEvent w klasie bazowej nie zostanie wywołana, stąd fallback ProcessEvent nie zostanie wywołana. Nie ma powodu, aby używać dynamic.

Powiązane problemy