2009-05-12 2 views
2

Encore et encore, je me trouve à développer des écrans d'application métier WinForm qui ont un tas de zones de texte pour les critères de recherche, puis un bouton de recherche. Ceux-ci sont mappés dans une expression en utilisant Linq, puis transmis sur ma couche Linq2Sql.Quel motif de conception dois-je utiliser pour créer une carte de liaison facile entre une requête et des zones de texte pour les écrans de recherche Linq?

Je voudrais créer un moyen facile de « lier » ces zones de texte à la requête sous-jacente en utilisant différentes options comme « contient », « startswith », « ExactMatch », etc ...

Qu'est-ce que je m est d'imaginer quelque chose comme ceci (notez SearchBinderT est imaginaire):

SearchBinder<Customer> searchBinder = new SearchBinder<Customer>(); 
searchBinder.Bind(txtFirstName, a=>a.FirstName, SearchBinderOptions.StarsWith); 
searchBinder.Bind(txtLastName, a=>a.LastName, SearchBinderOptions.StarsWith); 
searchBinder.Bind(txtTelephone, a=>a.Phone, SearchBinderOptions.Equals); 
searchBinder.SetAction(btnSearch, MyMethodThatHandlesTheExpressionTreeAndFillsTheResults); 

en cliquant sur la recherche générerait automatiquement l'arbre d'expression où les zones de texte ne sont pas vides et exécuter la recherche. Mais ce n'est qu'un modèle dans ma tête - il y en a beaucoup d'autres. Je suis principalement concentré sur le développement rapide d'applications. Quel (s) motif (s) de conception utiliseriez-vous pour cela (ou est ce que je pense être bon)?

  • Comment réagiriez-vous d'autres types de données (dates/numéros avec moins/supérieur)
+0

Je dois dire que c'est un concept plutôt sympa. Je vais le voler si cela ne vous dérange pas :-) –

Répondre

0

Ne serait-exécution retardée et l'état capturé de lambdas résoudre ce problème?

Predicate<Customer> searchQuery = c => { 
    c.FirstName.StartsWith(txtFirstName.Text) 
    && c.LastName.StartsWith(txtLastName.Text) 
    && c.Phone == txtTelephone.Text; 
} 

void btnSearch_Click(object sender, EventArgs e) { 
    return IEnumerable<Customer>.Where(searchQuery); 
} 

Depuis searchQuery n'est pas exécutée jusqu'à ce que les clics de bouton, il n'y a pas besoin de faire abstraction les comparaisons aux composants « constructeur ». Il y a tout le problème multithread avec l'accès aux zones de texte, mais vous pouvez utiliser un Expression<T> à la place et décomposer et reconstruire avec Control.Invoke. Ou, écrivez-le simplement avec Invoke pour commencer. Ou, renvoyez-le au thread d'interface utilisateur à exécuter. Mais, si vous vouliez vraiment aller avec votre conception - je suggérerais d'utiliser Expression<T> au lieu des opérateurs de comparaison que vous avez. C'est plus flexible, et vous économiserez beaucoup de travail. En ce qui concerne le motif de conception, le plus proche que je connaisse serait un Query Object - lequel [N] Hibernate a la forme Criteria. Il s'agit plutôt de construire des requêtes dynamiques, sans se lier aux éléments de l'interface utilisateur (ce dont je ne vois pas non plus le but). Dans votre exemple, votre requête est codée en dur - donc je ne suis pas sûr de ce que serait l'avantage.

+0

Le composant générateur aurait la logique de construire le prédicat en fonction de savoir si les zones de texte ont été remplies ou non. une zone de texte vide doit être exclue de la requête. Votre prédicat n'en tient pas compte. – TheSoftwareJedi

+0

Bon - alors il semble que vous vouliez un objet de requête qui est databound aux contrôles. Si les valeurs sont vides, vous les laisserez hors de la requête (qui est le modèle d'objet de requête normal). –

Questions connexes