Reflection, part Four

Αυτό το post είναι μέρος μιας τετράδας από blog posts σχετικά με το reflection. Δείτε τα υπόλοιπα εδώ

Σε αυτό το blog post θα δούμε πώς να δημιουργήσουμε τα δικά μας Types ή assemblies κατά το runtime (είτε για να τις αποθηκεύσουμε στο σκληρό δίσκο είτε για να τις χρησιμοποιήσουμε ενώ είναι στη μνήμη).

 

Κατασκευή δικού μας κώδικα

Το σύστημα του Reflection περιλαμβάνει ένα υπο-namespace το οποίο ονομάζεται Emit (System.Reflection.Emit) που περιλαμβάνει κάποιες κλάσεις που χρησιμοποιούνται για κατασκευή Assemblies, Types, Methods κ.λ.π. Για να κατασκευάσουμε κώδικα κατά το runtime, πρέπει να τον κάνουμε encapsulate όπως συνήθως (κατασκευή assembly, κατασκευή module μέσα στην assembly, και μετά κατασκευή Types μέσα στο Module). Κάθε μία από αυτές τις κλάσεις έχει παρόμοιο όνομα με την κλάση που κατασκευάζει, μαζί με την προσθήκη της λέξης Builder (για παράδειγμα για κατασκευή μιας Assembly χρησιμοποιούμε την κλάση AssemblyBuilder). Οι Builder κλάσεις που υποστηρίζονται είναι οι εξής

Όνομα κλάσης

Κατασκευάζει

AssemblyBuilder

assemblies

ConstructorBuilder

constructors

EnumBuilder

enumerations

EventBuilder

events

FieldBuilder fields
LocalBuilder τοπικές μεταβλητές για συναρτήσεις και constructors
MethodBuilder μεθόδους / συναρτήσεις
ModuleBuilder modules
ParameterBuilder παραμέτρους
PropertyBuilder properties
TypeBuilder types

Δημιουργία Assembly και Module

Πριν την δημιουργία ενός Type, πρέπει να δημιουργήσουμε μία Assembly και ένα Module. Για να το κάνουμε αυτό, πρέπει να ζητήσουμε από ένα AppDomain να δημιουργήσει μια δυναμική assembly. Η κλάση AppDomain έχει μία μέθοδο ονόματι DefineDynamicAssembly που παίρνει σαν παραμέτρους ένα AssemblyName αντικείμενο και ένα AssemblyBuilderAccess enumeration. Το πρώτο περιλαμβάνει πληροφορίες για την assembly και το δεύτερο είναι ένα enumeration με τιμές ReflectionOnly, Run, Save, RunAndSave, όπου καθορίζει το τι θέλουμε να κάνουμε με την assembly.

 image

Εφόσον έχουμε τώρα ένα αντικείμενο AssemblyBuilder, μπορούμε να κατασκευάσουμε ένα ModuleBuilder.

image

Δημιουργία Type

Για να δημιουργήσουμε ένα νέο Type, θα καλέσουμε μια συνάρτηση του ModuleBuilder ονόματι DefineType. Αυτή η συνάρτηση παίρνει σαν παραμέτρους ένα όνομα για το Type, και μία τιμή από το enumeration TypeAttributes. Το TypeAttributes περιλαμβάνει επιλογές για το καινούριο Type.

image

Υπάρχουν διάφορες overloaded συναρτήσεις της DefineType, που επιτρέπουν (μεταξύ άλλων) το inheritance μιας άλλης κλάσης ή το implementation κάποιου interface.

Δημιουργία Members

Η κλάση TypeBuilder μας επιτρέπει να δημιουργήσουμε μέλη για το Type μας. Οι συναρτήσεις που υποστηρίζει είναι

Όνομα συνάρτησης

Δημιουργεί

DefineContructor constructor για το type
DefineDefaultConstructor constructor χωρίς παραμέτρους
DefineEvent events
DefineField fields
DefineGenericParameters generic παραμέτρους για generic types
DefineMethod συναρτήσεις
DefineMethodOverride συναρτήσεις οι οποίες κάνουν override συναρτήσεις μιας γονικής κλάσης
DefineNestedType types τα οποία είναι εμφωλευμένα (nested) σε ένα type
DefinePInvokeMethod συναρτήσεις οι οποίες καλούν εξωτερικό κώδικα μέσω της λειτουργίας Platform Invoke
DefineProperty properties

Το πρώτο πράγμα που χρειάζεται να κάνουμε για το νέο μας Type είναι να δημιουργήσουμε έναν constructor. Θα κατασκευάσουμε έναν default (χωρίς παραμέτρους) constructor, οπότε θα γράψουμε το εξής τμήμα κώδικα

image

Η συνάρτηση DefineDefaultConstructor παίρνει σαν όρισμα μία τιμή από το MethodAttributes enumeration, η οποία και καθορίζει την “ορατότητα” του νέο μας constructor. Σε αυτή την περίπτωση, επιλέγουμε να είναι public.

