2011-06-23 13 views
6

Mam abstrakcyjną klasę "Action", która wyprowadziła typy ActionAppointment, ActionCall, ActionEmail i ActionLetter. Próbuję napisać funkcję, która DRY się naszą warstwą usługi, więc nie piszemy już 5 razy połączeń CRUD.C# Pattern dla kodu klasy abstrakcyjnej specyficznej

mam w naszej warstwie usług pewną logikę aktualizacji (wiele innego kodu usunięte dla zwięzłość):.

private IServiceResponse UpdateAction<T>(T action, string originalActionStatus) where T : Action 
{ 
     if (action.GetType() == typeof(Action)) 
     { 
      _actionRepository.Update(action); 
     } 
     else if (action.GetType() == typeof(ActionAppointment)) 
     { 
      _actionAppointmentRepository.Update(action as ActionAppointment); 
     } 
     else if (action.GetType() == typeof(ActionCall)) 
     { 
      _actionCallRepository.Update(action as ActionCall); 
     } 
     else if (action.GetType() == typeof(ActionEmail)) 
     { 
      _actionEmailRepository.Update(action as ActionEmail); 
     } 
     else if (action.GetType() == typeof(ActionLetter)) 
     { 
      _actionLetterRepository.Update(action as ActionLetter); 
     } 
} 

Niestety, jak nasze repozytoria są ustawione, muszę użyć specjalnie nazwanych repozytoriów (czyli ja nie można zaktualizować ActionLettera za pośrednictwem _actionRepository, mimo że pochodzi z Action)

Czytałem na różnych wzorach, i to brzmi jak coś podobnego do Factory Pattern, ale nie widzę jak to zrobić.

Czy brakuje mi czegoś głupiego?

+1

Możesz wziąć pod uwagę wzorzec * Visitor * (http://en.wikipedia.org/wiki/Visitor_pattern). –

+2

Tak, wzór fabryczny jest rozwiązaniem. Twoje repozytoria muszą mieć wspólną klasę podstawową lub implementować interfejs. Wszystkie muszą mieć metodę Update, która akceptuje obiekt wpisany jako Action. Fabryka akceptuje typ jako parametr (niezależnie od formy, nazwy, typu, wyliczenia, jeśli jest dostępny) i zwraca poprawne repozytorium. To tyle. Czy istnieje szczególny punkt dezorientacji w kwestii wdrażania fabryki? – Sisyphus

+0

Nie jestem pewien, jak zaimplementować wzorzec fabryczny dla tego, ponieważ IRepository jest generyczny na podstawie każdego obiektu modelu domeny. – mandreko

Odpowiedz

11

Nie możesz napisać przeciążenia tej metody dla każdego typu akcji? Zapomnij o rzeczach: <T> i typeof - to, co robisz, polega na ręcznym wdrażaniu wbudowanej funkcji języka (przeciążanie metod), a także w delikatny sposób.

+3

Tak, właśnie o to chodzi w przypadku polimorfizmu i dziedziczenia. –

+0

Kod został wcześniej napisany jako metoda dla każdego typu akcji. Po prostu próbuję to WYDUSZCZYĆ, ale chyba mogę OSUSZCZYĆ niektóre z udostępnianych komponentów, ale mam w każdym z nich konkretny kod repozytorium. – mandreko

+0

@Matt: Twoje urządzenie if-else nie tworzy żadnego DRYERA, to na pewno. –

-2

Niech odwrócić logikę tutaj:

abstract class Action { 
    protected abstract Repository GetRepository(); 
    protected void Update(){ 
     this.GetRepository().Update(this); 
    } 
} 

Wszystko co musisz zrobić, to zastąpić GetRepository w każdej z klas wynikających. Na przykład:

class ActionAppointment : Action { 
    protected override Repository GetRepository() { 
     return _actionAppointmentRepository; 
    } 
} 
+1

niezbyt dobry pomysł, aby klasa modelowa wiedziała, jak jest przechowywana. –

+2

-1, Wstrzykiwanie usług (nawet repozytoriów) do obiektów domeny jest złą praktyką. – smartcaveman

+0

Uzgodniono z smartcaveman. Naruszenie naszych zasad narusza nasze zasady. – mandreko

Powiązane problemy