2017-05-11 5 views
0

J'ai une application Windows Forms/Visual Basic .NET qui agit essentiellement comme un éditeur. L'une des fonctions qu'il devrait fournir à ses utilisateurs est la possibilité d'exécuter un ensemble de règles sur leur projet actuel et de signaler tout problème qu'il trouve. Ces règles seront toutes exécutées par un objet BackgroundWorker vivant dans un formulaire, de sorte que la progression de l'exécution peut être signalée. Ma stratégie pour implémenter ceci est de donner au formulaire un tas de méthodes d'instance privées qui saisissent les données de projet de l'utilisateur (contenues dans, par exemple, un objet ProjectData), exécutent la vérification nécessaire à cette étape, et retournent un objet contenant des informations affichables sur le test et s'il a réussi ou échoué. (Appelons cette classe CheckResult à des fins de discussion). Donc, pour être clair, toutes ces méthodes ont une signature le long des lignes de:Dans Visual Basic .NET, comment puis-je lister et appeler toutes les fonctions de classe avec un attribut personnalisé donné?

Private Function SomeCheckToRun(data As ProjectData) As CheckResult 

Je pouvais définir simplement toutes ces méthodes comme d'habitude et la liste manuellement-les un par un pour être appelé dans le gestionnaire d'événements DoWork de BackgroundWorker, mais cette approche semble être fastidieuse pour un nombre potentiellement important de contrôles. Ce serait bien si je pouvais simplement définir chaque méthode que je veux exécuter et la faire décorée en tant que telle, afin qu'une boucle puisse trouver automatiquement chaque définition de méthode et l'exécuter. Ce que je pense que je voudrais faire à la place est de définir une classe d'attribut personnalisée utilisée pour indiquer quelles méthodes d'instance sont censées être exécutées comme des contrôles (peut-être appelé CheckToRunAttribute), puis utiliser la réflexion pour obtenir une liste de toutes ces méthodes sont actuellement implémentées dans le formulaire et exécutent chacune d'elles en séquence, peut-être en mettant en place un délégué à exécuter pour chacune d'entre elles. Le nombre de ces méthodes au total, et combien ont été exécutées jusqu'à présent, peut être utilisé par BackgroundWorker pour indiquer les progrès globaux.

Jusqu'à présent, la structure de mon code ressemblerait à quelque chose comme ce qui suit dans mon esprit:

Private Sub MyBackgroundWorker_DoWork(sender As Object, e As DoWorkEventArgs) Handles MyBackgroundWorker.DoWork 
    ' TODO: Get a list of all the <CheckToRun()> methods here, 
    '  run each one in a loop, and report progress after each one. 
End Sub 

' Further down... 

<CheckToRun()> 
Private Function SomeCheckToRun(data As ProjectData) As CheckResult 
    ' Check code in here. 
End Function 

<CheckToRun()> 
Private Function AnotherCheckToRun(data As ProjectData) As CheckResult 
    ' Check code in here. 
End Function 

<CheckToRun()> 
Private Function YetAnotherCheckToRun(data As ProjectData) As CheckResult 
    ' Check code in here. 
End Function 

' And so on... 

Ce n'est pas quelque chose que j'ai beaucoup d'expérience avec faire bien. Je connais la fonction Type.GetMethods(), how to write custom attributes, et la Func(T, TResult) delegate, mais je ne sais pas comment tout mettre ensemble pour ce que je veux.

tl; dr: Étant donné une classe avec plusieurs fonctions d'instance privée suivant la même signature et toutes marquées avec le même attribut personnalisé, comment puis-je compter le nombre d'unités, puis les exécuter chacune?

Répondre

2

Vous pouvez utiliser Reflection pour lister toutes les méthodes avec votre attribut personnalisé. Ceci est une solution LINQ:

Dim methods = Me.GetType.GetMethods(Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance)_ 
         .Where(Function(m) m.GetCustomAttributes(GetType(CheckToRun), False)_ 
         .Length > 0).ToArray() 

Et puis les exécuter comme:

For Each method As Reflection.MethodInfo In methods 
    method.Invoke(Me, New Object() {methodParams}) 
Next 
+0

fonctionne comme un charme! Cela me sauvera une tonne de travail. Merci beaucoup! –