Κατασκευάζουμε και έναν άλλον constructor

image

Εν συνεχεία, θα χρησιμοποιήσουμε την κλάση ILGenerator προκειμένου να γράψουμε μέσα στον constructor μας κάποιο κώδικα. Αυτή η κλάση χρησιμοποιείται για να δημιουργήσουμε τοπικές μεταβλητές και IL (Intermediate Language) κώδικα. Στην προκειμένη περίπτωση, ο constructor μας απλά θα κάνει ένα return, οπότε θα γράψουμε το παρακάτω

 image

Για περισσότερες πληροφορίες σχετικά με τα OpCodes αλλά και με την Intermediate Language του .NET Framework, δείτε εδώ

Βέβαια, εκτός από constructor μπορούμε να δημιουργήσουμε και άλλες μεθόδους. Δείτε

image

Για να δημιουργήσουμε μία static μέθοδο, βάζουμε το MethodAttributes.Static στα attributes, με αυτόν τον τρόπο

image

Για να δημιουργήσουμε ένα private field, κάνουμε το εξής

image

Για να δημιουργήσουμε ένα property το οποίο θα μας κάνει expose το παραπάνω field, γράφουμε τον εξής κώδικα

image

Θα πρέπει βέβαια να φτιάξουμε και τα get και set operations για το property μας. Δείτε:

image

Τέλος, για να σώσουμε στο δίσκο την καινούρια μας assembly, κάνουμε το εξής

image

Στο παρόν blog post μπορείτε να βρείτε συννημένο τον τελικό κώδικα αυτής της τετράδας των blog posts.

Reflection, part Three

Αυτό το post είναι μέρος μιας τετράδας από blog posts σχετικά με το reflection. Δείτε τα υπόλοιπα εδώ

Στα προηγούμενα δύο blog posts είδαμε πως να βρίσκουμε το type information μιας assembly και να το παρουσιάζουμε. Πολλές φορές, χρειαζόμαστε να τρέξουμε κώδικα που περιέχεται σε αυτές τις assemblies, και θέλουμε να μην έχουμε απευθείας πρόσβαση στον κώδικα αυτό κατά το compile time (όπως γίνεται όταν κάνουμε κανονικά reference μια assembly). Η δυνατότητα φορτώματος μιας assembly δυναμικά και εκτέλεσης κώδικα από αυτή χωρίς να έχουμε πρόσβαση κατά το compile time είναι ο στόχος του dynamic code.

 

Χρήση του dynamic code

Το σύστημα του reflection μας επιτρέπει να δημιουργήσουμε αντικείμενα δυναμικά, ακόμα και από assemblies που δεν έχουνε γίνει reference στο project μας. Ενώ αυτό είναι πιο δύσκολο από την συγγραφή “type safe compiler checked” κώδικα (όπου έχουμε απευθείας πρόσβαση και “επίβλεψη” για τα πεδία των αντικειμένων που χρησιμοποιούμε) κάποιες φορές ο δυναμικός κώδικας είναι απαραίτητος.

Για το παράδειγμά μας, κατασκευάζουμε ένα νέο project (ονόματι DynamicLibrary) το οποίο και προσθέτουμε στο solution μας. Για ευκολία κατά την εκτέλεση του προγράμματός μας, επιλέγουμε κατά το build του, να τοποθετείται στον ίδιο φάκελο που είναι και η εφαρμογή μας.

image

Στο συγκεκριμένο project, κατασκευάζουμε μία κλάση Product. Μπορείτε να δείτε τον κώδικά της εδώ

  image

Για να πάρουμε δυναμικά ένα instance της κλάσης Product, υπάρχουν δύο τρόποι. Ο πρώτος είναι αυτός

image

Χρησιμοποιούμε την κλάση System.Activator για να πάρουμε δύο instances, το πρώτο καλώντας τον contructor που δεν έχει ορίσματα, και το δεύτερο καλώντας τον constructor που παίρνει όρισμα ένα string. Η κλάση αυτή χρησιμοποιείται και στις Remoting εφαρμογές για να πάρουμε instances από απομακρυσμένα αντικείμενα. Ο δεύτερος τρόπος είναι αυτός

 image

Με την πρώτη μορφή καλούμε τον empty constructor της κλάσης Product (γι’αυτό το λόγο παρέχουμε ένα Type.EmptyTypes κατά την κλήση της GetConstructor). Με τη δεύτερη μορφή, καλούμε τον άλλο constructor ο οποίος παίρνει σαν όρισμα ένα string.

Invoking Members

Εφόσον έχουμε ένα instance ενός object είναι πολύ απλό να καλέσουμε ένα Member. Ας δούμε πώς μπορούμε να κάνουμε set και get το Property Price.

image

