Teched 2007, Barcelona – Day 1

Δείτε εδώ τα υπόλοιπα blog posts για την Teched 2007

Πρώτη μέρα σήμερα του TechEd 2007, είχα την τύχη να παρακολουθήσω μερικά αρκετά ενδιαφέροντα sessions. Ξεκινήσαμε με το keynote, όπου μίλησε ο S. Somasegar. Μια εισαγωγική ομιλία, με κύριο περιεχόμενο τις τεχνολογίες που έρχονται με το Visual Studio 2008.

Πιο συγκεκριμένα, ανέφερε πως τα downloads του Visual Studio Express 2005 είναι 17.000.000 (πραγματικά τρόμαξα με το νούμερο) ενώ το Visual Studio 2005 το χρησιμοποιούν περί τους 1.000.000 developers. Πρόκειται πραγματικά για μια πάρα πολύ μεγάλη βάση χρηστών, η οποία είναι κάτι παραπάνω από σίγουρο ότι θα επιδοκιμάσει και θα επιδιώξει να χρησιμοποιήσει τις νέες τεχνολογίες όσο γίνεται πιο γρήγορα. Ποιες είναι αυτές; Αναφέρω μερικές επιγραμματικά

  • LINQ
  • Silverlight
  • Windows Presentation Foundation
  • Windows Communication Foundation
  • Workflow Foundation
  • Popfly

Ανέφερε επίσης, ότι η βοήθεια που προσφέρεται για τους developers ολοένα γίνεται και πιο εποικοδομητική. Το 80% των ερωτήσεων στα MSDN forums έχουν απαντηθεί, στο MSDN υπάρχει πλέον και code gallery, ενώ εξίσου σημαντική προσθήκη είναι το MSDN translation wiki.

Έκανε επίσης και 3 mini ανακοινώσεις

  • Microsoft Sync Framework CTP, για synchronization δεδομένων
  • S+S blueprints, guidance + best practices plugin for Visual Studio
  • New popfly Explorer for Visual Studio

Και τα τρία εργαλεία αναμένονται αρκετά σύντομα. Η τελική έκδοση του Visual Studio 2008 αναμένεται μέσα στο Νοέμβρη.

Στη συνέχεια, ανέβηκε ο Tony Goodhew, ο οποίος έκανε μια μικρή παρουσίαση του Visual Studio 2008 και μερικών προγραμμάτων που μπορούν εύκολα να κατασκευαστούν με τη χρήση αυτού. Ανάμεσα σε αυτά που έδειξε είναι

  • Split html/code view για web pages
  • Δυνατότητα του Visual Studio 2008 να παράγει εκτελέσιμα για 3 εκδόσεις του framework: 2, 3 και 3.5
  • Τον object/relational designer, μέσω του οποίου μπορούμε πολύ εύκολα να φτιάξουμε mapped κλάσεις για μια SQL βάση δεδομένων και να “παίξουμε” με αυτήν χρησιμοποιώντας DLINQ.
  • Δυνατότητα για Javascript debugging
  • Χρήση του ElementHost για εμφάνιση WPF περιεχομένου σε ένα outlook e-mail

Τη σκυτάλη πήρε ο Dan Fernandez. Μίλησε για Visual Studio extensibility, και μας έδειξε ένα φανταστικό sample, με το Visual Studio να κάνει host μία scripting γλώσσα για δημιουργία extension για το World of Warcraft.

Τέλος, ο S. Somasegar μας έδειξε μια πολύ ωραία διαφάνεια με το roadmap των developer προϊόντων, αλλά και ένα πολύ ωραίο promo video του Visual Studio 2008.

