{"id":83,"date":"2014-07-19T23:57:07","date_gmt":"2014-07-19T20:57:07","guid":{"rendered":"https:\/\/gokhan-gokalp.com\/?p=83"},"modified":"2014-07-20T00:33:04","modified_gmt":"2014-07-19T21:33:04","slug":"plug-in-tabanli-uygulama-gelistirme-ve-hesap-makinesi-ornegi","status":"publish","type":"post","link":"https:\/\/gokhan-gokalp.com\/tr\/plug-in-tabanli-uygulama-gelistirme-ve-hesap-makinesi-ornegi\/","title":{"rendered":"Plug-in Tabanl\u0131 Uygulama Geli\u015ftirme ve Hesap Makinesi \u00d6rne\u011fi"},"content":{"rendered":"<h4>Neden plug-in tabanl\u0131 uygulama geli\u015ftirmeye ihtiya\u00e7 duyar\u0131z?<\/h4>\n<p>Biz yaz\u0131l\u0131mc\u0131lar\u0131n kar\u015f\u0131la\u015ft\u0131klar\u0131 en b\u00fcy\u00fck sorunlardan birisi, bitirmi\u015f oldu\u011fumuz bir uygulaman\u0131n\u00a0\u00fczerine ek bir \u00f6zellik istenmesidir. \u015eahsen bu beni delirten bir \u015fey. :)<br \/>\n\u0130\u015fte bu tarz durumlar\u0131n \u00f6n\u00fcne ge\u00e7memizi sa\u011flayan etmenlerden birisidir plug-in tabanl\u0131 uygulama geli\u015ftirme.\u00a0Bu yoldaki en b\u00fcy\u00fck dostumuz <strong>Reflection<\/strong> namespace&#8217;idir.<\/p>\n<p>K\u0131saca Reflection&#8217;dan bahsetmek gerekirse nesneler ile ilgili \u00e7al\u0131\u015fma zaman\u0131nda nesneye ait property ve metotlara eri\u015febilmemizi ve metotlar\u0131 \u00e7a\u011f\u0131rabilmemizi sa\u011flar.<\/p>\n<h4>\u015eimdi konumuza Hesap Makinesi \u00f6rne\u011fimizle devam edelim.<\/h4>\n<p>Projemiz k\u0131saca: \u0130\u015flem fonksiyonlar\u0131 plug-in olarak tasarlanacak bir hesap makinesi olacakt\u0131r.<\/p>\n<p>\u00d6ncelikle projemiz 3 par\u00e7adan olu\u015facakt\u0131r.<\/p>\n<ul>\n<li><strong>Contracts<\/strong> (Hesap makinemize plug-in geli\u015ftirirken Application Domain&#8217;ler aras\u0131 plug-in komutlar\u0131m\u0131z i\u00e7in ana interface tan\u0131mlamam\u0131z)<\/li>\n<li><strong>MainAppicationDomain<\/strong> (Hesap makinesi uygulamam\u0131z ve Plug-in&#8217;leri \u00e7al\u0131\u015ft\u0131racak olan proje yer alacak)<\/li>\n<li><strong>PlugInApplicationDomain<\/strong> (Eklenmi\u015f olan plug-in&#8217;leri taray\u0131p kendi ApplicationDomainin&#8217;de instance&#8217;lar\u0131n\u0131 t\u00fcretip MainApplicationDomain&#8217;imize g\u00f6nderecek olan PlugInEngine projemiz yer alacak)<\/li>\n<\/ul>\n<p>\u00d6ncelikle Contract&#8217;\u0131m\u0131z i\u00e7in <strong>Contracts<\/strong> isminde yeni bir klas\u00f6r ekleyip i\u00e7erisine\u00a0<strong>GG.PlugInTabanliHesapMakinesi.Contracts <\/strong>isimli bir ClassLibrary projesi ekliyorum.\u00a0\u0130\u00e7erisine\u00a0<strong>ICalculationCommand<\/strong> isimli bir interface tan\u0131ml\u0131yorum.<\/p>\n<pre class=\"lang:c# decode:true\" title=\"ICalculationCommand\">namespace GG.PlugInTabanliHesapMakinesi.Contracts\r\n{\r\n    \/\/\/ &lt;summary&gt;\r\n    \/\/\/ Hesap makinemiz i\u00e7in plug-in tabanl\u0131 olarak geli\u015ftirece\u011fimiz hesaplama fonksiyonlar\u0131m\u0131z i\u00e7in ApplicationDomain'ler aras\u0131 contract'\u0131m\u0131z.\r\n    \/\/\/ &lt;\/summary&gt;\r\n    public interface ICalculationCommand\r\n    {\r\n        \/\/\/ &lt;summary&gt;\r\n        \/\/\/ Hesaplama fonksiyon ad\u0131\r\n        \/\/\/ &lt;\/summary&gt;\r\n        string Name { get; }\r\n\r\n        \/\/\/ &lt;summary&gt;\r\n        \/\/\/ 2 arg\u00fcmanl\u0131 hesaplama fonksiyonumuz i\u00e7in execute edecek metotumuz\r\n        \/\/\/ &lt;\/summary&gt;\r\n        \/\/\/ &lt;param name=\"arg1\"&gt;&lt;\/param&gt;\r\n        \/\/\/ &lt;param name=\"arg2\"&gt;&lt;\/param&gt;\r\n        \/\/\/ &lt;returns&gt;&lt;\/returns&gt;\r\n        double Execute(double arg1, double arg2);\r\n    }\r\n}<\/pre>\n<p>Evet contract&#8217;\u0131m\u0131z haz\u0131r durumda.<br \/>\n\u015eimdi s\u0131ra geldi <strong>PlugInApplicationDomain<\/strong>&#8216;imizi olu\u015fturmaya.<\/p>\n<p>Yine \u00f6ncelikle projemize <strong>PlugInApplicationDomain\u00a0<\/strong>isminde bir klas\u00f6r daha ekleyerek i\u00e7erisine\u00a0<strong>GG.PlugInTabanliHesapMakinesi.PlugInEngine<\/strong>\u00a0isimli bir ClassLibrary projesi daha\u00a0ekleyerek\u00a0<strong>GG.PlugInTabanliHesapMakinesi.Contracts\u00a0<\/strong>projemizi referans olarak ekliyorum.<\/p>\n<p>Bu proje plug-in&#8217;lerimiz taray\u0131p\u00a0<strong>ICalculationCommand\u00a0<\/strong>contract&#8217;\u0131m\u0131zdan inherit alan assembly&#8217;lerimizi bulup instance&#8217;lerini \u00fcretip\u00a0<strong>MainAppicationDomain<\/strong>\u00a0&#8216;imize g\u00f6nderecek olan class&#8217;\u0131m\u0131z\u00a0yer alacakt\u0131r.<\/p>\n<p><strong>GG.PlugInTabanliHesapMakinesi.PlugInEngine <\/strong>projemizin i\u00e7erisine\u00a0<strong>CalculationCommandCommunicator\u00a0<\/strong>isimli bir class ekliyorum ve\u00a0<strong>MarshalByRefObject<\/strong>, <strong>ICalculationCommand<\/strong> interface&#8217;lerinden t\u00fcretiyorum.<\/p>\n<p>Bu class&#8217;\u0131m\u0131z\u0131n amac\u0131: Geli\u015ftirece\u011fimiz olan plug-in&#8217;lerin sarmalan\u0131p serialize hale getirilip (<strong>MarshalByRefObject <\/strong>arac\u0131l\u0131\u011f\u0131 ile)\u00a0<strong>farkl\u0131 bir ApplicationDomain<\/strong>&#8216;de instance&#8217;s\u0131n\u0131n ve metotlar\u0131n\u0131n kullan\u0131lmas\u0131n\u0131\u00a0sa\u011flayacakt\u0131r.<\/p>\n<p>\u0130\u015fin \u00f6z\u00fcnde orjinal nesnemizmi\u015f gibi davranan <strong>Transparent Proxy<\/strong>&#8216;ler var asl\u0131nda. Bu sayede uygulamam\u0131z i\u00e7in Plug-in geli\u015ftiricilerimiz extradan <strong>MarshalByRefObject<\/strong>&#8216;den t\u00fcreyen nesnelere ihtiya\u00e7 duymayacakt\u0131r sadece <strong>Contract&#8217;<\/strong>\u0131m\u0131z yeterli olacakt\u0131r. Aksi durumda onlara contract&#8217;\u0131m\u0131z haricinde\u00a0MarshalByRefObject&#8217;den de\u00a0t\u00fcretmelerini s\u00f6ylemek pekte ho\u015f bir durum\u00a0olmayacakt\u0131r, eminim. :)<\/p>\n<p>\u015eimdi class&#8217;\u0131m\u0131za bir g\u00f6z atal\u0131m:<\/p>\n<pre class=\"lang:c# decode:true\">using GG.PlugInTabanliHesapMakinesi.Contracts;\r\nusing System;\r\n\r\nnamespace GG.PlugInTabanliHesapMakinesi.PlugInEngine\r\n{\r\n    \/\/\/ &lt;summary&gt;\r\n    \/\/\/ Plug-in'lerimizi serialize hale getirecek class'\u0131m\u0131z.\r\n    \/\/\/ &lt;\/summary&gt;\r\n    public class CalculationCommandCommunicator : MarshalByRefObject, ICalculationCommand\r\n    {\r\n        #region Constructor\r\n        \/\/\/ &lt;summary&gt;\r\n        \/\/\/ CalculationCommand t\u00fcr\u00fcndeki ger\u00e7ek nesnemiz.\r\n        \/\/\/ &lt;\/summary&gt;\r\n        private ICalculationCommand _RealCommand;\r\n        public CalculationCommandCommunicator(ICalculationCommand realCommand)\r\n        {\r\n            this._RealCommand = realCommand;\r\n        }\r\n        #endregion\r\n\r\n        #region Properties\r\n        \/\/\/ &lt;summary&gt;\r\n        \/\/\/ Hesaplama fonksiyon ad\u0131\r\n        \/\/\/ &lt;\/summary&gt;\r\n        public string Name { get { return this._RealCommand.Name; } }\r\n        #endregion\r\n\r\n        #region Public Methods\r\n        \/\/\/ &lt;summary&gt;\r\n        \/\/\/ 2 arg\u00fcmanl\u0131 hesaplama fonksiyonumuz i\u00e7in execute edecek metotumuz\r\n        \/\/\/ &lt;\/summary&gt;\r\n        \/\/\/ &lt;param name=\"arg1\"&gt;&lt;\/param&gt;\r\n        \/\/\/ &lt;param name=\"arg2\"&gt;&lt;\/param&gt;\r\n        \/\/\/ &lt;returns&gt;&lt;\/returns&gt;\r\n        public double Execute(double arg1, double arg2)\r\n        {\r\n            return this._RealCommand.Execute(arg1, arg2);\r\n        }\r\n\r\n        public override string ToString()\r\n        {\r\n            return this.Name;\r\n        }\r\n        #endregion\r\n    }\r\n}<\/pre>\n<p><strong>CalculationCommandCommunicator\u00a0<\/strong>class&#8217;\u0131m\u0131z\u0131da tamamlam\u0131\u015f olduk.<\/p>\n<p>\u015eimdi s\u0131ra geldi plug-in&#8217;lerimizi bulup instance&#8217;lar\u0131n\u0131 t\u00fcretip bir liste halinde <strong>MainApplicationDomain&#8217;<\/strong>imize g\u00f6nderecek olan\u00a0<strong>PlugInEngine<\/strong> class&#8217;\u0131m\u0131z\u0131 olu\u015fturmaya.<\/p>\n<pre class=\"lang:c# decode:true\">using GG.PlugInTabanliHesapMakinesi.Contracts;\r\nusing System;\r\nusing System.IO;\r\nusing System.Collections.Generic;\r\nusing System.Linq;\r\nusing System.Reflection;\r\n\r\nnamespace GG.PlugInTabanliHesapMakinesi.PlugInEngine\r\n{\r\n    \/\/\/ &lt;summary&gt;\r\n    \/\/\/ Plug-in'lerimizi bulup instance'lar\u0131n\u0131 t\u00fcretip geyire d\u00f6nderecek olan class'\u0131m\u0131z.\r\n    \/\/\/ &lt;\/summary&gt;\r\n    public class PlugInEngine : MarshalByRefObject\r\n    {\r\n        public List&lt;ICalculationCommand&gt; LoadPlugInCommands()\r\n        {\r\n            var commandList = new List&lt;ICalculationCommand&gt;(); \/\/ Plug-in'lerimizin instance'lar\u0131n\u0131 ekleyece\u011fimiz listemiz\r\n            string basePath = AppDomain.CurrentDomain.BaseDirectory + \"PlugIns\"; \/\/ Plug-in'lerimizi bulmak i\u00e7in tar\u0131yaca\u011f\u0131m\u0131z ana PlugIns path'imiz.\r\n\r\n            foreach (var filePath in Directory.GetFiles(basePath, \"*.dll\")) \/\/ GetFiles metotuna yazd\u0131\u011f\u0131m\u0131z \"*.dll\" patterni ile ilgili path'imizdeki assembly'lerimizi buluyoruz\r\n            {\r\n                var loadedAssembly = Assembly.LoadFile(filePath); \/\/ Reflection namespace'si alt\u0131ndaki Assembly s\u0131n\u0131f\u0131 ile ilgili assembly'imizi y\u00fckl\u00fcyoruz\r\n                var calculationTypes = loadedAssembly.GetTypes().Where(t =&gt; typeof(ICalculationCommand).IsAssignableFrom(t)); \/\/ ICalculationCommand'dan inherit alan nesneleri buluyoruz\r\n\r\n                foreach (var calculationType in calculationTypes)\r\n                {\r\n                    var cmd = Activator.CreateInstance(calculationType); \/\/ Instance'sini \u00fcretiyoruz\r\n                    commandList.Add(new CalculationCommandCommunicator(cmd as ICalculationCommand)); \/\/ \u00dcretti\u011fimiz instance'\u0131m\u0131z\u0131 haz\u0131rlam\u0131\u015f oldu\u011fumuz bizim i\u00e7in serialize hale getirecek olan CalculationCommandCommunicator ile sarmal\u0131yor ve commandList'imize ekliyoruz\r\n                }\r\n            }\r\n\r\n            return commandList;\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p><strong>PlugInEngine<\/strong> s\u0131n\u0131f\u0131m\u0131z\u0131da\u00a0<strong>MarshalByRefObject&#8217;<\/strong>den t\u00fcreterek haz\u0131rlam\u0131\u015f olduk.<\/p>\n<p>\u015eimdi s\u0131ra geldi \u015fu bahsedip durdu\u011fumuz me\u015fhur <strong>MainApplicationDomain&#8217;<\/strong>imizi olu\u015fturmaya. :) Hemen <strong>MainApplicationDomain\u00a0<\/strong>isminde bir klas\u00f6r daha ekleyerek i\u00e7erisine <strong>GG.PlugInTabanliHesapMakinesi.PlugInStarter<\/strong> isimli bir ClassLibrary projesi daha ekliyorum.\u00a0<strong>GG.PlugInTabanliHesapMakinesi.Contracts <\/strong>ve\u00a0<strong>GG.PlugInTabanliHesapMakinesi.PlugInEngine<\/strong>\u00a0projelerini\u00a0referans olarak eklemeyide unutmayal\u0131m. :)<br \/>\nBu proje plug-in&#8217;lerimiz i\u00e7in olan <strong>PlugInApplicationDomain<\/strong> &#8216;imizi baz\u0131 yetkilerle olu\u015fturacak ve tan\u0131ml\u0131 plug-in&#8217;leri hesap makinesi uygulamam\u0131za dahil edecektir.<\/p>\n<p>Hemen\u00a0<strong>GG.PlugInTabanliHesapMakinesi.PlugInStarter <\/strong>isimli library&#8217;mize\u00a0<strong>PlugInStarter<\/strong> isimli bir class ekliyorum ve kodlara bir g\u00f6z atal\u0131m:<\/p>\n<pre class=\"lang:c# decode:true\">using GG.PlugInTabanliHesapMakinesi.Contracts;\r\nusing System;\r\nusing System.Collections.Generic;\r\nusing System.Security;\r\nusing System.Security.Permissions;\r\n\r\nnamespace GG.PlugInTabanliHesapMakinesi.PlugInStarter\r\n{\r\n    \/\/\/ &lt;summary&gt;\r\n    \/\/\/ Ana hesap makinesi uygulamam\u0131z i\u00e7inde plug-in'lerimizi \u00e7al\u0131\u015ft\u0131racak olan class'\u0131m\u0131z.\r\n    \/\/\/ &lt;\/summary&gt;\r\n    public static class PlugInStarter\r\n    {\r\n        public static List&lt;ICalculationCommand&gt; Start()\r\n        {\r\n            #region Create AppDomain\r\n            var setUp = new AppDomainSetup();\r\n            setUp.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;\r\n\r\n            \/\/ K\u0131s\u0131tl\u0131 ve g\u00fcvenli olarak \u00fcretiyoruz. (CAS)\r\n            var permissionSet = new PermissionSet(PermissionState.None);\r\n            permissionSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution)); \/\/ \u00c7al\u0131\u015ft\u0131rabilmek i\u00e7in yetki veriyoruz\r\n            permissionSet.AddPermission(new FileIOPermission(FileIOPermissionAccess.PathDiscovery, AppDomain.CurrentDomain.BaseDirectory)); \/\/ Sadece gerekli klas\u00f6r\u00fcm\u00fcze ke\u015fife izin veriyoruz\r\n            permissionSet.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read, AppDomain.CurrentDomain.BaseDirectory + \"PlugIns\")); \/\/ Sadece gerekli klas\u00f6r\u00fcm\u00fcze okuma izni veriyoruz\r\n\r\n            var plugInApplicationDomain = AppDomain.CreateDomain(\"Plug In App Domain\", null, setUp, permissionSet); \/\/ Gerekli bilgileri vererek domain ismi, kurulum bilgisi ve g\u00fcvenlik izinleri gibi domainimizi \u00fcretiyoruz\r\n            #endregion\r\n\r\n            \/\/ Di\u011fer application domain'imizde PlugInEngine'mizi \u00fcretip bu objenin bize ObjectHandle bilgisini geriye d\u00f6ner.\r\n            var plugInEngine = (PlugInEngine.PlugInEngine)plugInApplicationDomain.CreateInstanceAndUnwrap(typeof(PlugInEngine.PlugInEngine).Assembly.FullName, typeof(PlugInEngine.PlugInEngine).FullName);\r\n\r\n            return plugInEngine.LoadPlugInCommands();\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p><strong>PlugInStarter<\/strong>\u00a0class&#8217;\u0131m\u0131z\u0131da haz\u0131rlam\u0131\u015f olduk.<\/p>\n<p>\u015eimdi s\u0131ra geldi yine\u00a0<strong>MainApplicationDomain\u00a0<\/strong>klas\u00f6r\u00fc i\u00e7erisinde UI katman\u0131m\u0131z\u0131 haz\u0131rlamaya. Hemen bir\u00a0<strong>GG.PlugInTabanliHesapMakinesi.WinUI\u00a0<\/strong>isminde bir Windows Application projesi ekliyorum <strong>GG.PlugInTabanliHesapMakinesi.Contracts <\/strong>ve\u00a0<strong>GG.PlugInTabanliHesapMakinesi.PlugInStarter <\/strong>projelerini referans olarak ekleyip\u00a0<strong>UI<\/strong> formunu a\u015fa\u011f\u0131daki \u015fekilde tasarl\u0131yorum.<\/p>\n<p><img decoding=\"async\" class=\"size-full wp-image-100 aligncenter lazyload\" data-src=\"\/wp-content\/uploads\/2014\/07\/WinUIHesapMakinesi.jpg\" alt=\"WinUIHesapMakinesi\" width=\"365\" height=\"233\" data-srcset=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2014\/07\/WinUIHesapMakinesi.jpg 365w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2014\/07\/WinUIHesapMakinesi-300x191.jpg 300w\" data-sizes=\"(max-width: 365px) 100vw, 365px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 365px; --smush-placeholder-aspect-ratio: 365\/233;\" \/><br \/>\nSay\u0131 1 ve Say\u0131 2 k\u0131s\u0131mlar\u0131na i\u015flem yapaca\u011f\u0131m\u0131z arg1 ve arg2 gelecek, sa\u011f tarafdaki ListBox&#8217;a ise Command&#8217;lar\u0131m\u0131z gelecek yani plug-in&#8217;lerimiz.<\/p>\n<p>Hemen ilgili formumuzun kod taraf\u0131na bir g\u00f6z atal\u0131m:<\/p>\n<pre class=\"lang:c# decode:true\">using GG.PlugInTabanliHesapMakinesi.Contracts;\r\nusing System;\r\nusing System.Collections.Generic;\r\nusing System.Windows.Forms;\r\n\r\nnamespace GG.PlugInTabanliHesapMakinesi.WinUI\r\n{\r\n    public partial class frmMain : Form\r\n    {\r\n        public frmMain()\r\n        {\r\n            InitializeComponent();\r\n\r\n            \/\/ PlugInStarter plug-inlerimizi ilgili application domain'de instance'lar\u0131n\u0131 \u00fcretip bize geriye d\u00f6n\u00fcyor.\r\n            List&lt;ICalculationCommand&gt; cmdList = PlugInStarter.PlugInStarter.Start();\r\n            lstCommands.Items.AddRange(cmdList.ToArray());\r\n        }\r\n\r\n        private void btnHesapla_Click(object sender, EventArgs e)\r\n        {\r\n            if (lstCommands.SelectedItem != null)\r\n            {\r\n                var cmd = lstCommands.SelectedItem as ICalculationCommand;\r\n                var arg1 = Convert.ToDouble(txtSayi1.Text);\r\n                var arg2 = Convert.ToDouble(txtSayi2.Text);\r\n                var result = cmd.Execute(arg1, arg2);\r\n\r\n                MessageBox.Show(string.Format(\"Sonu\u00e7: {0}\", result));\r\n            }\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p>\u0130\u015fte bu kadar.\u00a0<strong>PlugInStarter<\/strong> arac\u0131l\u0131\u011f\u0131 ile ilgili plug-in&#8217;lerimiz listemize ekleniyor ve <strong>Execute<\/strong> metotumuz arac\u0131l\u0131\u011f\u0131 ile kullan\u0131labilir bir hale geliyor. Uygulamam\u0131z neredeyse tamam. :) Geriye sadece \u00f6rnek bir plug-in tasarlamak kald\u0131. Hi\u00e7 fonksiyonsuz bir hesap makinesi i\u015fimize yaramayacakt\u0131r galiba. :P<\/p>\n<p>\u015eimdi solution&#8217;umuza\u00a0<strong>PlugIns\u00a0<\/strong>isimli bir klas\u00f6r daha ekleyerek\u00a0<strong>ABCSirketi.ToplamaPlugIn\u00a0<\/strong>isimli bir ClassLibrary daha ekliyorum. (Sanki ba\u015fka bir firma taraf\u0131ndan geli\u015ftirilmi\u015f gibi bir plug-in :))<\/p>\n<p>\u0130lgili plug-in&#8217;i geli\u015ftirebilmeleri i\u00e7in\u00a0da\u011f\u0131tt\u0131\u011f\u0131m\u0131z <strong>Contract<\/strong>&#8216;\u0131m\u0131z referans olarak ekleniyor. Hemen\u00a0<strong>ToplamaIslemi<\/strong> isminde bir class olu\u015fturuyorum ve <strong>ICalculationCommand<\/strong> interface&#8217;mizden t\u00fcretiyorum.<\/p>\n<p>Kodlar\u0131m\u0131za bakmadan \u00f6nce ilgili\u00a0<strong>ABCSirketi.ToplamaPlugIn\u00a0<\/strong>projemizin derlendi\u011finde <strong>output<\/strong> klas\u00f6r\u00fcn\u00fc \u00e7al\u0131\u015fmam\u0131z s\u0131ras\u0131nda kolayl\u0131k olmas\u0131 a\u00e7\u0131s\u0131ndan <strong>PlugInEngine&#8217;imizin\u00a0<\/strong>plug-in&#8217;lerimizi bulmak i\u00e7in bakt\u0131\u011f\u0131\u00a0<strong>GG.PlugInTabanliHesapMakinesi.WinUI <\/strong>klas\u00f6r\u00fc alt\u0131ndaki <strong>bin\/PlugIns\u00a0<\/strong>yolunu output klas\u00f6r\u00fc olarak belirliyorum.<\/p>\n<p><a href=\"\/wp-content\/uploads\/2014\/07\/outputPlugIns.jpg\"><img decoding=\"async\" class=\"size-full wp-image-101 aligncenter lazyload\" data-src=\"\/wp-content\/uploads\/2014\/07\/outputPlugIns.jpg\" alt=\"outputPlugIns\" width=\"605\" height=\"157\" data-srcset=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2014\/07\/outputPlugIns.jpg 605w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2014\/07\/outputPlugIns-300x77.jpg 300w\" data-sizes=\"(max-width: 605px) 100vw, 605px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 605px; --smush-placeholder-aspect-ratio: 605\/157;\" \/><\/a><br \/>\nPlug-in&#8217;imizin kodlar\u0131na \u015fimdi bir bakal\u0131m:<\/p>\n<pre class=\"lang:c# decode:true \">using GG.PlugInTabanliHesapMakinesi.Contracts;\r\n\r\nnamespace ABCSirketi.ToplamaPlugIn\r\n{\r\n    \/\/\/ &lt;summary&gt;\r\n    \/\/\/ ABCSirketi taraf\u0131ndan haz\u0131rlanan toplama plug-in'i.\r\n    \/\/\/ &lt;\/summary&gt;\r\n    public class ToplamaIslemi : ICalculationCommand\r\n    {\r\n        \/\/ Plug-in'imizin ismi\r\n        public string Name\r\n        {\r\n            get { return \"Toplama\"; }\r\n        }\r\n\r\n        public double Execute(double arg1, double arg2)\r\n        {\r\n            return arg1 + arg2; \/\/ Plug-in'imizin toplama i\u015flevi\r\n        }\r\n    }\r\n}<\/pre>\n<p>\u0130\u015fte bu kadar.<br \/>\nArt\u0131k ToplamaPlugIn&#8217;imizi derledi\u011fimizde ilgili assembly&#8217;miz\u00a0<strong>GG.PlugInTabanliHesapMakinesi.WinUI\u00a0<\/strong>alt\u0131ndaki <strong>bin\/PlugIns\u00a0<\/strong>yoluna derlenecektir.<\/p>\n<p>Art\u0131k\u00a0plug-in tabanl\u0131 hesap makinemiz \u00e7al\u0131\u015fmaya haz\u0131r! Ben \u00e7al\u0131\u015ft\u0131r\u0131yorum ve ilgili toplama i\u015flemini deniyorum :)<\/p>\n<p><img decoding=\"async\" class=\"size-full wp-image-102 aligncenter lazyload\" data-src=\"\/wp-content\/uploads\/2014\/07\/hesapmakinesi.jpg\" alt=\"hesapmakinesi\" width=\"389\" height=\"319\" data-srcset=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2014\/07\/hesapmakinesi.jpg 389w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2014\/07\/hesapmakinesi-300x246.jpg 300w\" data-sizes=\"(max-width: 389px) 100vw, 389px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 389px; --smush-placeholder-aspect-ratio: 389\/319;\" \/><\/p>\n<p>G\u00f6r\u00fcld\u00fc\u011f\u00fc gibi uygulamam\u0131z ba\u015far\u0131yla \u00e7al\u0131\u015f\u0131yor plug-in tabanl\u0131. :)<br \/>\nPlug-in tabanl\u0131 uygulama geli\u015ftirmede kendimi geli\u015ftirmemde \u00e7ok faydas\u0131 olan Say\u0131n <a href=\"http:\/\/www.tahircakmak.com\/\">Mustafa Tahir \u00c7akmak<\/a> hocamada te\u015fekk\u00fcr\u00fc bir bor\u00e7 bilirim. :)<\/p>\n<p>Bir sonraki makalede g\u00f6r\u00fc\u015fmek dile\u011fiyle.<\/p>\n<p>\u0130lgili proje&#8217;nin \u00e7al\u0131\u015f\u0131r hali ektedir.<\/p>\n<p><a href=\"\/wp-content\/uploads\/2014\/07\/GG.PlugInTabanliHesapMakinesi.rar\">GG.PlugInTabanliHesapMakinesi<\/a><\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Neden plug-in tabanl\u0131 uygulama geli\u015ftirmeye ihtiya\u00e7 duyar\u0131z? Biz yaz\u0131l\u0131mc\u0131lar\u0131n kar\u015f\u0131la\u015ft\u0131klar\u0131 en b\u00fcy\u00fck sorunlardan birisi, bitirmi\u015f oldu\u011fumuz bir uygulaman\u0131n\u00a0\u00fczerine ek bir \u00f6zellik istenmesidir. \u015eahsen bu beni delirten bir \u015fey. :) \u0130\u015fte bu tarz durumlar\u0131n \u00f6n\u00fcne ge\u00e7memizi sa\u011flayan etmenlerden birisidir plug-in tabanl\u0131 uygulama geli\u015ftirme.\u00a0Bu yoldaki en b\u00fcy\u00fck&#8230;<\/p>\n<div class=\"more-link-wrapper\"><a class=\"more-link\" href=\"https:\/\/gokhan-gokalp.com\/tr\/plug-in-tabanli-uygulama-gelistirme-ve-hesap-makinesi-ornegi\/\">Devam\u0131n\u0131 okuyun<span class=\"screen-reader-text\">Plug-in Tabanl\u0131 Uygulama Geli\u015ftirme ve Hesap Makinesi \u00d6rne\u011fi<\/span><\/a><\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[111,18,6,16,4,17],"class_list":["post-83","post","type-post","status-publish","format-standard","hentry","category-net","tag-net","tag-application-domain","tag-assembly","tag-plug-in-tabanli-uygulama-gelistirme","tag-reflection","tag-transparent-proxy","entry"],"translation":{"provider":"WPGlobus","version":"3.0.2","language":"tr","enabled_languages":["en","tr"],"languages":{"en":{"title":true,"content":true,"excerpt":false},"tr":{"title":false,"content":false,"excerpt":false}}},"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Plug-in Tabanl\u0131 Uygulama Geli\u015ftirme ve Hesap Makinesi \u00d6rne\u011fi - G\u00f6khan G\u00f6kalp<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/gokhan-gokalp.com\/plug-in-tabanli-uygulama-gelistirme-ve-hesap-makinesi-ornegi\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Plug-in Tabanl\u0131 Uygulama Geli\u015ftirme ve Hesap Makinesi \u00d6rne\u011fi - G\u00f6khan G\u00f6kalp\" \/>\n<meta property=\"og:url\" content=\"https:\/\/gokhan-gokalp.com\/plug-in-tabanli-uygulama-gelistirme-ve-hesap-makinesi-ornegi\/\" \/>\n<meta property=\"og:site_name\" content=\"G\u00f6khan G\u00f6kalp\" \/>\n<meta property=\"article:published_time\" content=\"2014-07-19T20:57:07+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2014-07-19T21:33:04+00:00\" \/>\n<meta name=\"author\" content=\"G\u00f6khan G\u00f6kalp\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"G\u00f6khan G\u00f6kalp\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/plug-in-tabanli-uygulama-gelistirme-ve-hesap-makinesi-ornegi\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/plug-in-tabanli-uygulama-gelistirme-ve-hesap-makinesi-ornegi\\\/\"},\"author\":{\"name\":\"G\u00f6khan G\u00f6kalp\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#\\\/schema\\\/person\\\/7e2a7fa98babd22a5fdae563c4b8cdbe\"},\"headline\":\"Plug-in Tabanl\u0131 Uygulama Geli\u015ftirme ve Hesap Makinesi \u00d6rne\u011fi\",\"datePublished\":\"2014-07-19T20:57:07+00:00\",\"dateModified\":\"2014-07-19T21:33:04+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/plug-in-tabanli-uygulama-gelistirme-ve-hesap-makinesi-ornegi\\\/\"},\"wordCount\":910,\"commentCount\":2,\"publisher\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#\\\/schema\\\/person\\\/7e2a7fa98babd22a5fdae563c4b8cdbe\"},\"keywords\":[\".NET\",\"Application Domain\",\"Assembly\",\"Plug-In Tabanl\u0131 Uygulama Geli\u015ftirme\",\"Reflection\",\"Transparent Proxy\"],\"articleSection\":[\".NET\"],\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/gokhan-gokalp.com\\\/plug-in-tabanli-uygulama-gelistirme-ve-hesap-makinesi-ornegi\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/plug-in-tabanli-uygulama-gelistirme-ve-hesap-makinesi-ornegi\\\/\",\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/plug-in-tabanli-uygulama-gelistirme-ve-hesap-makinesi-ornegi\\\/\",\"name\":\"Plug-in Tabanl\u0131 Uygulama Geli\u015ftirme ve Hesap Makinesi \u00d6rne\u011fi - G\u00f6khan G\u00f6kalp\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#website\"},\"datePublished\":\"2014-07-19T20:57:07+00:00\",\"dateModified\":\"2014-07-19T21:33:04+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/plug-in-tabanli-uygulama-gelistirme-ve-hesap-makinesi-ornegi\\\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/gokhan-gokalp.com\\\/plug-in-tabanli-uygulama-gelistirme-ve-hesap-makinesi-ornegi\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/plug-in-tabanli-uygulama-gelistirme-ve-hesap-makinesi-ornegi\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/gokhan-gokalp.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Plug-in Tabanl\u0131 Uygulama Geli\u015ftirme ve Hesap Makinesi \u00d6rne\u011fi\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#website\",\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/\",\"name\":\"G\u00f6khan G\u00f6kalp\",\"description\":\"C# &amp; Python lover\",\"publisher\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#\\\/schema\\\/person\\\/7e2a7fa98babd22a5fdae563c4b8cdbe\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/gokhan-gokalp.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#\\\/schema\\\/person\\\/7e2a7fa98babd22a5fdae563c4b8cdbe\",\"name\":\"G\u00f6khan G\u00f6kalp\",\"pronouns\":\"he\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659\",\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659\",\"contentUrl\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659\",\"caption\":\"G\u00f6khan G\u00f6kalp\"},\"logo\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659\"},\"sameAs\":[\"https:\\\/\\\/gokhan-gokalp.com\"],\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/tr\\\/author\\\/gok-gokalp\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Plug-in Tabanl\u0131 Uygulama Geli\u015ftirme ve Hesap Makinesi \u00d6rne\u011fi - G\u00f6khan G\u00f6kalp","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/gokhan-gokalp.com\/plug-in-tabanli-uygulama-gelistirme-ve-hesap-makinesi-ornegi\/","og_locale":"tr_TR","og_type":"article","og_title":"Plug-in Tabanl\u0131 Uygulama Geli\u015ftirme ve Hesap Makinesi \u00d6rne\u011fi - G\u00f6khan G\u00f6kalp","og_url":"https:\/\/gokhan-gokalp.com\/plug-in-tabanli-uygulama-gelistirme-ve-hesap-makinesi-ornegi\/","og_site_name":"G\u00f6khan G\u00f6kalp","article_published_time":"2014-07-19T20:57:07+00:00","article_modified_time":"2014-07-19T21:33:04+00:00","author":"G\u00f6khan G\u00f6kalp","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"G\u00f6khan G\u00f6kalp","Tahmini okuma s\u00fcresi":"8 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/gokhan-gokalp.com\/plug-in-tabanli-uygulama-gelistirme-ve-hesap-makinesi-ornegi\/#article","isPartOf":{"@id":"https:\/\/gokhan-gokalp.com\/plug-in-tabanli-uygulama-gelistirme-ve-hesap-makinesi-ornegi\/"},"author":{"name":"G\u00f6khan G\u00f6kalp","@id":"https:\/\/gokhan-gokalp.com\/#\/schema\/person\/7e2a7fa98babd22a5fdae563c4b8cdbe"},"headline":"Plug-in Tabanl\u0131 Uygulama Geli\u015ftirme ve Hesap Makinesi \u00d6rne\u011fi","datePublished":"2014-07-19T20:57:07+00:00","dateModified":"2014-07-19T21:33:04+00:00","mainEntityOfPage":{"@id":"https:\/\/gokhan-gokalp.com\/plug-in-tabanli-uygulama-gelistirme-ve-hesap-makinesi-ornegi\/"},"wordCount":910,"commentCount":2,"publisher":{"@id":"https:\/\/gokhan-gokalp.com\/#\/schema\/person\/7e2a7fa98babd22a5fdae563c4b8cdbe"},"keywords":[".NET","Application Domain","Assembly","Plug-In Tabanl\u0131 Uygulama Geli\u015ftirme","Reflection","Transparent Proxy"],"articleSection":[".NET"],"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/gokhan-gokalp.com\/plug-in-tabanli-uygulama-gelistirme-ve-hesap-makinesi-ornegi\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/gokhan-gokalp.com\/plug-in-tabanli-uygulama-gelistirme-ve-hesap-makinesi-ornegi\/","url":"https:\/\/gokhan-gokalp.com\/plug-in-tabanli-uygulama-gelistirme-ve-hesap-makinesi-ornegi\/","name":"Plug-in Tabanl\u0131 Uygulama Geli\u015ftirme ve Hesap Makinesi \u00d6rne\u011fi - G\u00f6khan G\u00f6kalp","isPartOf":{"@id":"https:\/\/gokhan-gokalp.com\/#website"},"datePublished":"2014-07-19T20:57:07+00:00","dateModified":"2014-07-19T21:33:04+00:00","breadcrumb":{"@id":"https:\/\/gokhan-gokalp.com\/plug-in-tabanli-uygulama-gelistirme-ve-hesap-makinesi-ornegi\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/gokhan-gokalp.com\/plug-in-tabanli-uygulama-gelistirme-ve-hesap-makinesi-ornegi\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/gokhan-gokalp.com\/plug-in-tabanli-uygulama-gelistirme-ve-hesap-makinesi-ornegi\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/gokhan-gokalp.com\/"},{"@type":"ListItem","position":2,"name":"Plug-in Tabanl\u0131 Uygulama Geli\u015ftirme ve Hesap Makinesi \u00d6rne\u011fi"}]},{"@type":"WebSite","@id":"https:\/\/gokhan-gokalp.com\/#website","url":"https:\/\/gokhan-gokalp.com\/","name":"G\u00f6khan G\u00f6kalp","description":"C# &amp; Python lover","publisher":{"@id":"https:\/\/gokhan-gokalp.com\/#\/schema\/person\/7e2a7fa98babd22a5fdae563c4b8cdbe"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/gokhan-gokalp.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/gokhan-gokalp.com\/#\/schema\/person\/7e2a7fa98babd22a5fdae563c4b8cdbe","name":"G\u00f6khan G\u00f6kalp","pronouns":"he","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659","url":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659","contentUrl":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659","caption":"G\u00f6khan G\u00f6kalp"},"logo":{"@id":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659"},"sameAs":["https:\/\/gokhan-gokalp.com"],"url":"https:\/\/gokhan-gokalp.com\/tr\/author\/gok-gokalp\/"}]}},"_links":{"self":[{"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/posts\/83","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/comments?post=83"}],"version-history":[{"count":30,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/posts\/83\/revisions"}],"predecessor-version":[{"id":117,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/posts\/83\/revisions\/117"}],"wp:attachment":[{"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/media?parent=83"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/categories?post=83"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/tags?post=83"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}