Konumuz, SharePoint üzerinde geliştirme yapılırken genelde gözardı edilen, ya da birçok geliştiricinin şimdiye kadar pek farketmemiş olduğu SharePoint Service Locator arayüzü.
SharePoint üzerinde uygulama geliştirmenin aslında temel anlamda ASP.Net uygulamaları geliştirmekten pek farkı yok. SharePoint ile gelen ve birçok uygulamada hız kazandıran araçları kullanmak dışında aslında yaptığınız şey ASP.Net uygulaması geliştirmek. Bu açıdan bakıldığında, herhangi bir tasarım deseni kullanmadan ASP.Net uygulaması geliştirmek ne kadar bünyeye(!) zararlıysa, aynı şey SharePoint için de geçerli. En çok kullanılan SharePoint özelliği olan SharePoint listelerini ele alalım. Arayüzden birkaç tıklama ile veri saklama amaçlı listeler oluşturup, yine birkaç tıklama ile bu listeler arasında ilişkiler tanımlayıp ve yine birkaç tıklama ile bu listelere uygun otomatik oluşturulmuş formlar üzerinden yeni veriler saklamak mümkün. Dikkat! "Eğer birkaç tıklama ile işler bu kadar hızlı yürüyebiliyorsa, dikkat edilmediğinde yine aynı hızda işler kontrolden çıkabilir."
Her platformda olduğu gibi, SharePoint'te de yazılım geliştirmenin bir adabı olmalı. Ben de IoC konusu ile giriş yaparak, ileriki yazılarımda da SharePoint listeleri üzerinde generic repository pattern uygulamaları, Business Connectivity Services modelleme, SharePoint ve birim testleri gibi konularla bu bahsettiğim yazılım geliştirme adabının nasıl olması gerektiğinden bahsedeceğim.
Yazıyı okumaya başlamadan önce, eğer konuya hakim değilseniz öncelikle Ioc (Dependency Injection) nedir okuyup anlamanızı tavsiye ederim. Konuyla ilgili birçok Türkçe ve yabancı dilde kaynak bulabilirsiniz.
SharePoint Service Locator (SPSL)
Öncelikle, başlıkta geçen Service ifadesinin web servisi ya da WCF servisi olmadığını belirtmekte fayda var. Burada Servis ile kastedilen şey belli bir arayüzü uygulayan bir bileşen, daha C# ifadesi ile, bir sınıf. SPSL ise, belli bir yöntemle (konfigürasyon dosyası kullanarak ya da programatik olarak) kayıt edilmiş olan servislerin bulunması ve kullanımınıza sunulmasını sağlayan başka bir SharePoint servisi. Nihai amaç ise uygulama geliştirirken kullandığınız kütüphanelerin belli uygulamalarına olan bağımlılığı ortadan kaldırmak, modüler hale getirmek, modüler hale getirdiğiniz bileşenleri sadece konfigürasyon üzerinde düzenleme yaparak değiştirilebilir hale getirmek. Birazdan vereceğim örneklerle konuyu biraz daha net ifade edebileceğim.
SharePoint Service Locator nasıl çalışır?
SPSL'in çalışma prensibinin temelinde yatan şey aslında çok basit bir Dictionary'dir. Bu Dictionary, içinde bir arayüz (Interface) ve bu arayüze karşılık, bu arayüzü uygulayan bir tip adından oluşan anahtar-değer çiftlerini (ya da teknik ismiyle tip eşleşmelerini) saklar. Aşağıda bu Dictionary için birkaç kayıt örneği vererek sürecin nasıl işlediğinden bahsedelim:
Arayüz |
Tip |
ILogger |
SharePointLogger* |
IConfigManager |
ConfigManager* |
ICustomerRepository |
SPCustomerRepository |
* SharePointLogger ve ConfigManager SharePoint ile hazır olarak gelen iki bileşen. ICustomerRepository ve SPCustomerRepository ise benim örnek vermek amacıyla uydurduğum isimler. Örneğin daha iyi anlaşılabilmesi için SPCustomerRepository nesnelerinin SharePoint listeleri üzerinde müşteri bilgilerini yönetmek amaçlı kullanılan bir sınıf olduğunu varsayalım.
Yukarıdaki yapılandırmaya göre, bir ICustomerRepository nesnesine ihtiyaç duyduğumda, bunu doğrudan bir SPCustomerRepository nesnesi oluşturarak yapmak yerine, SPSL'dan bana bir ICustomerRepository nesnesi vermesini isteyerek gerçekleştiriyorum. SPSL, tip eşleştirmeleri sözlüğüne bakarak, bir ICustomerRepository nesnesi istendiğinde hangi tipten bir nesne oluşturup döndüreceğini belirliyor, nesneyi oluşturuyor ve bana teslim ediyor. Bir kod örneği ile anlatacak olursak;
SPCustomerRepository repository = new SPCustomerRepository();
yerine;
IServiceLocator serviceLocator = SharePointServiceLocator.GetCurrent(); ICustomerRepository repository = serviceLocator.GetInstance<ICustomerRepository>();
yazarak, SPCustomerRepository nesnesinin SPSL tarafından inşa edilmesini ve bana teslim edilmesini sağlamış oluyorum. Dikkat edilmesi gereken nokta, artık yazdığım kod içinde SPCustomerRepository tip adını hiç kullanmamış olmam, başka bir deyişle artık SPCustomerRepository tipine bağımlılığımın kalmamış olması. Ayrıca ileride ihtiyaçlar değişir de müşteri bilgilerini artık SharePoint listeleri üzerinde değil de bir SQL Server veritabanı üzerinde saklamak gerekirse, ICustomerRepository arayüzünü uygulayan bir SQLCustomerRepository sınıfı yazılıp, SPSL'e artık bir ICustomerRepository nesnesi istendiğinde SPCustomerRepository değil SQLCustomerRepository nesneleri döndürmesi söylenebilir. Böylece yazılan kodun büyük bir kısmı değişmeden kalırken, sadece konfigürasyon kullanarak SharePoint üzerinde çalışan uygulama, SQL Server üzerine minimum etki ile taşınabilir.
Service Locator'a ulaşmak
Yukarıda anlatmış olduğum tüm işlemlerin çalışmasını sağlayan Service Locator nesnesi de aslında IServiceLocator arayüzünü uygulayan bir nesne. SharePoint çalıştığı sürece, arka planda daima tek bir kopyası aktif olan bir IServiceLocator nesnesi mevcut. Tip eşleştirmelerini kayıt etmek, SPSL'dan nesne talep etmek vb. gibi işlemlerin tamamı bu tek SPSL tarafından gerçekleştirilir. Bu tekil SPSL'e erişmek için ise SharePointServiceLocator adındaki statik sınıf kullanılır. Bir SPContext altında çalışan koddan bir IServiceLocator örneği elde etmek için aşağıdaki ifade kullanılır:
IServiceLocator serviceLocator = SharePointServiceLocator.GetCurrent();
Eğer bir SPContext altında değilseniz (bir feature ya da Object Model ile SPSL'e erişmeye çalışırken olabilir bu),
IServiceLocator locator = SharePointServiceLocator.GetCurrent(spSite);
ile GetCurrent metoduna parametre olarak bir SPSite nesnesi geçebilirsiniz.
Tip eşleştirmelerinin kayıt edilmesi
Uygulamalardan ulaşmak istediğiniz servis arayüzlerini ve bu arayüzlerin eşleştiği sınıfları önce SPSL'a kayıt etmelisiniz. Kayıt işlemini gerçekleştirmek için daha önce bahsettiğim tekil IServiceLocator nesnesine ulaşmanız gerekli. Aşağıda bunun yöntemini görebilirsiniz:
IServiceLocator serviceLocator = SharePointServiceLocator.GetCurrent(); IServiceLocatorConfig typeMappings = serviceLocator.GetInstance<IServiceLocatorConfig>(); typeMappings.RegisterTypeMapping<ICustomerRepository, SPCustomerRepository>();
Yukarıdaki ifadelerle, Service Locator nesnesine, bundan böyle bir ICustomerRepository nesnesi talep edildiğinde, bir SPCustomerRepository nesnesi döndürmesi gerektiğini söylemiş oluyoruz. Kayıt işleminin bir IServiceLocatorConfig nesnesi üzerinden yapıldığına dikkat edin.
Eğer servisi tekil (singleton) olarak kayıt etmek isterseniz IServiceLocator nesnesini bir ActivatingServiceLocator nesnesine döndürmelisiniz. Aşağıdaki örnekte tekil bir nesnenin nasıl kayıt edilebileceğini görebilirsiniz:
ActivatingServiceLocator serviceLocator = (ActivatingServiceLocator)SharePointServiceLocator.GetCurrent(); serviceLocator.RegisterTypeMapping<ICustomerRepository, SPCustomerRepository>(InstantiationType.AsSingleton);
Peki tekil kayıt etmek ne anlama gelmektedir? IServiceLocator.GetInstance<T>() metodu her çağırıldığında yeni bir nesne oluşturur ve döndürür. Yani her talebinizde elinizde tamamen yeni bir nesne vardır. Nesnelerinizi tekil kayıt ederseniz eğer, Service Locator kayıt ettiğiniz arayüze sahip tek bir nesne örneği oluşturur ve her GetInstance ile nesne talep ettiğinizde size o tek örneği döndürür.
Proje için ek bilgi
Yukarıda anlattığım tüm özellikleri canlı gösteren bir projeyi yazı ekinde bulabilirsiniz. Visual Studio 2010 ile çözümü açıp Deploy seçeneği ile SharePoint'e aktarmanız yeterli. Projede, bir Feature Event Receiver kullanarak Service Locator Sample Feature aktive edildiğinde Service Locator üzerinden tip kayıtlarını gerçekleştiriyorum. Müşteri listesini gösteren bir Visual Web Part ile de, önce kayıt ettiğim ICustomerRepository nesnesini talep edip, ardından repository'den gelen kayıtlarla web part üzerindeki bir SPGridView nesnesini dolduruyorum. Projedeki web part'I bir sayfaya ekleyerek sonucu görebilirsiniz. Projeyi indirmek için tıklayın.
Sonraki yazıda, SharePoint Guidance içinde gelen standart Service Locator nesnelerine alternatif, çok daha güçlü bir IoC container olan Unity ile Dependency Injection olayını inceleyeceğiz.
Kaynak: SharePoint Guidance 2010