Στη συνέχεια, πήγα στο room 117 για να παρακολουθήσω το πρώτο μέρος της παρουσίασης “Building a complete web application using ASP.NET ‘Orcas’ and Visual Studio 2008”. Εισηγητής ήτανε ο Omar Khan. Αρκετά αξιόλογος, μας έδειξε αρχικά τον HTML designer του Visual Studio 2008. Με δυνατότητες όπως υποστήριξη για nested master pages, split designer/source view και σαφώς ανώτερη css editing υποστήριξη, παρουσιάζεται κλάσεις ανώτερος από αυτόν του Visual Studio 2005. Είδαμε μερικά demos για CSS editing και για σχεδιασμό ενός .dbml αρχείου για object/relational mapping. Τόνισε ιδιαίτερα πως οι κλάσεις στο .dbml αρχείο κάνουν implement το INotifyPropertyChanging και το INotifyPropertyChanged (οπότε είναι αρκετά σαφής η εύκολη χρήση τους για data binding) αλλά και υποστηρίζουν πλήρως το System.Nullable<T>, οπότε δεν χρειάζεται να καταφύγουμε σε περίεργα tricks όταν μας έρχεται μια null τιμή από μια βάση.

Στη συνέχεια, μας έγινε μια επίδειξη data binding σε ένα asp.net gridview, και στη συνέχεια είδαμε χρήση LINQ queries με lambda expressions, αλλά και των function IQueryable<T>.Skip(startRow).Take(numberOfRows), για paging. Τέλος, είδαμε πως μπορούμε να “μαντέψουμε” ποια μέθοδο του datacontext πρέπει να κάνουμε override ώστε να φτιάξουμε validation για το DAL μας. Στην εύρεση της συνάρτησης βοηθάει ένα νέο χαρακτηριστικό της C# 3.0, τα partial methods (ελπίζω σε λίγο καιρό να γράψω μερικά πραγματάκια παραπάνω για το τι νέο μας φέρνει η C# 3.0).

Κατόπιν, πήγα στην αίθουσα 112. Θέμα “LINQ framework”, εισηγητής ο Luca Bolognese. Μας έγινε μια περιγραφή των core τμημάτων του LINQ framework, τα οποία είναι

  • LINQ to Objects
  • LINQ to SQL
  • LINQ to XML
  • LINQ to Dataset
  • LINQ to Entities

Έγινε αναφορά σε διάφορα features της C# 3.0, όπως automatic properties, type inference, lambda expressions, object initializers, collection initializers, anonymous types.

Έδειξε ότι τα LINQ queries για fetch δεδομένων παραμένουν τα ίδια, είτε το source είναι π.χ. List<T>, XML, Dataset, Database. Όλα αυτά λόγω των IQueryable<T> υλοποιήσεων αλλά και λόγω των Expression Trees.

Είδαμε και πως μπορούμε να βλέπουμε τα queries που φτιάχνει το LINQ στο runtime. Τόσο με τη χρήση του debugger, όσο και με τη χρήση του myDatacontext.Log = Console.Out.

Τέλος, είδαμε το XElement και πώς μπορεί να φτιάξει κανείς δυναμικά XML documents με τη χρήση του, αλλά και τη δυνατότητα της Visual Basic 9 για συγγραφή XML κώδικα μέσα στο .vb αρχείο! Ιδιαίτερη αναφορά πρέπει να γίνει και στο εξαιρετικό χιούμορ του παρουσιαστή.

Πριν τον γυρισμό στο ξενοδοχείο, κάναμε μια βόλτα και από τον εκθεσιακό χώρο, όπου πήραμε δωρεάν το βιβλίο “The security development lifecycle”, με υπογραφή ενός εκ των συγγραφέων, του κυρίου Michael Howard, ο οποίος είναι και speaker στην TechEd (ναι, ναι είναι αυτός που έχει γράψει και το Writing Secure Code).  

Αυτά για σήμερα, φωτογραφίες κατά πάσα πιθανότητα θα ανεβάσω αύριο!!!

Δεύτερο Studentguru event

Με επιτυχία ολοκληρώθηκε το δεύτερο StudentGuru event σήμερα, 2 Νοεμβρίου!! Πολλά ευχαριστώ στα 80 περίπου άτομα που ήρθανε και μας παρακολουθήσανε, σας υπόσχομαι ότι θα έχουμε πολλά ενδιαφέροντα events φέτος!

Νά’στε καλά!!!!!

Μπορείτε να κατεβάσετε την παρουσίαση και τα demos του session σχετικά με τη C# από εδώ

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