Compilerservices | Engin Polat\'ın Windows 8 , Windows Phone 8 ve C# içerikli programcılık sitesi

Arşiv

Etiketlenen yazılar compilerservices

C#’ta assembly: InternalsVisibleToAttribute kullanımı

16 July 2016 Yorum yapılmamış

C#‘ta kullanabildiğimiz erişim belirleyicileri (Access Modifiers) daha önce C# Erişim Belirleyiciler – Access Modifiers isimli makalede ele almıştım.

C# kurallarına göre, bir proje diğer projeyi referans olarak görüyorsa public erişim belirleyicili (access modifier) olan class‘lara erişebilir. internal access modifier olan class‘lara ise referans olarak gören projeden erişilemez, sadece tanımlandığı projeden erişilebilir.

Göstermesi, anlatmasından kolay olacak sanırım.

Hemen Visual Studio 2015 açalım ve yeni bir Console Application projesi oluşturalım;

Solution‘a sağ tuşla tıklayalım ve Add Project menüsünden bir tane Class Library ekleyelim ve Class1.cs dosyasının ismini VeritabaniErisimi.cs olacak şekilde değiştirelim;

Yeni oluşturduğumuz Class Library projesini Console Application projesinin referans‘larına ekleyelim;

Böylece solution‘ımız aşağıdaki gibi gözükmeli;

VeritabaniErisimi.cs dosyasını açalım ve VeritabaniErisimi class‘ının erişim belirleyicisini (Access Modifier) internal yapalım.

Console Application projesindeki Program.cs dosyasını açar ve içerisinden VeritabaniErisimi isimli class‘a erişmek istersek, internal access modifier‘ına sahip olduğu için erişemeyeceğiz.

Bu noktada proje derlenemez ve ‘VeritabaniErisimi’ is inaccessible due to its protection level hatası verir.

Çünkü; internal access modifier‘ına sahip class‘lar sadece kendi projelerinde kullanılabilir, erişebilirlerdir. Kendi projelerinin dışından erişilemezler.

Eğer istersek, Kutuphane isimli Class Library‘deki internal access modifier‘ına sahip sınıfların başka projelerden de erişilebilir olmasını sağlayabiliriz.

Bunun için namespace üstünde InternalsVisibleTo Attribute‘ünü kullanmamız lazım.

Öncelikle VeritabaniErisimi.cs dosyasını açalım (aslında Kutuphane projesindeki herhangi bir csharp dosyasını açsak olur) ve using kısmına System.Runtime.CompilerServices ekleyelim, namespace üzerine de [assembly: InternalsVisibleTo(“PROJEADI”)] yazalım.

InternalsVisibelTo attribute‘ünün parametresi olan PROJEADI, internal access modifier‘ına sahip class‘ların görünür olmasını istediğimiz projelerin adı olmalı. Örneğin;

C# CallerMemberName attribute

12 February 2013 Yorum yapılmamış

.Net 4.5 ve C# 5 ile duyurulan CallerMemberName attribute’unun Loglama ve OnPropertyChanged method’unu daha kolay tetiklemek dışında ne işe yarayacağını uzun süre düşündükten sonra, internette gördüğüm bir makale ile aklıma bir fikir geldi. CallerMemberName attribute‘unun kullanım alanlarını inceleyelim;

Loglama

public static void LogException(string message,
	[CallerMemberName] string callerName = null,
	[CallerLineNumber] int lineNumber = 0,
	[CallerFilePath] string filePath = null)
{
	Console.WriteLine("Hata oluştu : {0}. Method : {1} Satır : {2} Dosya : {3}", message, callerName, lineNumber, filePath);
}

private static void Calculate()
{
	try
	{
		/// Veritabanına bağlan, sorgulama yap, hesapla
	}
	catch (Exception ex)
	{
		LogException(ex.Message);
	}
}

OnPropertyChanged

OnPropertyChanged method’unu C# 5‘ten önce şöyle tetikleriz;

protected virtual void OnPropertyChanged(string propertyName)
{
	PropertyChangedEventHandler handler = PropertyChanged;
	if (handler != null)
	{
		handler(this, new PropertyChangedEventArgs(propertyName));
	}
}

private string _productName;
public string ProductName
{
	get { return _productName; }
	set
	{
		_productName = value;
		OnPropertyChanged("ProductName");
	}
}

C# 5 ile birlikte gelen CallerMemberName attribute’unu kullanarak aynı işi şu şekilde yapabiliriz;

protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
	PropertyChangedEventHandler handler = PropertyChanged;
	if (handler != null)
	{
		handler(this, new PropertyChangedEventArgs(propertyName));
	}
}
 
private string _productName;
public string ProductName
{
	get { return _productName; }
	set
	{
		_productName = value;
		OnPropertyChanged();
	}
}

Strategy Pattern

CallerMemberName attribute‘unun yukarıdakilerden farklı kullanımı aşağıdaki gibi olabilir;

public class CustomSerializer
{
	public Func<string> Serialize { get; private set; }

	public CustomSerializer([CallerMemberName] string memberName = "")
	{
		if (memberName.Contains("Xml"))
		{
			Serialize = () => { return "xml"; };
		}
		else
		{
			Serialize = () => { return "json"; };
		}
	}
}

public static void WriteXml()
{
	var serializer = new CustomSerializer();
	Console.WriteLine(serializer.Serialize()); /// xml
}

public static void WriteJson()
{
	var serializer = new CustomSerializer();
	Console.WriteLine(serializer.Serialize()); /// json
}

Böylece, CustomSerializer class’ında bulunan Serialize method’unu çağıran method’un adında Xml anahtar kelimesi varsa Serialize method’u xml serialization yapacak, yoksa json serialization yapacak.

Kaynak : Makaleyi tekrar bulamadım :(