Λάθος. Τα expression trees χρησιμεύουν σε πολύ περισσότερα πράγματα από LINQ providers. Όσο για το serialization ... δεν χρησιμοποιούνται τα expression trees για serialization αλλά το αντίστροφο: αν θέλεις να στείλεις ένα expression tree από ένα process σε ένα άλλο, μπορείς να χρησιμοποιήσεις ΚΑΙ .NET serialization. Ή να μετατρέψεις το expression tree σε ένα κοινό string format (π.χ. SQL, FORTRAN, καντονέζικα) και να στείλεις αυτή τη μορφή.
Τα expression trees σχετίζονται άμεσα με το parsing. To expression tree είναι η δομή που δημιουργείται όταν γίνεται parse ένα expression είτε είναι LINQ είτε αριθμητική πράξη. Αυτή τη δομή μετά την επεξεργάζεται το σύστημα ή ο δικός σου κώδικας για να κάνει "κάτι". Αυτό μπορεί να είναι να δημιουργήσει SQL statements και Sharepoint CAML queries, ή να εκτελέσει κώδικα για κάθε διαφορετικό statement και operator που θα βρει. Επιπλέον, μπορείς να κάνεις compile ένα expression tree και να εκτελέσεις τον κώδικα που αντιπροσωπεύει.
Για παράδειγμα, το DLR δημιουργεί expression trees για να εκτελέσει τον κώδικα που του δίνεις σε μία δυναμική γλώσσα στο runtime. Ή μπορείς εσύ να φτιάξεις ένα mini parser που θα παίρνει π.χ. φόρμουλες που δίνει ο χρήστης (σε στυλ Excel) και θα τις μετατρέπει σε expression tree για εκτέλεση. Αν θέλεις να φτιάξεις δυναμικά ένα LINQ Query θα πρέπει να φτιάξεις το αντίστοιχο LINQ expression tree με κώδικα.
Τα expression trees και τα lambdas συνδέονται γιατί στο .ΝΕΤ μπορείς άνετα να περάσεις ένα lambda είτε ως function, είτε ως expression χωρίς να αλλάξεις τον κώδικα σου. Αυτό επιτρέπει κάποιες πολύ ενδιαφέρουσες τεχνικές.
Για παράδειγμα, στο Silverlight και το WPF (και όχι μόνο) σηκώνεις το PropertyChanged event για να ειδοποιήσεις ότι κάποιο property άλλαξε. Το event δέχεται ως παράμετρο ένα string και προφανώς, αν αλλάξεις όνομα στο property χωρίς να αλλάξεις και το string, την πάτησες. Ένας τρόπος να αποφύγεις το πρόβλημα είναι να ορίσεις είναι ένα function του στυλ RaisePropertyChanged(()=>MyPropertyName). Αν η RaisePropertyChanged οριστεί ως RaisePropertyChanged<T>(Funct<T> param1), το param1 είναι ένα function που θα σου γυρίσει την τιμή του property. Άν όμως οριστεί ως Expression<Func<T>>, είναι ένα expression tree το οποίο περιέχει το function. Από αυτό το expression μετά μπορώ να τραβήξω το όνομα του property. Αν τώρα κάποιος αλλάξει το όνομα του property χωρίς να αλλάξει και την κλήση του RaisePropertyChanged, ο compiler θα χτυπήσει και θα σε ειδοποιήσει.
Την παρακάτω (απλοποιημένη) υλοποίηση την έχω αντιγράψει από το Caliburn.Micro
public virtual void NotifyOfPropertyChange<TProperty>(Expression<Func<TProperty>> property) {
RaisePropertyChanged(property.GetMemberInfo().Name);
}
και καλείται άνετα ως NotifyOfPropertyChange(()=>MyProperty);
Σε αυτή τη συζήτηση θα βρεις και άλλη μία παρόμοια χρήση. Το client library του Sharepoint απαιτεί να του δώσεις με τον ίδιο τρόπο lambdas με τα ονόματα των πεδίων που θέλεις να φορτώσεις. Χωρίς να έχω ψάξει σε βάθος τον κώδικα του Sharepoint, υποθέτω ότι θα μπορούσαν να στείλουν το expression tree στον server για να μετατρέψουν το DataTable που σου επιστρέφει ο server στο OData stream που περιμένει ο client.
Τα expression trees επιτρέπουν επίσης το metaprogramming: Να δώσεις τη δυνατότητα στο πρόγραμμα σου να φτιάχνει το ίδιο τον κώδικα που πρέπει να εκτελέσει. Για παράδειγμα, αν έχεις μία περίπλοκη διαδικασία της οποίας τα βήματα εξαρτώνται από τα στοιχεία που δίνει ο χρήστης, μπορείς να τη σπάσεις σε απλά βήματα και να δομήσεις το expression tree της συνολικής διαδικασίας με βάση τα στοιχεία του χρήστη.
Ένα παράδειγμα metaprogramming θα ήταν π.χ. σε ένα GIS σύστημα ή σε ένα παιχνίδι, να ορίσεις τις ενέργεις που θα πρέπει να γίνουν αν μετακινήσεις ένα αντικείμενο από το σημείο Α στο Β ανάλογα με τις συνθήκες: υπάρχει δρόμος, έχουμε βενζίνη ή ενέργεια, ειδοποιώ άλλα συστήματα για τη μετακίνηση? Μπορείς μάλιστα να δεις τα LINQ statements ως μία πολύ απλή μορφή metaprogramming, καθώς τα Where, Select κλπ δημιουργούν βήμα - βήμα τον κώδικα που θα εκτελεστεί στο τέλος όταν καλέσεις την ToList().
Παναγιώτης Καναβός, Freelancer
Twitter: http://www.twitter.com/pkanavos