La fonctionnalité « Coller en tant que… » des applications telles que Microsoft® Word est devenue indispensable pour moi. Je copie souvent quelque chose à partir du Web afin de le copier dans un document sans la mise en forme HTML. Coller en tant que est l'outil idéal.
Un jour, en examinant un exemple de code sur le Web, je me suis dit que la fonctionnalité Coller en tant que serait également intéressante dans Visual Studio®. Cependant, plutôt que de convertir simplement la mise en forme du texte, elle pourrait convertir le langage du code. Il est courant de coder en C# et de trouver un exemple Visual Basic® et qui fait exactement ce que vous souhaitez, ou inversement. L'utilisation de ce code nécessite la copie de l'exemple vers le presse-papiers, l'accès à l'un des nombreux sites Web de conversion de code, le collage dans le code, sa conversion, la copie du nouveau code, puis le collage du code converti dans Visual Studio.
Lorsque je trouve un exemple de code C# sur un site Web, j'aimerais pouvoir éviter les étapes de conversion intermédiaires et simplement Coller en tant que Visual Basic dans l'éditeur de code. Tous les blocs nécessaires sont en place pour cela ; j'ai simplement besoin de code pour les réunir.
Découvrez l’article original en anglais.
Cet article traite des sujets suivants :
| • | Utilisation des services Web de conversion de code |
| • | Code de test d'unité |
| • | Création d'un complément Visual Studio |
| • | Ajout d'éléments de menu à Visual Studio |
Cet article utilise les technologies suivantes :
| • | Visual Studio 2005, Visual Basic .NET |
| • | Téléchargement de code disponible à l'adresse suivante :PasteAs.exe (875 ko) |
Scott Swigart est consultant, rédacteur et intervenant sur les technologies convergentes et émergentes. Scott est l'auteur de plusieurs livres sur .NET, est formateur certifié Microsoft (MCT) et développeur certifié Microsoft (MCSD), ainsi que Microsoft MVP. Vous pouvez contacter Scott à l'adresse scott@swigartconsulting.com.
| Création du complément | |
| Tests | |
| Ajout d'un complément | |
| Formulaire de conversion | |
| Conclusion |
Il existe différents convertisseurs de code sur le Web ; je souhaitais donc organiser le complément Paste as Visual Basic (coller en tant que Visual Basic) afin que l'utilisateur puisse choisir le convertisseur à utiliser. Lorsque vous utilisez des solutions Web, il n'existe aucune garantie qu'un site Web particulier restera opérationnel indéfiniment, ou qu'il ne changera pas son implémentation d'une façon qui endommage le code. L'utilisation de plusieurs services de conversion permet d'augmenter la probabilité qu'il existera toujours un service disponible pour effectuer la conversion. En outre, les différents convertisseurs de code utilisent différents algorithmes, dont certains fonctionnent mieux ou moins bien pour un élément de code particulier. Enfin, je souhaitais qu'il soit facile pour le complément Visual Studio de prendre en charge les convertisseurs supplémentaires à l'avenir.
Pour dissocier l'implémentation du convertisseur du reste du code, j'ai défini l'interface IConvertCode. Cette interface décrit l'opération de conversion dans son ensemble, mais elle laisse l'implémentation spécifique aux autres classes. L'interface IConvertCode est relativement simple :
Public Interface IConvertCode
Function Convert(ByVal csCode As String) As String
ReadOnly Property ConverterName() As String
End Interface
La méthode Convert prend le code C# en tant qu'argument de type chaîne et renvoie le code Visual Basic en tant que chaîne. La propriété ConverterName renvoie le nom du convertisseur, de sorte que l'utilisateur puisse choisir le convertisseur à utiliser.
La première implémentation de cette interface utilise le service Web de Kamal Patel de conversion de code C# en Visual Basic, actuellement disponible à l'adresse ConvertCSharp2VB. Une fois qu'une référence est ajoutée à ce service, le code à appeler est relativement direct, comme illustré dans le code ci-dessous.
Calling a Conversion Web Service
Public Class WSConvert
Implements IConvertCode
Public Function Convert(ByVal csCode As String) As String _
Implements IConvertCode.Convert
Dim codeConverter As _
New CSToVBWebService.ConvertCSharp2VBService()
Return codeConverter.Execute(csCode)
End Function
Public ReadOnly Property ConverterName() As String _
Implements IConvertCode.ConverterName
Get
Return "Kamal Patel's Converter"
End Get
End Property
End Class
Le service Web expose une méthode Execute qui accepte du code C# et qui renvoie du code Visual Basic. Dans la mesure où le service Web utilise la même signature que IConvertCode.Convert, les arguments de IConvertCode.Convert peuvent simplement être transmis au service Web et les résultats peuvent être renvoyés.
Le convertisseur de code de Carlos Aguilar Mares, qui utilise AJAX, est également un outil intéressant, disponible à l'adresse Convertisseur de code. Cette opération effectue la conversion entre C# et Visual Basic lors de la saisie. En coulisse, le code est publié sur carlosag.net/Tools/CodeTranslator/translate.ashx sous forme de champs de formulaire. Une autre implémentation de IConvertCode utilise cette fonctionnalité pour effectuer la conversion, comme illustré figure 2.
Using a Form-Based Converter
Public Class CAConvert
Implements IConvertCode
Public Function Convert(ByVal csCode As String) As String _
Implements IConvertCode.Convert
Dim formFields As New NameValueCollection
formFields.Add("code", csCode)
formFields.Add("Language", "C#")
formFields.Add("DestinationLanguage", "VB")
Dim client As New WebClient
Return Encoding.ASCII.GetString( _
client.UploadValues( _
"http://www.carlosag.net/Tools/" & _
"CodeTranslator/translate.ashx", _
"POST", formFields _
) _
)
End Function
Public ReadOnly Property ConverterName() As String _
Implements IConvertCode.ConverterName
Get
Return "Carlos Aguilar's Converter"
End Get
End Property
End Class
Cette implémentation publie le code C# sous forme de champs de formulaire vers une adresse Web. Le code Visual Basic est renvoyé en tant que corps de la réponse HTTP. Pour envoyer le code C#, une collection NameValueCollection est utilisée. Le code C# est ajouté en tant qu'élément de code, le langage source est spécifié en tant qu'élément Language et le résultat Visual Basic est spécifié en tant qu'élément DestinationLanguage. Une fois la collection remplie, elle est envoyée à l'adresse Web via la méthode WebClient.UploadValues. Cette méthode publie les champs de formulaire et reçoit les résultats sous forme de tableau d'octets. Encoding.ASCII.GetString est utilisé pour reconvertir le tableau d'octets en chaîne. Cette chaîne contient la conversion Visual Basic.Vous pouvez voir que, si les implémentations internes sont assez différentes, les deux convertisseurs satisfont à l'interface IConvertCode en ce sens qu'elles fournissent des méthodes qui acceptent le code C# en tant que chaîne et renvoient le code Visual Basic en tant que chaîne.
J'ai placé les implémentations de conversion de code dans un projet de bibliothèque de classes. Par le passé, j'aurais probablement créé une application Windows Form simple pour tester mes deux convertisseurs, afin de m'assurer de leur bon fonctionnement. Cependant, Visual Studio 2005 Team Edition for Software Developers offre des fonctionnalités de test intégrées. Il me suffit de cliquer avec le bouton droit de la souris dans une méthode afin de générer rapidement un test pour cette méthode.
La première fois que vous créez un test, un nouveau projet est ajouté à votre solution et le code de test est placé dans ce projet. Le test d'unité de l'une des méthodes de conversion est illustré :
Unit Test for Form-Based Conversion
<TestMethod()> _
Public Sub CAConvertTest()
Dim target As IConvertCode = New CAConvert()
Dim csCode As String = My.Computer.FileSystem.ReadAllText( _
DataDir & "\CSCode.txt")
Dim expected As String = My.Computer.FileSystem.ReadAllText( _
DataDir & "\CAVBCode.txt")
Dim actual As String
actual = target.Convert(csCode)
Assert.AreEqual(expected, actual, _
"PasteAsVB.CAConvert.Convert did not return the expected value.")
End Sub
Le test charge le code source C# à partir d'un fichier texte. Le code est converti en Visual Basic et est comparé à un autre fichier contenant les résultats attendus. Si les résultats correspondent, le test est réussi. La fenêtre Gestionnaire des tests me permet d'exécuter rapidement mes tests. Si j'ajoute d'autres convertisseurs par la suite, ou que j'apporte des modifications à ma logique existante, ces tests doivent me donner un moyen rapide de m'assurer que tout fonctionne correctement.
Maintenant que je sais que les convertisseurs fonctionnent comme prévu, il est temps de créer un complément pour Visual Studio 2005. Vous pouvez créer un complément en ajoutant un nouveau projet de complément à votre solution. Les compléments sont disponibles sous Projets d'extensibilité, comme illustré figure 4.
Création d'un projet de complément
L'assistant vous pose un certain nombre de questions afin de vous aider à créer le squelette du complément. Vous êtes invité à spécifier un nom, à indiquer si vous souhaitez que le complément s'affiche dans la barre d'outils, si le complément doit être chargé au démarrage de Visual Studio et s'il est toujours non modal afin d'être sûr pour une utilisation à partir de la ligne de commande.
Contrairement à Visual Studio .NET 2003, le projet de complément pour Visual Studio 2005 contient le code requis pour la connexion de votre complément dans l'environnement de développement. La classe de complément implémente IExtensibility2, l'interface qui sera utilisée par Visual Studio pour communiquer avec le complément. Certaines méthodes clé, telles que OnConnection et QueryStatus, sont également écrites pour vous. La méthode Exec (appelée lorsque l'utilisateur appelle votre complément) est également remplacée.
Lorsque vous définissez le complément comme projet de démarrage et que vous appuyez sur F5, une chose surprenante se produit : une nouvelle instance de Visual Studio est lancée, avec le complément installé. Vous pouvez utiliser cette nouvelle instance de Visual Studio afin de tester le complément. Vous pouvez même définir des points d'arrêt et déboguer votre complément comme n'importe quel autre morceau de code. Le lancement du complément dans une instance de test de Visual Studio est une nouvelle fonctionnalité bienvenue dans Visual Studio 2005.
Je souhaite apporter quelques modifications au code à ce stade du processus. Tout d'abord, le complément s'affiche sous le menu Outils par défaut. Je souhaite réellement qu'il s'affiche sous le menu Édition, immédiatement après l'élément de menu Coller. Le code ci-dessous affiche la méthode OnConnection modifiée.
Modified OnConnection Method
Public Sub OnConnection(ByVal application As Object, _
ByVal connectMode As ext_ConnectMode, _
ByVal addInInst As Object, _
ByRef custom As Array) Implements IDTExtensibility2.OnConnection
_applicationObject = CType(application, DTE2)
_addInInstance = CType(addInInst, AddIn)
If connectMode = ext_ConnectMode.ext_cm_UISetup Then
Dim commands As Commands2 = CType( _
_applicationObject.Commands, Commands2)
Dim editMenuName As String
Try
Dim resourceManager As System.Resources.ResourceManager = _
New System.Resources.ResourceManager( _
"PasteAsVBAddIn.CommandBar", _
System.Reflection.Assembly.GetExecutingAssembly())
Dim cultureInfo As System.Globalization.CultureInfo = _
New System.Globalization.CultureInfo( _
_applicationObject.LocaleID)
editMenuName = resourceManager.GetString( _
String.Concat(cultureInfo.TwoLetterISOLanguageName, _
"Edit"))
Catch e As Exception
editMenuName = "Edit"
End Try
Dim commandBars As CommandBars = _
CType(_applicationObject.CommandBars, CommandBars)
Dim menuBarCommandBar As CommandBar = commandBars.Item("MenuBar")
Dim editControl As CommandBarControl = _
menuBarCommandBar.Controls.Item(editMenuName)
Dim editPopup As CommandBarPopup = CType(editControl, CommandBarPopup)
Try
Dim command As Command = commands.AddNamedCommand2( _
_addInInstance, "PasteAsVBAddIn", _
"Paste as Visual Basic", _
"Convert the clipboard content from C# " & _
"to Visual Basic and paste", _
True, 59, Nothing, _
CType(vsCommandStatus.vsCommandStatusSupported,Integer)+ _
CType(vsCommandStatus.vsCommandStatusEnabled, Integer), _
vsCommandStyle.vsCommandStylePictAndText, _
vsCommandControlType.vsCommandControlTypeButton)
command.AddControl(editPopup.CommandBar, 12)
Catch argumentException As System.ArgumentException
End Try
End If
End Sub
Quelques modifications importantes sont apportées au code de cette méthode. Tout d'abord, le projet inclut un fichier de ressource nommé CommandBar.resx, qui contient le texte des éléments de menu Visual Studio de niveau supérieur dans de nombreux langages. La ligne de code suivante recherche un élément de menu, avec le code de langue à deux lettres comme préfixe :
editMenuName = resourceManager.
GetString( _
String.Concat(cultureInfo.TwoLetterISOLanguageName, "Edit"))
Si vous exécutez ce code sur un ordinateur configuré pour l'anglais américain, il recherche une chaîne de ressource nommée enEdit dans CommandBar.resx. Si l'ordinateur avait été configuré pour l'allemand, il rechercherait deEdit. Ce code renvoie le texte propre à la langue pour l'élément de menu, requis pour localiser cet objet de menu par programmation. Une fois le menu de niveau supérieur localisé, vous pouvez y ajouter des sous-menus. Les lignes de code suivantes localisent l'objet de menu réel :
Dim editControl As CommandBarControl = _
menuBarCommandBar.Controls.Item(editMenuName)Dim editPopup As
CommandBarPopup = CType(editControl, CommandBarPopup)
Une fois la barre de menu localisée, le nouvel élément de menu Paste as Visual Basic peut y être ajouté. Cette opération est effectuée par création d'une commande, puis ajout de la commande au menu :
Dim command As Command = commands.AddNamedCommand2( _
_addInInstance, "PasteAsVBAddIn", "Paste as Visual Basic", _
"Convert the clipboard content from C# to Visual Basic and paste", _
True, 59, Nothing, _
CType(vsCommandStatus.vsCommandStatusSupported, Integer) + _
CType(vsCommandStatus.vsCommandStatusEnabled, Integer), _
vsCommandStyle.vsCommandStylePictAndText, _
vsCommandControlType.vsCommandControlTypeButton)
command.AddControl(editPopup.CommandBar, 12)
La commande est ajoutée au menu à la position 12, c'est-à-dire immédiatement après l'élément de menu Coller (voir figure 6).
Figure 6 Complément dans le menu Édition
Il est également important que le complément soit activé uniquement s'il est destiné à être utilisé. En effet, la fonction Paste as Visual Basic ne sera utile que si vous modifiez un fichier de code Visual Basic. L'activation et la désactivation du complément sont traitées par la méthode QueryStatus. Le code de la figure 7 entraîne l'affichage du complément uniquement lorsqu'un document actif se termine par l'extension .vb et lorsque le presse-papiers contient du texte.
Control Whether Add-In is Enabled
Public Sub QueryStatus( _
ByVal commandName As String, _
ByVal neededText As vsCommandStatusTextWanted, _
ByRef status As vsCommandStatus, _
ByRef commandText As Object) Implements IDTCommandTarget.QueryStatus
If neededText = _
vsCommandStatusTextWanted.vsCommandStatusTextWantedNone Then
If commandName = "PasteAsVBAddIn.Connect.PasteAsVBAddIn" Then
If _applicationObject.ActiveDocument IsNot Nothing _
AndAlso _
LCase(_applicationObject.ActiveDocument.FullName) _
.EndsWith(".vb") _
AndAlso My.Computer.Clipboard.GetText <> String.Empty Then
status = CType(vsCommandStatus.vsCommandStatusEnabled + _
vsCommandStatus.vsCommandStatusSupported, _
vsCommandStatus)
Else
status = CType(vsCommandStatus.vsCommandStatusSupported, _
vsCommandStatus)
End If
Else
status = vsCommandStatus.vsCommandStatusUnsupported
End If
End If
End Sub
À ce stade du projet, le complément est correctement connecté à Visual Studio et est prêt à être utilisé pour convertir le code. La seule tâche qui reste consiste à connecter la méthode Exec du complément au code qui effectuera la conversion et à coller le résultat dans l'éditeur.
Afin d'offrir une expérience complète à l'utilisateur, j'ai créé un formulaire qui permet à l'utilisateur de sélectionner parmi différentes options de conversion et de prévisualiser les résultats de la conversion. La figure 8 illustre le formulaire de conversion qui s'affiche lorsque l'utilisateur sélectionne la commande de menu Paste as Visual Basic. 
Figure 8 Interface utilisateur de conversion
La zone source C# affiche le contenu actuel du presse-papiers. Une zone de liste permet à l'utilisateur de choisir le convertisseur à utiliser. Lorsque vous cliquez sur le bouton Aperçu, la sortie de la conversion s'affiche en bas du formulaire afin de garantir que la conversion est acceptable, avant son collage dans le fichier de code. Le fait de cliquer sur Convertir lance la conversion et colle le résultat directement dans le fichier de code ouvert. Si la case Formater le code après la conversion est cochée, le code est reformaté afin de garantir l'indentation appropriée, après le collage du code converti.
Le code du formulaire est relativement simple et utilise les classes de conversion illustrées au début de cet article :
Private converters() As IConvertCode = { _
New PasteAsVB.CAConvert(), _
New PasteAsVB.WSConvert() _
}
Private Sub ConverterForm_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
CsSourceTextBox.Text = My.Computer.Clipboard.GetText
ConverterListBox.ValueMember = "ConverterName"
ConverterListBox.DisplayMember = "ConverterName"
ConverterListBox.DataSource = converters
End Sub
Lorsque le formulaire est chargé, un tableau de convertisseurs est instancié. Ces convertisseurs implémentent tous l'interface IConvertCode. Dans FormLoad, la zone de liste est liée à ce tableau et la propriété ConvertName est définie pour être affichée. Le nom de chaque convertisseur apparaît ainsi dans la zone de liste. Si vous souhaitiez ajouter d'autres convertisseurs, vous n'auriez qu'à créer des classes supplémentaires qui implémentent IConvertCode, puis à les ajouter au tableau des convertisseurs. Cela pourrait également être modifié afin d'extraire la liste des convertisseurs à utiliser à partir d'un fichier de configuration.
Lorsque vous cliquez sur Aperçu, le convertisseur sélectionné est utilisé pour effectuer la conversion et afficher les résultats dans la zone de texte d'aperçu. Lorsque vous cliquez sur Convertir, le code converti est affecté à une propriété du formulaire, et ce dernier est fermé. Le code de la fonctionnalité d'aperçu et de conversion est illustré dans la figure 9.
Preview and Convert Functionality
Private Sub Preview_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Preview.Click
Dim oldCursor As Cursor = Cursor
Cursor = Windows.Forms.Cursors.WaitCursor
Dim convertedCode As String = GetConvertedCode(CsSourceTextBox.Text)
VbResultsTextBox.Text = convertedCode
Cursor = oldCursor
End Sub
Private Sub ConvertButton_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles ConvertButton.Click
Dim oldCursor As Cursor = Cursor
Cursor = Windows.Forms.Cursors.WaitCursor
VBCode = GetConvertedCode(CsSourceTextBox.Text)
Cursor = oldCursor
Me.DialogResult = Windows.Forms.DialogResult.OK
End Sub
Private Function GetConvertedCode(ByVal csCode As String) As String
Dim converter As IConvertCode = ConverterListBox.SelectedItem
Dim convertedCode As String = converter.Convert(csCode)
Return convertedCode
End Function
Le formulaire de conversion est désormais complet et doit simplement être appelé à partir de la méthode Exec du complément, comme illustré figure 10. Lorsque le complément est appelé, le formulaire de conversion s'affiche. Si vous cliquez sur le bouton Convertir, la conversion est effectuée et le résultat est stocké dans la propriété VBCode du formulaire. Le formulaire renvoie alors le résultat DialogResult.OK. Le complément vérifie le résultat, puis insère le code converti dans l'éditeur de code. Si la case de format est cochée, le complément exécute également la commande Edit.FormatDocument afin de reformater le fichier de code actuel.
Performing a Conversion
Public Sub Exec(ByVal commandName As String, _
ByVal executeOption As vsCommandExecOption, _
ByRef varIn As Object, ByRef varOut As Object, _
ByRef handled As Boolean) Implements IDTCommandTarget.Exec
handled = False
If executeOption=vsCommandExecOption.vsCommandExecOptionDoDefault Then
If commandName = "PasteAsVBAddIn.Connect.PasteAsVBAddIn" Then
Dim f As New ConverterForm()
If f.ShowDialog() = System.Windows.Forms.DialogResult.OK Then
_applicationObject.ActiveDocument _
.Selection.Insert(f.VBCode)
If f.Reformat Then
_applicationObject.ExecuteCommand( _
"Edit.FormatDocument")
End If
End If
handled = True
Exit Sub
End If
End If
End Sub
Visual Studio 2005 simplifie la création de compléments. Tout d'abord, il génère du code qui intègre votre complément dans le menu de Visual Studio. Ensuite, lorsque vous appuyez sur F5, une instance de test de Visual Studio contenant votre complément est lancée. Cela facilite le débogage du complément.
Le complément illustré ici exécute une tâche très utile ; il vous permet de coller du code C# dans votre projet en tant que code Visual Basic. Le complément inclut la possibilité d'utiliser deux convertisseurs Web existants, mais il est conçu de façon à permettre l'ajout facile de convertisseurs supplémentaires.
Si vous souhaitez simplement installer ce complément et l'utiliser, le téléchargement de code qui accompagne cet article (sur le site Web de MSDN Magazine) inclut un projet d'installation qui vous permet d'installer le complément Paste as Visual Basic dans n'importe quel environnement de développement Visual Studio 2005. J'espère que vous constatez que la création de vos propres compléments n'est pas nécessairement une tâche fastidieuse. Si vous vous dites « J'aimerais un complément qui… », vous pouvez créer ce complément vous-même, beaucoup plus facilement que vous ne l'imaginez.