Yansıma (Reflection), üst verinin (metadata) çalışma zamanında (runtime) incelenmesini sağlayan mekanizmadır. Yansıma ile metod adları, nesnenin veri tipi ve "Constructor" bilgileri alınabilmektedir.
.NET ‘te kullanılan herşeyin bir tipi vardır. Üyeleri öğrenilmek istenen bir tip, öncelikle bir "Type" değişkeni olarak alınmaktadır. Bu noktadan sonra Yansıma uzayına ait sınıfları ve metodlarını kullanarak ilgili tipe ait tüm bilgiler elde edilebilmektedir.
Tasarım yaparken en çok karşılaşılan problem uygulamanın esnek bir yapıya sahip olma sorunudur. Uygulamanın mümkün olduğu kadar modüler olmasını sağlamanın en önemli yollarından biri, eklentiler çözümüdür. Eklenti tabanlı programlar, bir çok yenilikle programcının işini kolaylaştırmaktadır. Bu konudaki en önemli özelliği "System.Reflection" isim alanıdır ve yansıma kullanılarak "Assembly" dosyaları hakkında bilgiler edinebilmeyi, metadata’larını sorgulayarak, onları tekrar tekrar hafızaya yükleyebilmeyi oldukça kolay bir hale getirir. "System.Reflection" isim alanı yansıma sırasında kullanılan sınıfları (class) temsil eder.
"Assembly" sınıfı "System.Reflection" içinde yer alır ve fiziksel bir "assembly" temsil edilir.
Assembly cls = Assembly.LoadFrom("test.dll");
Type[] types = cls.GetTypes();
DirectoryInfo d = new DirectoryInfo(Application.StartupPath);
FileInfo[] files = d.GetFiles("*.dll");
MethodInfo[] mthds = type.GetMethods();
ParameterInfo[] prms = info.GetParameters();
Yukarıdaki kod sayesinde, cls nesnesi test.dll dosyası ile temsil edilmektedir. Sırasıyla, test.dll dosyası içerisinde yer alan türler okunur, uygulamanın bulunduğu klasöre ait Directory nesnesi oluşturulur, uygulamanın çalıştığı klasördeki *.dll dosyaları FileInfo[] nesnesine atılmaktadır. "Type" cinsinden tip (type) oluşturularak "types" ın içindeki methotlar elde edilmektedir. "MethodInfo" türünden bilgi (info) oluşturularak methodun içindeki parametreler elde edilmektedir.
Yansıma ile herhangi bir referans olmadan, ayrı bir "assembly" içinde yer alan bir fonksiyonu çalıştırarak, dönen değeri almak son derece kolay bir şekilde gerçekleştirilebilmektedir.
class App
{
private int x;
public void fonk()
{
Console.WriteLine(x);
}
public App()
{
Console.WriteLine(“default”);
}
public App(int a)
{
x = a;
}
}
Başka bir örnek ise;
class Program
{
private static void Main(string[] args)
{
Type type= typeof(App);
ConstructorInfo cin = type.GetConstructor(new Type[] {typeof(int)});
App a = (App)cin.Invoke(new object[] {2});
a.fonk();
}
}
"Runtime" sırasında özellikle dinamik olarak yapılan işlem ve kontrollerde verim sağlayan bir özellik ise ("Constructor" ve metodlar getirilmiştir);
{
static void Main(string[] args)
{
Type objectType = testObject.GetType();
ConstructorInfo[] info = objectType.GetConstructors();
MethodInfo[] methods = objectType.GetMethods();
Console.WriteLine("Constructors:");
foreach (ConstructorInfo cf in info)
Console.WriteLine(cf);
Console.WriteLine();
Console.WriteLine("Methods:");
foreach (MethodInfo mf in methods)
Console.WriteLine(mf);
}
}
{
public static void Main(string[] args)
{
Assembly a = Assembly.GetExecutingAssembly();
Type t = a.GetType("ReflectionSample.Program");
MethodInfo mi = t.GetMethod("Foo");
foreach (ParameterInfo pi in mi.GetParameters())
Console.WriteLine("{0} {1}", pi.ParameterType.Name, pi.Name);
public void Foo(int a, long b)
{
}
}
Uygulamalar
{
static void Main(string[] args)
{
Type tur=Type.GetType("System.Single");
System.Reflection.MemberInfo[] turmembers=tur.GetMembers();
Console.WriteLine(tur.Name.ToString()+" sinifindaki üye sayisi:"
+turmembers.Length.ToString());
for (int i = 0; i < turmembers.Length;i++ )
Console.WriteLine(i.ToString() + ". üye adi:"
+ turmembers[i].Name.ToString()
+ "||" + turmembers[i].MemberType.ToString());
}
}
{
static void Main(string[] args)
{
DataTable dt=new System.Data.DataTable();
Type tipimiz=dt.GetType();
MethodInfo[] turMetodlari=tipimiz.GetMethods();
Console.WriteLine(tipimiz.Name.ToString()+" sinifindaki metod
sayisi:"+turMetodlari.Length.ToString());
for(int i=0;i < turMetodlari.Length ; i++)
{
Console.WriteLine("Metod adi:"+turMetodlari[i].Name.ToString()+
" |Dönüs degeri:"
ParameterInfo[] paramInfo = turMetodlari[i].GetParameters();
Console.WriteLine("-----Parametre Bilgileri-----"
+paramInfo.Length.ToString()+
" parametre");
for (int j = 0; j < paramInfo.Length;j++ )
Console.WriteLine("Param.Adi:"
+ paramInfo[j].Name.ToString()
+"|Param.Tipi:"
+ paramInfo[j].ParameterType.ToString());
Console.WriteLine("----");
}
}
}
"DataTable" örneğinin "GetType" metodunu kullanarak, bu örneğin dolayısıyla "DataTable" sınıfının tipi elde edilmektedir. Sadece metodları incelemek istenildiğinden, "GetMethods()" metodunu kullanılmakta ve sonuçları "MethodInfo" sınıfı tipinden bir diziye aktarılmaktadır. Metod sayısı "Length" özelliği ile alınmakta, döngü oluşturulmakta ve metodları bir takım özellikleri ile birlikte yazdırmaktadır. Metodun ismi "Name" özelliği ile metodun dönüş tipi ise "ReturnType" özelliği ile alınmaktadır. Daha sonraki satırda ise, "i" indeksli metoda ait parametre bilgileri "GetParameters()" metodu ile alınmakta ve Yansıma uzayında bulunan "ParameterInfo" sınıfı tipinden bir diziye aktarılmaktadır. Böylece ilgili metodun parametrelerine ve parametre bilgilerine erişebilmektedir. Döngü ile "i" indeksli metoda ait parametrelerin isimleri ve tipleri yazdırılmaktadır. Bunun için "Name" ve "ParameterType" özellikleri kullanılmaktadır.