Herkesin oldukça iyi bildiğini düşündüğüm bir kavramın, çok fazla kullanılmayan ama yeri geldiğinde çok hayat kurtaran bir C# özelliğinden bahsedicem bu sefer.
Bildiğiniz üzere, C#’da da bir çok yazılım dilinde olan “type visibility” kavramları mevcut. Son kullanıcıya yönelik olan adıyla “Access Modifiers” demem daha doğru olur sanırım. Yarattığımız nesnelerin ve değişkenlerin erişebilirlik seviyelerini ve erişim durumlarını belirten kavramlar. public, private, protected…falan filan…
Falan filan dedim, asıl bahsedeceğimi söylemedim. Eksik olan Internal’ın kullanımı ile ilgili bir kaç ipucu vereceğim. Yazılım geliştirirken, API veya SDK tarzı şeyler geliştirirken, internal kavramının özelliklerini biliyor olmak tasarımda ve kod geliştirmede oldukça işinize yarayacaktır.
Bir çoğunuzun da bildiği üzere, internal olarak tanımladığınız bir sınıf ya da metod, sadece o assembly içerisinde erişilebilmektedir. Dışarıya verdiğiniz kütüphane tarzı yapılarda ya da farklı takımların aynı projede çalışıp ortak assembly’lerde ulaşabilecekleri elemanları kısıtlamak için oldukça kullanılabilecek bir yaklaşım.
Şimdi şöyle bir senaryomuz olsun; X projesi için geliştirdiğimiz FriendAssembly_1.dll‘inin bir sınıfının, bir metodunun sadece FriendAssembly_1.dll‘nin içerisinde kullanılmasını sağlamak adına, metodu internal tanımlamış olalım. Daha sonra aynı X projesinin FriendAssembly_2.dll‘inde çalışan ekibin FriendAssembly_1.dll‘inde ki o metoda erişmesi gereksin. Bu durumda eğer o metodu public yaparsak, herhangi bir başka projede bu FriendAssembly_1.dll‘ini kullanan kişi de o metoda ulaşabilecektir ki, bu da istediğimiz bir şey değil. Peki FriendAssembly_1.dll‘inde ki bir metodun sadece FriendAssembly_2.dll‘inden ulaşılmasını nasıl sağlarız?
Bu durumu engellemek adına .NET Framework’de CLR’da ki “Friend Assembly” kavramını biliyor olmamız lazım.
Bildiğiniz üzere, Visual Studio’da bir proje geliştirirken, proje şablonunda AssemblyInfo.cs diye bir dosya vardır. Bu dosya adındanda anlaşıldığı üzere, geliştirdiğimiz assembly ile ilgili bilgileri içerir. Burada yapacağımız küçük bir ekleme ile yukarıdaki bahsetmiş olduğum senaryo ile ilgili çözüm sağlayabiliriz.
Öncelikle FriendAssembly_1.dll‘i olarak adlandırdığımız projemizin içeriğine bakalım.
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace FriendAssembly_1 { public class FriendAssembly { public FriendAssembly() { } //Sadece bu sınıfın olduğu assembly'de kullanılabilir. internal void InternalTest() { } public void PublicTest() { } //Sadece bu sınıfın olduğu assembly'de //veya bu sınıftan türeyen ama farklı bir assembly'de //olan sınıflarda kullanılabilir. protected internal void ProtectedInternalTest() { } } }
Çok standart, herkesin bildiği, bilebileceği bir yapı. Bu FriendAssembly_1.dll‘imizi, başka bir projede(FriendAssembly_2.dll) referans verip, kullanmaya çalıştığımızda, geliştirme ortamımızda InternalTest() metodunu göremediğimizi(?) fark ediyor olacağız doğal olarak.
Öncelikle FriendAssembly_2.dll‘nindeki örnek yapımıza bakalım.
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace FriendAssembly_2 { public class YourFriend { //FriendAssembly_1.dll'nindeki FriendAssembly //sınıfını kullanıyoruz. public YourFriend() { FriendAssembly_1.FriendAssembly fa = new FriendAssembly_1.FriendAssembly(); } } //FriendAssembly_1.dll'ninden gelen, //FriendAssembly'den türeyen bir sınıf yaratıyoruz. public class MyFriend : FriendAssembly_1.FriendAssembly { public MyFriend() { FriendAssembly_1.FriendAssembly fa = new FriendAssembly_1.FriendAssembly(); } } }
Burada YourFriend sınıfımız FriendAssembly_1.dll‘inden gelen FriendAssembly’i kullanmakta. Ancak fa değişkeninden InternalTest() metoduna ulaşamaz.
MyFriend sınıfı ise, FriendAssembly_1.dll‘indeki FriendAssembly sınıfından türediği için base’deki ProtectedInternalTest() metoduna ulaşabilir.
Ancak yine içinde ki fa değişkeni InternalTest() metoduna ulaşamaz.
FriendAssembly_2.dll‘inin, FriendAssembly_1.dll‘indeki bu internal metodlara ulaşmasını sağlamak için FriendAssembly_1.dll‘ninde AssemblyInfo.cs dosyasına küçük bir ekleme yapmamız gerekmekte.
[assembly: InternalsVisibleTo("FriendAssembly_2")]
şeklinde InternalsVisibleTo() attribute’unu eklerken, hangi assembly’de görünür olsunu da belirtip, FriendAssembly_1.dll‘ini tekrar build edip, diğer projemize döndüğümüzde, artık diğer projedeki fa değişkenimizden InternalTest() metoduna ulaşabildiğimizi göreceğiz.
Herhangi başka bir projede FriendAssembly_1.dll‘ini referans olarak kullanmak istediğimizde,InternalTest() metoduna ulaşamıyor olacağız tekrardan.
Oldukça işe yarayan ama çok fazla farkında olunmayan bu özellik umarım sizin de işinize yarar…