Χρησιμοποιούμε τις συναρτήσεις SetValue και GetValue για να πάρουμε τον accessor και τον mutator, αντίστοιχα, του property. Το πρώτο argument στις GetValue και στην SetValue είναι το object στο οποίο θέλουμε να καλέσουμε το αντίστοιχο member (στην περίπτωσή μας, καλούμε τις συναρτήσεις στο αντικείμενο o1). Το τελευταίο argument σε αυτές τις μεθόδους χρησιμοποιείται αν θέλουμε να πάρουμε indexed properties. Εμείς δεν έχουμε κάτι τέτοιο στην περίπτωσή μας, οπότε απλά το κάνουμε set σε null.

Ας δούμε τώρα πως μπορούμε να κάνουμε δυναμικά Register σε Events. Το event μας είναι το PriceChanged, το οποίο είναι τύπου EventHandler. Κατασκευάζουμε λοιπόν μία συνάρτηση που έχει το signature (return value and parameter types) που απαιτεί ο συγκεκριμένος Delegate.

image

Μέσα σε αυτή ενημερώνουμε ότι άλλαξε η τιμή, και παίρνουμε μέσω reflection την καινούρια. Πώς όμως κάνουμε register στο Event; Είναι πολύ απλό. Δείτε εδώ

image

Σαν πρώτο όρισμα στην AddEventHandler βάζουμε το αντικείμενο στο event του οποίου θέλουμε να κάνουμε register.

Εκτελώντας το συγκεκριμένο τμήμα κώδικα θα πάρουμε σαν output

image

το οποίο σημαίνει ότι ο event handler πράγματι έκανε handle το event.

Ας δούμε και πώς μπορούμε να κάνουμε δυναμική κλήση των δύο συναρτήσεων της Product. Ο κώδικας είναι εδώ

image

Για να πάρουμε την WritePrice, χρησιμοποιούμε και το BindingFlags enumeration, καθώς η συγκεκριμένη method είναι declared σαν private, οπότε, μέσω του BindingFlags, δηλώνουμε στην GetMethod ότι η συνάρτηση που ψάχνουμε είναι Instance method και όχι Public. Για να πάρουμε την WriteName, απλά δίνουμε σαν παράμετρο το όνομά της (αφού έχει δηλωθεί ως Public).

Παρόμοια είναι και η κλήση όλων των αντικειμένων που έχουν το Info σαν κατάληξη (FieldInfo, MemberInfo κ.λ.π.), οπότε δεν θα αναφερθούμε παραπάνω.

Invoking Static Members

Για να πάρουμε static μεθόδους από ένα object, δεν κάνουμε κάτι διαφορετικό. Απλά περνάμε null στο object του οποίου η μέθοδος θα εκτελεστεί. Δείτε εδώ πως μπορούμε να γράψουμε στην κονσόλα ένα “Hello World!” με reflection στην static μέθοδο της κλάσης System.Console

image

Στην GetMethod, με την χρήση του new Type[] {typeof(string)} επιλέγουμε την overloaded μέθοδο WriteLine η οποία παίρνει σαν όρισμα ένα string. Κατόπιν, σε αντίθεση με τα προηγούμενα παραδείγματα, όπου στο πρώτο όρισμα της Invoke βάζαμε το αντικείμενο στο οποίο θέλαμε να κληθεί η reflected μέθοδος, εδώ βάζουμε null, αφού η συγκεκριμένη μέθοδος στην οποία έχουμε κάνει reflect είναι static.

Η κλάση Binder

