C# Reflection

C# runtime’da tip bilgilerini elde edebilmemizi sağlayacak bir yapı sunmuştur ve buna reflection(yansıma) adı verilmiştir. Reflection sayesinde çok dinamik ve plug-in tabanlı uygulamalar geliştirmek imkansız olmaktan çıkmıştır. Kabaca reflectionı runtime da koda müdahale etmek olarak nitelendirebiliriz.
CLR(Common Language Runtime) içerisindeki kod bir assembly içerisine paketlenmiştir. Metadata CLR’ın kullandığı ve kodları execute ettiği ve bütün sınıf bilgilerini barındırdığı bir veridir.Bütün metod,property,event,delegate,enumaration’ların tip bilgileri metadata’da bulunur. Metadata parçalara ayrılmıştır.
Assembly Metadata : name,versiyon,strong name,culture gibi bilgiler bu parçada yer alır.

Type metadata : namespace ve class name’ler bu parçada bulunur.
Code (Intermediate Language Code) : Makine koduna çevrilmiş kod

Resources : string,image ve dosyalar gibi nesnelerdir.

//Mevcut çalışan kodun assembly'nin instance'ını yaratmak

Assembly asm = Assembly.GetExecutingAssembly();

String msg = String.Format(@"Full Name:{0},Location:{1},Only Reflection?:{2}",

    asm.FullName,asm.Location,asm.ReflectionOnly);

MessageBox.Show(msg);

 

//Bu hata verir cunku Assembly'i sadece reclection için load ettik.

string fullName = "System.Transactions,Version 2.0.0.0," +

    "Culture=neutral,PublicKeyToken=b77a5c561934e089";

Assembly asm = Assembly.ReflectionOnlyLoad(fullName);

asm.CreateInstance("System.Transactions.TransactionScope");

 

//Her assembly en az bir modül içerir.

Assembly asm = Assembly.GetExecutingAssembly();

Module[] mods = asm.GetModules();

foreach (Module m in mods)

{

    Console.WriteLine("Module Name:{0},n {1}",m.Name,m.Assembly.FullName);

}

 

Properties altındaki AssemblyInfı sınıfı içerisinde assembly’nizin özelliklerini görebilirsiniz. Aşağıda bu sınıfa ait bazı attribute’ler listelenmiştir.
[
assembly: AssemblyTitle("WindowsApp")]

[assembly: AssemblyDescription("")]

[assembly: AssemblyConfiguration("")]

[assembly: AssemblyCompany("")]

[assembly: AssemblyProduct("WindowsApp")]

[assembly: AssemblyCopyright("Copyright ©  2009")]

[assembly: AssemblyTrademark("")]

[assembly: AssemblyCulture("tr")]

[assembly: AssemblyAlgorithmId(AssemblyHashAlgorithm.MD5)]

[assembly: AssemblyDefaultAlias("DataLayer")]

[assembly: ComVisible(false)]

[assembly: Guid("41f2bb06-8f33-4321-8e41-76c503147f60")]

[assembly: AssemblyVersion("1.0.0.0")]

[assembly: AssemblyFileVersion("1.0.0.0")]
[
assembly: AssemblyFlags(AssemblyNameFlags.EnableJITcompileOptimizer | AssemblyNameFlags.EnableJITcompileTracking)]

 

//Bu kod ile çalışan assembly içerisindeki custom attribute'lar listelenir.

Assembly asm = Assembly.GetExecutingAssembly();

object[] attrs = asm.GetCustomAttributes(false);

foreach (Attribute attr in attrs)

    Console.WriteLine("Attribute:{0}",attr.GetType());

 

Reflection Tipleri :

Bir nesnenin tipin 4 farklı şekilde alabiliriz. Bunlar ; Assembly sınıfı ile, Module sınıfı ile, bir nesnenin instance’ı ile veya typeof keywordu ile.

Type[] tt;

Assembly asm = Assembly.GetExecutingAssembly();

tt = asm.GetTypes();

 

Module[] mods = asm.GetModules();

Module m = mods[0];

tt = m.GetTypes();

 

object o = new object();

Type t = o.GetType();

 

t = typeof(Int32);

 

Bu yöntemlerden biriyle tipi aldıktan sonra artık o tipin metodları,propertyleri, eventleri,interface’leri,kalıtım ağacı vs elimizin altında demektir.

 

