-
Notifications
You must be signed in to change notification settings - Fork 0
Home
Przypuścmy, żę mamy 2 klasy. Klasa A i klasa B.
Klasa A implementuje pewne funkcjonalności, tak samo jak klasa B. Nie trzymamy się tutaj żadego wzorca! Niech klasa A przetwarza jakieś informacje od użytkownika a klasa B zapisuje te informacje do “czegoś” – plik, baza, nie ważne. Wychodząc z tego założenia klasa A musi utworzyć sobie obiekt klasy B aby wywołać metodę zapisującą te dane. Najprościej jest stworzć metodę publiczną w klasie B i ją wywołać prawda?
public class A { private string userName; private B b;
public A()
{
b = new B();
}
private void GetUserName()
{
userName = Console.ReadLine();
b.InsertData(userName);
}
}
public class B { public void InsertData(string userName) { //insert userName } } public class A { private string userName; private B b;
public A()
{
b = new B();
}
private void GetUserName()
{
userName = Console.ReadLine();
b.InsertData(userName);
}
}
public class B { public void InsertData(string userName) { //insert userName } }
A co jeżeli ktoś będzie chciał zrobić nam przysłowiowe kuku i w swoim projekcie dołączy referencję naszej dll’ki, exe’ca?
kuku
Ano będzie coś takiego jak na screenie powyżej. Ktoś będzie mógł wywołać naszą metodę InsertData. Ja wiem… zabezpieczamy się na różnych poziomach… logowanie użytkownika, sesje i temu podobne. Ale nie o to mi chodzi. Chodzi mi o to aby ten nieszczęsny public zamienić na private i tu właśnie z pomocą przychodzą nam delegaty.
Przytaczając przykład, który opisałem wcześniej postaram się wyjaśnić co można zrobić aby taka sytuacja się nie powtórzyła.
Mając za zadanie napisanie klas(y) i nieumożliwienie osobom postronnym wywołania metod mocno wrażliwych (jak InsertData) pierwsze co powinniśmy zrobić to te właśnie metody zamienić na metody prywatne. I teraz pewna magia :) Dodajemy delegat
internal delegate void InsertDataDelegate(string userName);
internal delegate void InsertDataDelegate(string userName);
internal jest tu użyty celowo. Następnie w klasie, w której mamy naszą metodę insertującą dodajemy metodę, która zwraca nam wcześniej zadeklarowany delegat
internal InsertDataDelegate GetInsertDataDelegate() { return InsertData; } internal InsertDataDelegate GetInsertDataDelegate() { return InsertData; }
Jak widać metoda zwraca nam tak naprawdę definicję metody InsertData, która wygląda właśnie tak:
private void InsertData(string userName) { Console.WriteLine(userName); }
private void InsertData(string userName) { Console.WriteLine(userName); }
W tym momencie możemy w klasie, która tworzy sobie obiekt klasy zawierającej metodę insertujcą dodać odpowiednie linijki:
var dc = new DelegateClass(); InsertDataDelegate insert = dc.GetInsertDataDelegate(); insert("sebastian");
var dc = new DelegateClass(); InsertDataDelegate insert = dc.GetInsertDataDelegate(); insert("sebastian");
W ten oto prosty sposób możemy wywołać metodę prywatną dzięki delegatom. Prawda, że proste? :)
Patrząc teraz na przysłowiowe “kuku”, po podłączeniu referencji naszego projektu do innego, stworzeniu zmiennej naszej klasy intellisense pokaże coś takiego:
delegates
Wiem, tak samo jak i Wy, że nie jest to do końca rozwiązanie problemu ponieważ istnieją sposoby na to aby wywołać metody prywatne w inny sposób ale o tym może poźniej. Tak czy inaczej… jeżeli chcecie chronić swój kod używajcie obfuscator’ów będzi trudniej osobom postronnym zrobić naszej aplikacji “kuku” ;)