Όταν χρησιμοποιούμε κώδικα από assemblies/classes στις οποίες κάνουμε reflect κατά το runtime, μπορούμε να κατασκευάσουμε μία δικιά μας υλοποίηση της κλάσης Binder, η οποία είναι υπεύθυνη για να αποφασίζει πως να κάνει type conversions (μετατροπές μεταξύ τύπων) και που να βρει τον δυναμικό κώδικα. Ένα instance μιας Binder κλασης είναι ένα προαιρετικό argument στις μεθόδους της κλάσης Type που επιστρέφουν μέλη ενός Type (GetMember, GetEvent κ.λ.π.). Αν δεν προσδιοριστεί μία custom υλοποίηση της κλάσης Binder, το Framework χρησιμοποιεί τον default binder (ο οποίος, στις περισσότερες των περιπτώσεων θα κάνει τη δουλειά που θέλουμε. Μία custom κλάση Binder είναι χρήσιμη αν αναμένουμε να κάνουμε μετατροπές τύπων ή κάποιο άλλο “ταίριασμα” των παραμέτρων προκειμένου να βρούμε τη σωστή μέθοδο/property/event κ.λ.π. σε μία reflected κλάση, όταν δεν γνωρίζουμε την ακριβή υλοποίηση μιας κλάσης. Για περισσότερες πληροφορίες σχετικά με την κλάση Binder, δείτε το παράδειγμα του MSDN εδώ.

Στο επόμενο blog post θα δούμε πως μπορούμε να δημιουργήσουμε κώδικα κατά το runtime.

Επισυνάπτεται ο μέχρι στιγμής κώδικας αυτής της σειράς των posts.

Reflection, part Two

Αυτό το post είναι μέρος μιας τετράδας από blog posts σχετικά με το reflection. Δείτε τα υπόλοιπα εδώ

Στο προηγούμενο blog post αναφερθήκαμε σχετικά με τι είναι γενικά το reflection, και πως μπορούμε να πάρουμε διάφορες πληροροφίες από μία assembly κατά το runtime. Σε αυτό, θα δούμε πως μπορούμε να πάρουμε πληροφορίες για διάφορα types και να κάνουμε reflection πάνω σε αυτά.

  

Getting Types

Υπάρχουν διάφοροι τρόποι για να πάρουμε types.

  • Μπορούμε να πάρουμε τα types μιας assembly
  • Μπορούμε να πάρουμε τα types ενός module
  • Μπορούμε να πάρουμε τα types κάποιου instance ενός object
  • Μπορούμε να χρησιμοποιήσουμε τα keywords typeof (C#) και GetType (Visual Basic)

Όταν εργαζόμαστε με μία assembly, μπορούμε να πάρουμε τα Types της με χρήση της GetTypes() συνάρτησης. Η ίδια μέθοδος υπάρχει και στο αντικείμενο Module.

image

Επίσης, μπορούμε να πάρουμε το Type ενός instance ενός αντικειμένου, με την GetType μέθοδο (την κληρονομεί από το System.Object)

image

Επίσης, μπορούμε να δημιουργήσουμε ένα Type από ένα value type ή ένα reference type με τη χρήση της typeof keyword (GetType στη VB)

image

Το αντικείμενο Type έχει πολλά μέλη (συναρτήσεις, properties κ.λ.π.) τα οποία μπορείτε να τα δείτε εδώ. Μερικές πληροφορίες που μπορούμε να πάρουμε για ένα instance ενός Type είναι το namespace του, το όνομά του, αν είναι ValueType (όπως τα int, float, double, κάποιο structure κ.λ.π.), αν είναι Public κ.λ.π. Δείτε τον παρακάτω κώδικα για μερικές από τις πληροφορίες που μπορούμε να πάρουμε

image

Επιπροσθέτως, με τον ίδιο τρόπο που μπορούμε να εξετάσουμε για attributes σε μία assembly, μπορούμε να εξετάσουμε και για attributes σε ένα Type

image

Η διαφορά ανάμεσα στην GetCustomAttributes όταν εκτελείται σε assembly και όταν εκτελείται σε Type, είναι πως η boolean παράμετρος ενώ αγνοείται όταν γίνεται κλήση από assembly, εδώ δεν αγνοείται. Η χρησιμότητά της είναι ότι “λέει” στην GetCustomAttributes να κοιτάξει στην κλάση που αντιπροσωπεύει το instance του Type και για attributes που γίνονται inherit από μία γονική κλάση.

Σημείωση

Έστω ότι έχουμε τα εξής
image 
Έτσι και εκτελέσουμε τον παρακάτω κώδικα
image
το αποτέλεσμα θα είναι
image
Γιατί; Επειδή ένα αντικείμενο είναι πάντα ενός τύπου. Μπορεί να γίνει cast σε μία γονική κλάση ή σε ένα Interface που υλοποιεί, αλλά ο τύπος του δεν αλλάζει.

Enumerating Class members

Στην κλάση Type υπάρχουνε μέθοδοι για να πάρουμε διαφορετικά μέρη ενός Type (μεθόδους, properties, fields, events κ.α.). Κάθε ένα από αυτά τα μέρη αντιπροσωπεύεται στο Framework από μία κλάση που το όνομά της τελειώνει με τη λέξη Info. Έτσι λοιπόν, η κλάση που αντιπροσωπεύει μια μέθοδο λέγεται MethodInfo, η κλάση που αντιπροσωπεύει ένα Event λέγεται EventInfo, κ.λ.π. Όλες αυτές οι κλάσεις παράγονται από μία γονική, που ονομάζεται MemberInfo (αυτή την κλάση κληρονομεί και το Type αντικείμενο). Στην κλάση MemberInfo υπάρχουν κάποιες κοινές μέθοδοι για διάφορες πληροφορίες, ενώ οι σημαντικές πληροφορίες υπάρχουνε στις κλάσεις “απογόνους”. Οι συναρτήσεις για να πάρουμε instances αυτών των κλάσεων από ένα Type ακολουθούν την ονοματοδοσία Get + Event|Method|Field|Property κ.α. Στο τέλος μπορεί να υπάρχει και η κατάληξη s, για να μας επιστραφεί ένας πίνακας από objects.

Για παράδειγμα, για να βρούμε όλα τα methods σε μία κλάση κάνουμε το εξής

 image

Βλέπουμε ότι μπορούμε να πάρουμε το όνομα κάθε συνάρτησης, το όνομα της επιστρεφόμενης τιμής της, καθώς και όλα τα ονόματα των παραμέτρων της.

Είναι πολύ εύκολο επίσης να δούμε και τα Nested Types

image

αλλά και τα Members γενικά

image 

Βέβαια, όσο κάνουμε enumerate τα MemberInfo, μπορούμε να δούμε και αν κάποιο από αυτά είναι κάποιου συγκεκριμένου τύπου, κάνοντας χρήση του MemberTypes enumeration

image

Το MethodBody

Για να πάρουμε τον IL κώδικα μιας μεθόδου, χρησιμοποιούμε το MethodBody αντικείμενο (επιστρέφεται από τη συνάρτηση GetMethodBody, η οποία υπάρχει στις κλάσεις ConstructorInfo ή MethodInfo).

Δείτε εδώ πως μπορούμε να δούμε τις τοπικές μεταβλητές μιας συνάρτησης αλλά και πως μπορούμε να πάρουμε τον IL κώδικα της συνάρτησης σε έναν πίνακα από bytes.

image

BindingFlags

Το enumeration BIndingFlags χρησιμοποιείται για να ελέγξει πως κάποια members ενός Type λαμβάνονται κατά τη χρήση της GetMembers μεθόδου. Είναι ένα flagged enumeration, πράγμα το οποίο σημαίνει ότι δύο ή περισσότερα μέλη της μπορούν να χρησιμοποιηθούν ταυτόχρονα.

Τα μέλη του BindingFlags enumeration είναι

  • DeclaredOnly : αγνοούνται τα inherited members
  • Default : Δεν χρησιμοποιείται κάποιο BindingFlag
  • FlattenHierarchy : Επιστρέφει declared, inherited αλλά και protected members
  • IgnoreCase : Αγνοείται το casing (πεζά – κεφαλαία) κατά το ταίριασμα του ονόματος
  • Instance : Επιστρέφονται τα μέλη του instance του type
  • NonPublic : Επιστρέφει protected, internal και private μέλη
  • Public : Επιστρέφει τα public μέλη
  • Static : Επιστρέφει τα static μέλη

Δείτε τον παρακάτω κώδικα

image

Ο μέχρι τώρα κώδικας επισυνάπτεται στο παρόν post.

Στο επόμενο blog post θα δούμε την χρήση κώδικα από assemblies που γίνονται reflected στο runtime.

Reflection, part One

Αυτό το post είναι μέρος μιας τετράδας από blog posts σχετικά με το reflection. Δείτε τα υπόλοιπα εδώ

Το συγκεκριμένο blog post ξεκινάει από μια κουβέντα που είχα σε ένα άλλο forum, όπου μου ζητήθηκε να δώσω μερικές πληροφορίες για το Reflection στο .ΝΕΤ. Well, here it is!

Το reflection στο .ΝΕΤ χρησιμοποιείται για να πάρουμε πληροφορίες σχετικά με τους τύπους/κλάσεις μιας assembly αλλά και για να δημιουργήσουμε κώδικα “on-the-fly”. Το αποτέλεσμα είναι ο κώδικας του επερωτούμενου assembly παρουσιαζόμενος σε ένα οbject model.

Τι είναι η assembly και τι το module;

Ο κώδικας στο CLR “πακετάρεται” σε μία assembly. Εκτός από τον κώδικα, περιλαμβάνονται μεταδεδομένα (metadata) τα οποία το CLR χρησιμοποιεί για να φορτώσει και να εκτελέσει τον κώδικα, αλλά και πληροφορίες για όλους τους τύπους (types) μέσα στην assembly. Το τελευταίο περιλαμβάνει κάθε μέθοδο, property, event, delegate και interface κάθε τύπου. Επιπροσθέτως, υπάρχουν μεταδεδομένα για τον ίδιο τον κώδικα, όπως το μέγεθός του αλλά και τις τοπικές μεταβλητές. Ουσιαστικά, μία assembly είναι ένας λογικός χώρος όπου μέσα φυλάσσονται διάφορες πληροφορίες, και πιο συγκεκριμένα τα εξής

· Assembly metadata

· Type metadata

· IL Code

· Resources

Τα assembly metadata (αλλιώς καλούνται και manifest) περιγράφουνε την ίδια την assembly, όπως το όνομά της, την έκδοση, το culture κ.λ.π. Μπορείτε να δείτε ένα dump του manifest μιας Console εφαρμογής ονόματι Reflection (χρησιμοποιώντας το ILDasm.exe utility) εδώ
 

Untitled
Type metadata
είναι όλες οι πληροφορίες που περιγράφουνε πως είναι ένα type (το namespace, το όνομα του type, επιπρόσθετα types που περιέχει, τα μέλη του, όπως συναρτήσεις, delegates, enumerations κ.λ.π.). Για παράδειγμα, για μία κλάση ονόματι MyClass στο ίδιο με το προηγούμενο assembly (ονόματι Reflection.exe) που έχει ένα public property MyInt που κάνει encapsulate έναν private integer _MyInt, το type metadata δείχνει κάπως έτσι
image

Ο IL Code, είναι ο μεταγλωττισμένος σε IL κώδικας της εφαρμογής. Επί παραδείγματι, για τη Main συνάρτηση της Console εφαρμογής μας, ο κώδικας σε C# είναι
image

και σε IL βλέπουμε ότι έχει γίνει
image

Τα Resources είναι διάφορα αντικείμενα που έχουνε γίνει embed στην assembly και μπορούν να χρησιμοποιηθούν από την εφαρμογή (π.χ. images, icons κ.α.).

Τις περισσότερες φορές, μία assembly περιλαμβάνεται σε ένα και μόνο αρχείο. Κάποιες φορές όμως, μπορεί να θελήσουμε μία assembly να “σπάσει” σε περισσότερα από ένα αρχεία (να σημειωθεί ότι στο Visual Studio 2005 δεν υπάρχει εγγενής υποστήριξη για να γίνει αυτό).  Σε αυτή την περίπτωση ένα κεντρικό αρχείο περιέχει τα assembly metadata ενώ τα type metadata, code και resources μπορεί να είναι είτε στο κεντρικό αρχείο είτε στα υπόλοιπα αρχεία της assembly (τα οποία έχουν την προέκταση .netmodule)

Από την άλλη, τα modules είναι containers για τύπους μέσα σε μια assembly. Δεν χρησιμοποιείται συνήθως, παρά μόνο σε ειδικές περιπτώσεις όπως π.χ. σε ανάμιξη διαφορετικών γλωσσών μέσα σε μία assembly. Το Visual Studio δεν υποστηρίζει πολλαπλά modules σε μία assembly, έτσι η δημιουργία multimodule asemblies γίνεται με ειδικά εργαλεία (MSBuild).

Εξέταση μιας assembly

Για να ξεκινήσουμε να εξετάσουμε μία Assembly, πρέπει να δημιουργήσουμε ένα instance της κλάσης Assembly (αφού κάνουμε using το System.Reflection). Ας δούμε μερικά πράγματα μπορούμε να κάνουμε με αυτό. Ο κάτωθι κώδικας
image

μας δίνει σαν αποτέλεσμα τα ακόλουθα
image

Η GetExecutingAssembly χρησιμοποιείται για να δώσει ένα reference στην εκτελούμενη assembly.

Με τη χρήση της Assembly.ReflectionOnlyLoad(string fullName) και της Assembly.ReflectionOnlyLoadFrom(string path) μπορούμε να διαβάσουμε τα δεδομένα μιας άλλης assembly, αλλά δεν επιτρέπεται να χρησιμοποιήσουμε κώδικα από την συγκεκριμένη assembly ούτε να δημιουργήσουμε νέα instances τύπων που περιλαμβάνονται στην συγκεκριμένη assembly. Αυτό γίνεται γιατί απαιτείται αρκετή δουλειά από το CLR για να φορτωθεί ένας καινούριος τύπος στο τρέχων εκτελούμενο ApplicationDomain, οπότε αυτές οι δύο συναρτήσεις έχουνε προστεθεί για μεγαλύτερη απόδοση. Για να φορτώσουμε μία assembly προκειμένου να χρησιμοποιήσουμε κώδικά της, μπορούμε να χρησιμοποιήσουμε τις μεθόδους Load(string assemblyString), LoadFile(string path), LoadFrom(string assemblyFile).

Με τον κάτωθι τρόπο μπορούμε να πάρουμε διάφορες πληροφορίες για τα modules μιας assembly
image

Μπορείτε να δείτε περισσότερες πληροφορίες για τις κλάσεις Assembly και Module εδώ και εδώ

Assembly Attributes

Τα assembly attributes είναι ιδιότητες που μπορούν να παρέχουν περισσότερες πληροφορίες για μία assembly. Τυπικά, αυτές βρίσκονται σε ένα αρχείο ονόματι AssemblyInfo.cs (AssemblyInfo.vb στη Visual Basic). Μπορείτε να δείτε μερικές εδώ
image

Κατασκευάζονται με τη χρήση του assembly prefix, μετά με ένα string που αναπαριστάνει την εκάστοτε κλάση που θα δοθεί τιμή (για παράδειγμα, το string AssemblyCompany θα δώσει τιμή στην κλάση AssemblyCompanyAttribute).  Με αυτόν τον κώδικα μπορούμε εύκολα να κάνουμε enumerate αυτές τις attributes.

image
Αν θέλουμε να πάρουμε τιμή για κάποια συγκεκριμένη attribute, μπορούμε να χρησιμοποιήσουμε τον παρακάτω κώδικα
image

όπου και παίρνουμε τιμή για το FileVersionAttribute. Stay tuned για το επόμενο blog post, όπου και θα δείξουμε πως να κάνουμε reflection σε Types.

Ο μέχρι στιγμής κώδικας είναι συνημμένος στο παρόν blog post.

The base class includes the field ‘MyControl’, but its type (common_MyControl) is not compatible with the type of control (ASP.common_mycontrol_ascx)

Κατασκευάζετε ή παίρνετε ένα έτοιμο web user control, το τοποθετείτε σε μια aspx σελίδα σε ένα Web Application, δοκιμάζετε να το τρέξετε, και κατά την εκτέλεση του project, αντί για την σελίδα σας, βγαίνει στον browser κάποιο error σαν το παραπάνω;

 Το πρόβλημα μπορεί να οφείλεται σε προβλήματα με το batch compilation ενός web application, ή σε διάφορα circular references μέσα στο ίδιο το project (όπως χαρακτηριστικά αναφέρεται εδώ). Στην περίπτωσή μου (προσπαθούσα να βάλω ένα ScriptManager και ένα UpdatePanel σε μία σελίδα, και κατά την εκτέλεση χτύπαγε ένα παρεμφερές με τον τίτλο του post error), δεν λύθηκε το πρόβλημα. 

Μία άλλη πιθανή λύση που βρήκα ψάχνοντας είναι η απομάκρυνση του id=”…” από το σημείο του HTML κώδικα που έχει τοποθετηθεί το επίμαχο control. Αυτή η λύση βέβαια έχει και τα μειονεκτήματά της, καθώς δεν μπορεί να γίνει reference το control μέσα από κώδικα. 

Δυστυχώς, ούτε με αυτό τον τρόπο κατάφερα να τρέξει το project επιτυχώς. Αυτό που τελικά έκανα και δούλεψε σωστά το web application μου, ήταν να πάω στο MyWebPage.aspx.designer.cs, να πάρω την δήλωση του control από κει και να την γράψω στο MyWebPage.aspx.cs. Με αυτό τον τρόπο, το project δεν εμφανίζει προβλήματα κατά την εκτέλεσή του.Smile

3D tools for the Windows Presentation Foundation

Συλλογή από utilities, με σκοπό την βοήθεια των προγραμματιστών για δημιουργία 3d αντικειμένων στο Windows Presentation Foundation. Μπορείτε να δείτε τη σελίδα στο Codeplex εδώ:

http://www.codeplex.com/3DTools

 και να δείτε ένα πολύ ωραίο video tutorial εδώ

http://www.contentpresenter.com/contentpresenter_3DTools.wmv

Προβλήματα με το svcutil στο Visual Studio 2008 beta 2

Προσπαθείτε να τρέξετε κάποια WCF service από το Orcas Beta 2 και παίρνετε το ακόλουθο σφάλμα κατά την εκτέλεση του test client

Unhandled Exception: System.IO.FileLoadException: Could not load file or assembl
y ‘svcutil, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a’ o
r one of its dependencies. Strong name validation failed. (Exception from HRESUL
T: 0x8013141A)
File name: ‘svcutil, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11
d50a3a’ —> System.Security.SecurityException: Strong name validation failed. (
Exception from HRESULT: 0x8013141A)
The Zone of the assembly that failed was:
MyComputer

Αυτό που χρειάζεται να γίνει είναι το εξής

(Visual Studio Command Prompt->) C:Program FilesMicrosoft SDKsWindowsV6.0ABin>sn -Vr svcutil.exe

Από εδώ

Microsoft Deepfish

Το Deepfish είναι μία εφαρμογή/τεχνολογία που αναπτύσσεται στα Live Labs της Microsoft. Στην ουσία πρόκειται για έναν browser, που έχει κατασκευαστεί με στόχο ένα καλύτερο browsing ιστοσελίδων από Mobile Devices! Διαμορφώνει την ιστοσελίδα προς εμφάνιση ώστε να είναι ανάλογη με την ιστοσελίδα που θα βλέπατε με χρήση ενός browser application. Επιτρέπει zoom-in/zoom-out και εύκολο navigation με τη χρήση του joystick. Αλλά, επειδή τα πολλά λόγια είναι φτώχεια, πάρτε το url και δείτε μόνοι σας

http://labs.live.com/deepfish/default.aspx

 

REMIX07, Βουδαπέστη

Την προηγούμενη βδομάδα ήμουνα στη Βουδαπέστη, όπου και παρακολούθησα το REMIX07! Μπορώ πραγματικά να πω ότι έμεινα εντυπωσιασμένος από το Silverlight! Έχοντας ασχοληθεί με Flash στο παρελθόν και έχοντας αντιμετωπίσει το ‘δύστροπο’ (για τον προγραμματιστή) περιβάλλον του καθώς και τις αδυναμίες της Actionscript, πραγματικά έχω να πω ότι ο συνδυασμός XAML και .NET code είναι εκπληκτικά πρωτοποριακός στο χώρο του Web Development. Το Expression Blend είναι ένα αρκετά ώριμο εργαλείο, μέσω του οποίου μπορεί κάποιος σε ελάχιστα λεπτά να κάνει θαύματα. Anyway, ας παραθέσω μερικά από τα highlights της εκδήλωσης

  1. Την πρώτη θέση δικαίως κατέχει ο Scott Guthrie. Ένας σύγχρονος guru, μας έδειξε πάρα πολύ όμορφα demos σχετικά με κατασκευή Silverlight apps.
  2. Έμεινα πραγματικά εντυπωσιασμένος από την ταχύτητα πληκτρολόγησης αλλά και την ακρίβεια του κώδικα του Steve Marx. Μας έδειξε demos για κατασκευή Vista Gadgets, έναν Video Player με Silverlight και AJAX patterns.
  3. Πολύ καλή ήτανε και η παρουσίαση της Molly Holzschlag, σχετικά με CSS.
  4. Εντυπωσιακός ήτανε και ο Wayne Smith, ο οποίος, χρησιμοποιώντας το Blend, κατάφερε μέσα σε λίγη ώρα να φτιάξει ένα photo gallery (τμήμα του οποίου έκανε reflection πάνω σε ένα donut!).
  5. Πολύ καλός και ο George Moore, με demos από τα APIs που μας παρέχει το Live.
  6. Η river-boat το βράδυ στο Δούναβη! Αξέχαστη, από όλες τις απόψεις!

 

Παραθέτω και δύο photos, η μία έξω και η άλλη μέσα στο χώρο της εκδήλωσης

HPIM0813     DSC05856

Να προσθέσω ότι πολλά demos που παρουσιαστήκανε ομοιάζουν αρκετά με αυτά που παρουσιάστηκαν στην MIX07, και μπορείτε να βρείτε εδώ (credits go to Dimis for the link Smile)

edit: ένα πολύ ενημερωτικό blog post σχετικά με την πόλη της Βουδαπέστης έχει γράψει ο συνάδελφος Dimis εδώ

Τεχνολογίες Εφαρμογών Διαδικτύου – 2ο εργαστήριο

Σήμερα διεξήχθη στο τμήμα Πληροφορικής και Τηλεπικοινωνιών το δεύτερο εργαστήριο με θέμα την ASP .NET, στα πλαίσια του μαθήματος “Τεχνολογίες Εφαρμογών Διαδικτύου”. Θα ήθελα να ευχαριστήσω θερμά τους

  • Φοιτητές που ήρθανε και μας παρακολουθήσανε. Πραγματικά μας δίνετε δύναμη!! Smile
  • Τον Δημήτρη Ράπτη (dimis) και στον Στέλιο Καραμπασάκη (skarab) για την πολύτιμη βοήθειά τους στην επιλογή/σχεδιασμό/ανάλυση των θεμάτων που παρουσιάστηκαν καθώς και για την πολύτιμη βοήθειά τους κατά το 12ωρο των δύο εργαστηρίων. Καθώς και τον Άγγελο Μπιμπούδη (grnemo), για τη βοήθεια και την συμπαράστασή του.
  • Τον Στέφανο Σταμάτη, ενός εκ των admins του τμήματος για την πολύτιμη βοήθειά του.
  • Τον Αναπληρωτή Καθηγητή Δ. Μαρτάκο, για την ευγενική του άδεια να πραγματοποιήσουμε το εργαστήριο στα πλαίσια του μαθήματος που διδάσκει αυτό το εξάμηνο.

Συνοπτικά, τα θέματα που παρουσιαστήκανε (τα πρώτα 5 στο πρώτο εργαστήριο και τα άλλα 5 σήμερα) είναι

1. Εισαγωγή στο Visual Web Developer 2005
2. Κατασκευή  διεπαφής χρήστη διαδικτυακής εφαρμογής
3. Events – PostBack
4. Web Application State
5. Debugging  –  Tracing  a  Website
6. Style Sheets  –  Master Page
7. Databinding to User Interface Control
8. GridView  –  FormView
9. Login Controls  –  Membership
10. Configuring  –  Building  –  Deploying

Στο δεύτερο τμήμα προλάβαμε και δείξαμε λίγα πραγματάκια σχετικά με Web Services και winforms clients. 

Συνημμένα μπορείτε να βρείτε τα powerpoint presentations, demos καθώς και τις σημειώσεις που χρησιμοποιήθηκαν στα δύο εργαστήρια, καθώς και τη mini εφαρμογή που κατασκεύασα προκειμένου να δημιουργήσω sql server 2005 databases για τον καθέναSmile

Άντε, και του χρόνου!!Big Smile