{"id":1093,"date":"2017-11-23T10:05:52","date_gmt":"2017-11-23T09:05:52","guid":{"rendered":"http:\/\/piatkosia.k4be.pl\/wordpress\/?p=1093"},"modified":"2017-11-23T10:05:52","modified_gmt":"2017-11-23T09:05:52","slug":"modyfikatory-dostepu-nie-takie-swiete","status":"publish","type":"post","link":"https:\/\/piatkosia.k4be.pl\/wordpress\/2017\/11\/23\/modyfikatory-dostepu-nie-takie-swiete\/","title":{"rendered":"Modyfikatory dost\u0119pu nie takie \u015bwi\u0119te"},"content":{"rendered":"<p style=\"text-align: justify;\">Choroba ma swoje dobre strony. Jak akurat nie boli, mo\u017cna si\u0119 za co\u015b wzi\u0105\u0107. Na przyk\u0142ad za napisanie posta na blogu, na kt\u00f3rym nie pisa\u0142o si\u0119 nic od prawie roku.<br \/>\nNo to i pisz\u0119;)<\/p>\n<p style=\"text-align: justify;\">Dzi\u015b wezm\u0119 na tapet\u0119 modyfikatory dost\u0119pu. Temat zdaje si\u0119 prosty i oklepany. Mamy ich kilka i s\u0105 dobrze zdefiniowane:<br \/>\n\u2022 Private \u2013 dost\u0119p tylko z klasy<br \/>\n\u2022 Protected \u2013 dost\u0119p z klasy i jej dzieci (klas dziedzicz\u0105cych po klasie)<br \/>\n\u2022 Public \u2013 dost\u0119p sk\u0105d popadnie<br \/>\n\u2022 Internal \u2013 dost\u0119p w zakresie jednego assembly<br \/>\n\u2022 Protected internal\u2013 dost\u0119p w zakresie jednego assembly, nielimitowany dla dzieci (dzieci nie musz\u0105 by\u0107 z tego samego assembly, ale nie-dzieci ju\u017c musz\u0105)<\/p>\n<p style=\"text-align: justify;\">i \u2026<br \/>\n<!--more--><\/p>\n<p style=\"text-align: justify;\">o albo opowiem wam jeszcze jedn\u0105 anegdotk\u0119.<br \/>\nDawno, dawno kto\u015b, nie pami\u0119tam kto, prawdopodobnie wi\u0119cej ni\u017c jedna osoba, w wi\u0119cej ni\u017c jednym momencie powiedzia\u0142a mi mniej wi\u0119cej tak: \u201eWiesz co? Obiektowo to mo\u017cna pisa\u0107 we wszystkim, nawet w asmie \u2013 byle si\u0119 tylko trzyma\u0107 konwencji. Procesor i tak nie my\u015bli obiektowo\u201d.<\/p>\n<p style=\"text-align: justify;\">Te wszystkie modyfikatory s\u0105 wi\u0119c dla nas- dla programist\u00f3w, aby by\u0142o nam \u0142atwiej nadmienionej powy\u017cej konwencji si\u0119 trzyma\u0107. Jako\u015b \u0142atwiej, kiedy nam kompilator zapewnia hermetyczno\u015b\u0107 sam od siebie, przy naszym niewielkim nak\u0142adzie energii, a potem bije nas po \u0142apkach b\u0142\u0119dami kompilacji, kiedy spr\u00f3bujemy u\u017cy\u0107 naszej zmiennej czy funkcji tam, gdzie wg nas nie powinni\u015bmy.<\/p>\n<p style=\"text-align: justify;\">Czy jednak mo\u017cna zadzia\u0142a\u0107 w odwrotny spos\u00f3b? Za\u0142\u00f3\u017cmy \u017ce chcemy jednak dobra\u0107 si\u0119 do zakazanego owocu bez ra\u017c\u0105cego po oczkach \u201ewtf is inaccessible due to its protection level\u201d. Czy to mo\u017cliwe? Oczywi\u015bcie \u017ce tak;) Czy powinni\u015bmy u\u017cywa\u0107 tego w kodzie produkcyjnym? Oczywi\u015bcie \u017ce nie;). Czy wi\u0119c w og\u00f3le podobny myk mo\u017ce przyda\u0107 nam si\u0119 w pracy? Pozostawmy to pytanie na troch\u0119 p\u00f3\u017aniej.<\/p>\n<p style=\"text-align: justify;\">By\u0142am sobie na rozmowie kwalifikacyjnej. Mo\u017ce przemilcz\u0119 do jakiej firmy, co by im asa z r\u0119kawa nie wytr\u0105ca\u0107. I zosta\u0142am zapytana o to, w jaki spos\u00f3b przetestowa\u0142abym metod\u0119 prywatn\u0105.<\/p>\n<p style=\"text-align: justify;\">No c\u00f3\u017c, po pierwsze, to nie widz\u0119 potrzeby testowania tego typu metod \u2013 skoro wed\u0142ug architektury jest ona u\u017cywana tylko wewn\u0105trz mojej klasy, a nie nigdzie na zewn\u0105trz a klasa powstaje raczej po to, aby j\u0105 gdzie\u015b u\u017cy\u0107, raczej bym uzna\u0142a, \u017ce jej kod jest przetestowany poprzez pokrycie testami dost\u0119pnych na zewn\u0105trz metod, kt\u00f3re ich u\u017cywaj\u0105. Ale na upartego mo\u017cna i do tego s\u0142u\u017cy pewien myk zwi\u0105zany z refleksj\u0105.<\/p>\n<ul style=\"text-align: justify;\">\n<li>Stw\u00f3rzmy sobie projekt class library w visual studio o dowolnej nazwie i stw\u00f3rzmy tam<br \/>\nmetod\u0119 o ograniczonym dost\u0119pie<\/li>\n<li>\u00a0przeci\u0105\u017cony ToString (aby pokaza\u0107, \u017ce obiekt si\u0119 stworzy\u0142)<\/li>\n<li>\u00a0Klas\u0119 zagnie\u017cd\u017con\u0105 (nested class) z modyfikatorem private a w niej\n<ul>\n<li>przeci\u0105\u017conego ToStringa (w tym celu co powy\u017cej)<\/li>\n<li>funkcj\u0119 prywatn\u0105<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">I stw\u00f3rzmy drugi projekt, dodaj\u0105c referencj\u0119 do tego pierwszego. A w nim zwyk\u0142y ma\u0142y program konsolowy. Tam zwyk\u0142ym printowaniem udowodnimy, \u017ce si\u0119 da.<br \/>\nI teraz tak. Pozwol\u0119 sobie wklei\u0107 \u00f3w kod i wyt\u0142umaczy\u0107 na czym \u00f3w myk polega:<\/p>\n<pre class=\"brush: csharp; collapse: true\">\r\nusing System;\r\nusing System.Reflection;\r\n\r\nnamespace olejTo\r\n{\r\n    class Program\r\n    {\r\n        static void Main(string[] args)\r\n        {\r\n            var Asm = Assembly.Load(\"FindMeIfYouCan\");\r\n            var types = Asm.GetTypes();\r\n            var SingleType = types[0];\r\n            var FunnyObject = Convert.ChangeType(Activator.CreateInstance(SingleType), SingleType);\r\n            Console.WriteLine(FunnyObject);\r\n            var MethodInfoF = SingleType.GetMethod(\"GetHiddenString\", BindingFlags.NonPublic | BindingFlags.Instance);\r\n            Console.WriteLine(MethodInfoF.Invoke(FunnyObject, null));\r\n            \/\/to teraz zejdziemy sobie odpowiednio g\u0142\u0119biej\r\n            Type nested = SingleType.GetNestedType(\"HyperSecureClass\", BindingFlags.NonPublic | BindingFlags.Instance);\r\n            var StrangeObject = Convert.ChangeType(Activator.CreateInstance(nested), nested);\r\n            var MethodInfoS = nested.GetMethod(\"GetMoreHiddenString\", BindingFlags.NonPublic | BindingFlags.Instance);\r\n            Console.WriteLine(StrangeObject);\r\n            Console.WriteLine(MethodInfoS.Invoke(StrangeObject, null));\r\n            Console.ReadKey();\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p style=\"text-align: justify;\">\nI teraz co si\u0119 dzieje po kolei.<br \/>\nPierwszym co nale\u017cy zrobi\u0107, to wyszuka\u0107 typ w assembly. Kiedy ju\u017c go mamy, to tworzymy sobie obiekt typu, o jakim tylko wiemy \u017ce istnieje. S\u0142u\u017cy do tego funkcja Activator.CreateInstance, kt\u00f3rej parametrem jest \u00f3w typ. Ja chcia\u0142am jeszcze dosta\u0107 co\u015b bardziej konkretniejszego ni\u017c zwracany zwyk\u0142y object, co nie wiadomo czym jest, wi\u0119c hmm\u2026 no jak mam typ w zmiennej, to nie scastuj\u0119 podaj\u0105c po prostu tej zmiennej, wi\u0119c u\u017cy\u0142am do tego funkcji Convert.ChangeType, przyjmuj\u0105cej obiekt, oraz zmienn\u0105 typu. Skojarzenie z np. Convert.ToInt32 nie jest przypadkowe;). ChangeType po prostu jest jej bardziej uniwersaln\u0105 opcj\u0105.<\/p>\n<p style=\"text-align: justify;\">Czas si\u0119 zabra\u0107 za funkcj\u0119. Intellisence nam nie podpowie jej (brak na li\u015bcie) bo przecie\u017c jest prywatna ale\u2026 no przecie\u017c mamy refleksj\u0119:).<br \/>\nPierwsze wi\u0119c co robimy, to szukamy funkcji o zadanej nazwie (dla odmiany, bo ile mo\u017cna szuka\u0107 po tablicach), przy czym mo\u017cna mu poda\u0107 tzw flagi bindowania. Czyli \u017ceby poszuka\u0142 tam, gdzie zwykle nie zagl\u0105da;). No i znalaz\u0142, a jak znalaz\u0142 to zwr\u00f3ci\u0142 MethodInfo dla tej funkcji. A jak ju\u017c mamy MethodInfo, to mo\u017cna je invoken\u0105\u0107\u2026 wywo\u0142a\u0107 znaczy si\u0119.<br \/>\nFunkcja Invoke z klasy MethodInfo przyjmuje na przyk\u0142ad dwa parametry i s\u0105 to kolejno: obiekt na rzecz kt\u00f3rego mamy wywo\u0142a\u0107 dan\u0105 funkcj\u0119, oraz list\u0119 parametr\u00f3w tej funkcji.<\/p>\n<p style=\"text-align: justify;\">Przejd\u017amy do trudniejszego przypadku \u2013 naszej g\u0142\u0119boko ukrytej prywatnej klasy zagnie\u017cd\u017conej. Przypadek niby bardziej zawi\u0142y, jednak analogiczny do poprzedniego. Tyle \u017ce pobranie typu wymaga od nas wywo\u0142anie na znanym nam ju\u017c typie funkcji GetNestedType(\u201enazwa\u201d, bindflagi) i tyle. Jak ju\u017c mamy typ o jaki nam chodzi, post\u0119pujemy analogicznie do poprzedniego. I jaki b\u0119dzie output wy\u017cej wymienionego programu? To zale\u017cy co dali\u015bcie w funkcjach swojej klasy:)<br \/>\nU mnie wygl\u0105da\u0142o to tak:<\/p>\n<p style=\"text-align: justify;\">Podsumowuj\u0105c:<br \/>\nOgraniczenia s\u0105 dla programisty, nie dla maszyny. Maszyna wie, co zrobi\u0107 z tym co napisali\u015bmy, to my nie zawsze wiemy co chcemy napisa\u0107. Albo nie do ko\u0144ca mamy \u015bwiadomo\u015b\u0107 tego, co piszemy. A ju\u017c zw\u0142aszcza jak piszemy program w zespole.<br \/>\nOmijanie podstawowych mechanizm\u00f3w j\u0119zyka nie jest jako\u015b specjalnie trudne i czasami si\u0119 przydaje \u2013 cho\u0107by w testach.<br \/>\nOczywi\u015bcie, zmiana private na public by\u0142aby szybsza;) wi\u0119c po co sobie utrudnia\u0107 \u017cycie?<br \/>\nJeszcze jedno \u2013 pami\u0119tajcie, \u017ce u\u017cycie modyfikator\u00f3w dost\u0119pu nie blokuje mo\u017cliwo\u015bci wywo\u0142ania chronionego kodu- ma to jedynie u\u0142atwi\u0107 prac\u0119 programistom.<br \/>\nZ dwojga z\u0142ego lepiej kod zmodyfikowa\u0107 ni\u017c stosowa\u0107 \u201ehacki\u201d, po to, aby kod by\u0142 czytelniejszy i \u0142atwiejszy w utrzymaniu.<\/p>\n<p style=\"text-align: justify;\">Link do projektu na githubie: <a href=\"https:\/\/github.com\/Piatkosia\/olejTo\" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/Piatkosia\/olejTo<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Choroba ma swoje dobre strony. Jak akurat nie boli, mo\u017cna si\u0119 za co\u015b wzi\u0105\u0107. Na przyk\u0142ad za napisanie posta na blogu, na kt\u00f3rym nie pisa\u0142o<\/p>\n<div class=\"more-link-wrapper\"><a class=\"more-link\" href=\"https:\/\/piatkosia.k4be.pl\/wordpress\/2017\/11\/23\/modyfikatory-dostepu-nie-takie-swiete\/\">Lecim dalej<span class=\"screen-reader-text\">Modyfikatory dost\u0119pu nie takie \u015bwi\u0119te<\/span> <i class=\"fas fa-angle-right\"><\/i><\/a><\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[83],"tags":[],"class_list":["post-1093","post","type-post","status-publish","format-standard","hentry","category-c_sharp","entry"],"_links":{"self":[{"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/posts\/1093","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/comments?post=1093"}],"version-history":[{"count":1,"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/posts\/1093\/revisions"}],"predecessor-version":[{"id":1094,"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/posts\/1093\/revisions\/1094"}],"wp:attachment":[{"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/media?parent=1093"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/categories?post=1093"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/tags?post=1093"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}