Type t = typeof(String);

Console.WriteLine(" NameSpace : {0}",t.Namespace);

Console.WriteLine(" FullName : {0}", t.FullName);

Console.WriteLine(" IsValueType : {0}", t.IsValueType);

Console.WriteLine(" IsSealed : {0}", t.IsSealed);

Console.WriteLine(" IsAbstract : {0}", t.IsAbstract);

Console.WriteLine(" IsPublic : {0}", t.IsPublic);

Console.WriteLine(" IsClass : {0}", t.IsClass);

 

//Bir sınıfın Property'lerini listelemek

Type t = typeof(System.Data.OleDb.OleDbCommand);

foreach (PropertyInfo item in t.GetProperties())

{

    Console.WriteLine("{0} - {1}",item.Name,item.MemberType);

}

//Bir sınıfın member'lerini listelemek

 Type t = typeof(System.Data.OleDb.OleDbCommand);

 //BindingFlagler ile filtre eklemek

BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;

foreach (MemberInfo item in t.GetMembers(flags))

{

     if (item.MemberType == MemberTypes.Event) Console.WriteLine("Bu bir Event");

     else if (item.MemberType == MemberTypes.Method) Console.WriteLine("Bu bir Metod");

      //.....

      Console.WriteLine("{0} - {1}", item.Name, item.MemberType);

}

 

Dinamik Kod Yazma : Buraya kadar mevcut olan dll’leri ve özelliklerini listelemeyi öğrendik artık referans olarak vermeden bir dll’i nasıl runtime’da çalıştırabiliriz ona bakacağız.

 

//Bu kod Hastable'ı referans göstermeden olusturup yeni bir hashtable yaratıyor.

Assembly asm = Assembly.LoadFile( @"C:WINDOWSMicrosoft.NETFrameworkv2.0.50727mscorlib.dll");

Type hashType = asm.GetType("System.Collection.Hashtable");

//Constructoru parametre almayan

ConstructorInfo ctor = hashType.GetConstructor(Type.EmptyTypes);

object newHash = ctor.Invoke(new object[] { });

 

MethodInfo meth = hashType.GetMethod("Add");

meth.Invoke(newHash, new object[] { "Hi", "Hello" });

//Yaratılan hastableın countu alınıyor.

PropertyInfo prop = hashType.GetProperty("Count");

int count = (int)prop.GetValue(newHash,null);

 

Örneğin bir sınıf içerisindeki statik metodları çağırmak istersek bu sefer sınıfın instance oluşturma işini atlayabiliriz.

 

Runtime’da Kod Oluşturma : Reflection sadece assembly ve tipleri hakkında bilgi alabilme ile sınırlı değildir. Reclection ile Runtime’da bir assembly oluşturabiliriz.

System.Reflection.Emit namespace’i altında bunu yapabilecek builder sınıfları mevcuttur. AssemblyBuilder bir assembly , MethodBuilder bir method , TypeBuilder bir tip oluşturmamıza imkan tanır.

İlk önce bir Assembly ve Module oluşturarak işlemlere başlayabiliriz.

 

//Runtime da Kod Oluşturma

AssemblyName asmName = new AssemblyName();

asmName.Name = "DinamikAssembly";

AssemblyBuilder asmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName,

    AssemblyBuilderAccess.RunAndSave);

ModuleBuilder modBuilder = asmBuilder.DefineDynamicModule("MainMod", "DinamikAssembly.dll");

//Yeni bir public sınıf oluşturuyoruz.

TypeBuilder typeBuilder = modBuilder.DefineType("Sinif1", TypeAttributes.Public | TypeAttributes.Class);

//Bir sınıf daha oluşturuldu.Base'i Hastable ve IDisposable ı implement edecek.

TypeBuilder typeBuilder2 = modBuilder.DefineType("Sinif2", TypeAttributes.Public | TypeAttributes.Class, typeof(Hashtable),new Type[]{typeof(IDisposable)});

ConstructorBuilder ctorBuilder = typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);

ILGenerator codeGen = ctorBuilder.GetILGenerator();

codeGen.Emit(OpCodes.Ret);

//................

asmBuilder.Save(asmName+".dll");

 

Reflection ile ilgili anlatacaklarım bu kadar.Herkese iyi çalışmalar.

Yorum Yaz
Arkadaşların Burada !
Arkadaşların Burada !