﻿
{"id":26663,"date":"2023-10-26T10:10:23","date_gmt":"2023-10-26T10:10:23","guid":{"rendered":"https:\/\/www.gencayyildiz.com\/blog\/?p=26663"},"modified":"2023-10-26T10:10:23","modified_gmt":"2023-10-26T10:10:23","slug":"net-8-keyed-service-dependency-injection","status":"publish","type":"post","link":"https:\/\/www.gencayyildiz.com\/blog\/net-8-keyed-service-dependency-injection\/","title":{"rendered":".NET 8 &#8211; Keyed Service | Dependency Injection"},"content":{"rendered":"<div id=\"fb-root\"><\/div>\n<p>Merhaba,<\/p>\n<p>Bu i\u00e7eri\u011fimizde .NET 8 ile IoC container&#8217;a gelen <em>keyed service<\/em> \u00f6zelli\u011fini inceleyecek, nas\u0131l ve ne zaman kullan\u0131lmalar\u0131 gerekti\u011fini, olay\u0131n perde arkas\u0131n\u0131 masaya yat\u0131rarak bol isti\u015fare e\u015fli\u011finde de\u011ferlendirece\u011fiz. O halde buyurun ba\u015flayal\u0131m&#8230;<\/p>\n<h3>Keyed Service Nedir?<\/h3>\n<p>Malumunuz dependency injection, Asp.NET Core mimarisinin \u00fczerine in\u015fa edildi\u011fi en kritik davran\u0131\u015fsal yap\u0131lanmalardan birisidir. Mimarinin \u00e7ekirde\u011fi de dahil olmak \u00fczere hemen hemen her yerinde kullan\u0131lan bu model, biz geli\u015ftiriciler taraf\u0131ndan da rahat\u00e7a kullan\u0131labilmesi ve konfig\u00fcre edilebilmesi i\u00e7in minimum \u00f6zellikleri bar\u0131nd\u0131ran built-in bir IoC container ile birlikte gelmektedir. Ha tabi istek do\u011frultusunda Autofac gibi third party k\u00fct\u00fcphaneler e\u015fli\u011finde de daha yetenekli container&#8217;lar sisteme dahil edilip, kullan\u0131labilmektedir.<\/p>\n<p>Velhas\u0131l&#8230;<\/p>\n<p>\u015eimdi bizler varsay\u0131lan container a\u00e7\u0131s\u0131ndan olay\u0131 de\u011ferlendirirsek e\u011fer, herhangi bir servisi provide ederken a\u015fa\u011f\u0131daki \u00fc\u00e7 parametreye odakl\u0131 bir yakla\u015f\u0131m sergilenmesi gerekti\u011fini s\u00f6yleyebiliriz;<\/p>\n<ol>\n<li><em><strong>Lifetime<\/strong><\/em><br \/>\nBuilt-in container&#8217;a eklenecek olan servisin instance&#8217;\u0131n\u0131n nas\u0131l olu\u015fturulaca\u011f\u0131n\u0131 veya olu\u015fturulmu\u015f olan instance&#8217;\u0131n ne s\u0131kl\u0131kla yeniden kullan\u0131laca\u011f\u0131n\u0131 ifade eden parametredir.<\/p>\n<p><em>Transient<\/em>, <em>Scoped<\/em> veya <em>Singleton<\/em> olarak davran\u0131\u015f belirlenebilir.\n<\/li>\n<li><em><strong>Service Type<\/strong><\/em><br \/>\nContainer&#8217;a eklenen servisin, hangi referans\/type ile ili\u015fkilendirilece\u011fini ifade etmektedir. Bu t\u00fcr, bir interface ya da class veya record gibi concrete t\u00fcr olabilir.\n<\/li>\n<li><em><strong>Implementation Type<\/strong><\/em><br \/>\nService Type&#8217;a kar\u015f\u0131l\u0131k verilecek servis t\u00fcr\u00fcn\u00fcn ta kendisidir. Misal olarak; &#8216;IPersonService&#8217; interface&#8217;i service type&#8217;a kar\u015f\u0131l\u0131k gelirken, bu interface&#8217;i implemente etmi\u015f olan &#8216;PersonService&#8217; class&#8217;\u0131 ise implementation type&#8217;a kar\u015f\u0131l\u0131k gelmektedir.\n<\/li>\n<\/ol>\n<p><span style=\"font-size:12px;\">Not: Konuya dair tam teferruatl\u0131 bilgi i\u00e7in youtube kanal\u0131mda yay\u0131nlad\u0131\u011f\u0131m <a href=\"https:\/\/youtu.be\/Bhj2XdcoT2Q?t=1826\" rel=\"noopener\" target=\"_blank\">Asp.NET Core 5.0 &#8211; Derinlemesine Dependency Injection &#8211; IoC Yap\u0131lanmas\u0131<\/a> ba\u015fl\u0131kl\u0131 videoya g\u00f6z atabilirsiniz.<\/span><\/p>\n<p>Yani anlayaca\u011f\u0131n\u0131z .NET mimarisinde built-in container&#8217;a bir servisi kaydetmek bu parametrelerden ge\u00e7mektedir. Ha arka planda bu yap\u0131land\u0131rmalar\u0131n bir <code>ServiceDescriptor<\/code> t\u00fcr\u00fcne kar\u015f\u0131l\u0131k depoland\u0131\u011f\u0131n\u0131 s\u00f6ylemekte de fayda g\u00f6rmekteyim.<\/p>\n<p>\u015eimdi, .NET 8 ile gelmi\u015f olan keyed service&#8217;lere gelirsek e\u011fer bu \u00f6zellik sayesinde provide edilmi\u015f olan servisi tan\u0131mlayacak farkl\u0131 bir bilgi par\u00e7as\u0131 da devreye girmektedir. Bu bilgi par\u00e7as\u0131 <em><strong>Service Key<\/strong><\/em> olarak nitelendirilmektedir ve yine <code>ServiceDescriptor<\/code> s\u0131n\u0131f\u0131 \u00fczerinde konfig\u00fcre edilmektedir. Service key, herhangi bir t\u00fcrden nesne olabilece\u011fi gibi genellikle string veya enum t\u00fcrden de\u011fer tercih edilmektedir. <span style=\"font-size:12px;\">(Angular&#8217;da ki injection token akla geliyor \ud83d\ude09 )<\/span><\/p>\n<p>Bu teorik izahatten sonra mevzuyu daha da netle\u015ftirebilmek i\u00e7in keyed service \u00f6zelli\u011fini pratiksel olarak g\u00f6zlemlemeye ge\u00e7elim.<\/p>\n<h3>Keyed Service \u00d6zelli\u011finin Kullan\u0131m\u0131<\/h3>\n<p>Keyed service \u00f6zelli\u011finin kullan\u0131m\u0131n\u0131 pratikte tecr\u00fcbe edebilmek i\u00e7in \u00f6ncelikle a\u015fa\u011f\u0131daki servis yap\u0131lanmas\u0131n\u0131 in\u015fa edelim:<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\npublic interface IPersonService\r\n{\r\n    string GetPersonType { get; }\r\n}\r\n<\/pre>\n<\/div>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\npublic class SalesDepartmentPersonService : IPersonService\r\n{\r\n    public string GetPersonType =&gt; &quot;Sales Department&quot;;\r\n}\r\n<\/pre>\n<\/div>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\npublic class JobDepartmentPersonService : IPersonService\r\n{\r\n    public string GetPersonType =&gt; &quot;Job Department&quot;;\r\n}\r\n<\/pre>\n<\/div>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\npublic class AccountingDepartmentPersonService : IPersonService\r\n{\r\n    public string GetPersonType =&gt; &quot;Accounting Department&quot;;\r\n}\r\n<\/pre>\n<\/div>\n<p>Yukar\u0131daki \u00e7al\u0131\u015fmalara g\u00f6z atarsan\u0131z e\u011fer &#8216;IPersonService&#8217; isminde bir interface ve bu interface&#8217;i implemente eden \u00fc\u00e7 farkl\u0131 concrete s\u0131n\u0131f\u0131 mevcuttur.<\/p>\n<p>E\u011fer ki, keyed service \u00f6zelli\u011fi olmaks\u0131z\u0131n bu servisleri IoC Container&#8217;a provide ediyor olsayd\u0131k a\u015fa\u011f\u0131daki gibi bir \u00e7al\u0131\u015fma yap\u0131lmas\u0131 gerekiyor olacakt\u0131:<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n.\r\n.\r\n.\r\nbuilder.Services.AddSingleton&lt;IPersonService, SalesDepartmentPersonService&gt;();\r\nbuilder.Services.AddSingleton&lt;IPersonService, JobDepartmentPersonService&gt;();\r\nbuilder.Services.AddSingleton&lt;IPersonService, AccountingDepartmentPersonService&gt;();\r\n.\r\n.\r\n.\r\n<\/pre>\n<\/div>\n<p>Tabi bu \u015fekilde birden fazla ayn\u0131 service type&#8217;a kar\u015f\u0131l\u0131k gelen provide yap\u0131land\u0131rmalar\u0131nda, yap\u0131lacak inject&#8217;e her daim sonuncu tan\u0131mlanan t\u00fcr\u00fcn instance&#8217;\u0131 g\u00f6nderilecektir. Yani a\u015fa\u011f\u0131daki \u00f6rne\u011fi ele al\u0131rsak e\u011fer;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\napp.MapGet(&quot;\/&quot;, (IPersonService personService) =&gt;\r\n{\r\n    ...\r\n});\r\n<\/pre>\n<\/div>\n<p>&#8216;personService&#8217; referans\u0131na &#8216;AccountingDepartmentPersonService&#8217; t\u00fcr\u00fcnden bir nesne g\u00f6nderilmi\u015f olacakt\u0131r.<\/p>\n<p><em><strong>Ee peki hoca, ben &#8216;IPersonService&#8217; referans\u0131na kar\u015f\u0131l\u0131k &#8216;SalesDepartmentPersonService&#8217; veya &#8216;JobDepartmentPersonService&#8217; nesnelerini nas\u0131l elde edebilirim?<\/strong><\/em><\/p>\n<p>Keyed service \u00f6zelli\u011finden \u00f6nce ayn\u0131 referansa kar\u015f\u0131l\u0131k provide edilmi\u015f instance&#8217;lardan istedi\u011fimizi alman\u0131n pekte basit bir yolu oldu\u011funu s\u00f6yleyemem. Burada yap\u0131lmas\u0131 gereken bu nesneleri farkl\u0131 referanslarla i\u015faretleyebilmek i\u00e7in hususi interface&#8217;lerin implemente edilmesi ve bu interface&#8217;ler \u00fczerinden provide edilmesi uygulayabilece\u011fimiz esas \u00e7\u00f6z\u00fcmlerden birisidir diyebilirim.<\/p>\n<p>Ya da anlayaca\u011f\u0131n\u0131z \u00fczere bu ihtiyac\u0131 .NET 8 ile gelmi\u015f olan keyed service \u00f6zelli\u011fiyle de rahatl\u0131kla \u00e7\u00f6z\u00fcmleyebiliriz. Bunun i\u00e7in &#8216;AddKeyed&#8230;&#8217; fonksiyonlar\u0131n\u0131 a\u015fa\u011f\u0131daki gibi kullanmak yeterlidir;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n.\r\n.\r\n.\r\nbuilder.Services.AddKeyedSingleton&lt;IPersonService, SalesDepartmentPersonService&gt;(&quot;sales&quot;);\r\nbuilder.Services.AddKeyedSingleton&lt;IPersonService, JobDepartmentPersonService&gt;(&quot;job&quot;);\r\nbuilder.Services.AddKeyedSingleton&lt;IPersonService, AccountingDepartmentPersonService&gt;(&quot;accounting&quot;);\r\n.\r\n.\r\n.\r\n<\/pre>\n<\/div>\n<p>G\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere, keyed service \u00f6zelli\u011fi ayn\u0131 service type&#8217;a kar\u015f\u0131l\u0131k provide edilmi\u015f olan instance&#8217;lar\u0131 bu sefer de vermi\u015f oldu\u011fumuz key&#8217;ler \u00fczerinden ay\u0131rmam\u0131z\u0131 sa\u011flayan bir niteli\u011fe sahiptir. Tabi bu \u00f6zelli\u011fi illaki bir service type&#8217;a kar\u015f\u0131n \u00e7oklu provide durumlar\u0131nda tercih edece\u011fiz diye bir kaide yok. Yap\u0131n\u0131n niteli\u011fine vak\u0131f oldu\u011funuz taktirde istedi\u011finiz her noktada g\u00f6n\u00fcl rahatl\u0131\u011f\u0131yla kullanabilirsiniz.<\/p>\n<p>Keyed service \u00f6zelli\u011fi ile provide edilmi\u015f olan servisleri inject edebilmek i\u00e7in <code>FromKeyedServices<\/code> attribute&#8217;undan a\u015fa\u011f\u0131daki gibi istifade edebiliriz.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n.\r\n.\r\n.\r\napp.MapGet(&quot;\/&quot;, (&#x5B;FromKeyedServices(&quot;sales&quot;)] IPersonService personService) =&gt;\r\n{\r\n    ...\r\n});\r\n.\r\n.\r\n.\r\n<\/pre>\n<\/div>\n<p>Ya da &#8216;IServiceProvider&#8217; \u00fczerinden de IoC container&#8217;dan talepte bulunabiliriz.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n.\r\n.\r\n.\r\napp.MapGet(&quot;\/&quot;, (IServiceProvider keyedServiceProvider) =&gt;\r\n{\r\n    var personService = keyedServiceProvider.GetRequiredKeyedService&lt;IPersonService&gt;(&quot;accounting&quot;);\r\n    return personService.GetPersonType;\r\n});\r\n.\r\n.\r\n.\r\n<\/pre>\n<\/div>\n<p>Anlayaca\u011f\u0131n\u0131z, keyed service \u00f6zelli\u011fi esas\u0131nda non-keyed service&#8217;lerle ayn\u0131 \u015fekilde \u00e7al\u0131\u015fmakta, tek fark container&#8217;da ki servislerin tan\u0131mlanmas\u0131ndad\u0131r. Yani non-keyed service&#8217;ler sadece service type ile provide edilirken, keyed service&#8217;ler ise service type e\u015fli\u011finde service key ile birlikte tan\u0131mlanmaktad\u0131rlar. Ha e\u011fer ki gidip birden fazla provide&#8217;\u0131 ayn\u0131 keyed service \u00f6zelli\u011fiyle kaydederseniz bu durumda da non-keyed service&#8217;ler de oldu\u011fu gibi sonuncu olarak provide edilen instance&#8217;\u0131n gelece\u011fini bilmenizde fayda vard\u0131r.<\/p>\n<p>Nihai olarak,<br \/>\nKeyed service \u00f6zelli\u011fi inceledi\u011fimiz \u00fczere IoC container&#8217;daki kimi durumlara kar\u015f\u0131n davran\u0131\u015flar\u0131m\u0131z\u0131 basite indirgemekte ve dependency injection a\u00e7\u0131s\u0131ndan farkl\u0131 bir yakla\u015f\u0131m sergileyebilmemize olanak tan\u0131maktad\u0131r. Ha \u00e7ok mu gerekli bir yap\u0131lanmayd\u0131 diye sorarsan\u0131z kesinlikle olmad\u0131klar\u0131 konusunda hemfikiriz diyebilirim \ud83d\ude42 O y\u00fczden s\u0131rf var olduklar\u0131 i\u00e7in kullanma mecburiyetinde oldu\u011funuzu d\u00fc\u015f\u00fcnmeyin.<\/p>\n<p>\u0130lgilenenlerin faydalanmas\u0131 dile\u011fiyle&#8230;<br \/>\nSonraki yaz\u0131lar\u0131mda g\u00f6r\u00fc\u015fmek \u00fczere&#8230;<br \/>\n\u0130yi \u00e7al\u0131\u015fmalar&#8230;<\/p>\n<!-- AddThis Advanced Settings generic via filter on the_content --><!-- AddThis Share Buttons generic via filter on the_content -->","protected":false},"excerpt":{"rendered":"<p>Merhaba, Bu i\u00e7eri\u011fimizde .NET 8 ile IoC container&#8217;a gelen keyed service \u00f6zelli\u011fini inceleyecek, nas\u0131l ve ne zaman kullan\u0131lmalar\u0131 gerekti\u011fini, olay\u0131n perde arkas\u0131n\u0131 masaya yat\u0131rarak bol isti\u015fare e\u015fli\u011finde de\u011ferlendirece\u011fiz. O halde buyurun ba\u015flayal\u0131m&#8230; Keyed Service&#46;&#46;&#46;<!-- AddThis Advanced Settings generic via filter on get_the_excerpt --><!-- AddThis Share Buttons generic via filter on get_the_excerpt --><\/p>\n","protected":false},"author":1,"featured_media":26539,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4912],"tags":[4915,4955,4953,946,4952,4954],"class_list":["post-26663","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-net-8","tag-net-8","tag-net-8-dependency-injection","tag-net-8-keyed-service","tag-dependency-injection","tag-keyed-service","tag-keyed-service-dependency-injection"],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/26663","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/comments?post=26663"}],"version-history":[{"count":7,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/26663\/revisions"}],"predecessor-version":[{"id":26670,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/26663\/revisions\/26670"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media\/26539"}],"wp:attachment":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media?parent=26663"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/categories?post=26663"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/tags?post=26663"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}