Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 11 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
11
Dung lượng
239,94 KB
Nội dung
360 Microsoft Visual Studio 2010: A Beginner’s Guide Writing Macros When the productivity features that ship with VS and custom snippets don’t give you enough power, the next step is to consider creating a macro, which is a repeatable set of actions that you can record and re-run multiple times. An example of when a macro is useful is whenever you find yourself continuously repeating the same set of actions in VS. This section will show you how to create and run a macro that uses VS features to create a customized block of code for validating strings. Recording a Macro When creating business objects, it’s common to validate input parameters to ensure they are valid. One such validation is enforcing that calling code pass a required parameter. The example in this section shows you how to write a macro for validating that a string- type parameter is not null, empty, or white space (such as a space or tab). To get started, create a new Console project and add a Class file with the following method to the project, which simulates adding a new customer: C#: using System; class Customer { public int AddNewCustomer(string firstName, string lastName) { int newCustID = 0; // Logic to add customer return newCustID; } } VB: Public Class Customer Function AddNewCustomer( ByVal firstName As String, ByVal lastName As String) As Integer Dim newCustID As Integer = 0 ' Logic to add customer Chapter 12: Customizing the Development Environment 361 Return newCustID End Function End Class The point of interest in the AddNewCustomer method is the firstName and lastName parameters. Whenever working with data, you’ll usually want to ensure that input data is legal. When user input is being processed, it’s common to get bad information, even if you have good input validation in your user interface code. For example, the following code calls the preceding AddNewCustomer method, passing in bad data as arguments: C#: class Program { static void Main() { string firstName = "Joe"; string lastName = null; Customer cust = new Customer(); cust.AddNewCustomer(firstName, lastName); } } VB: Module Module1 Sub Main() Dim firstName As String = "Joe" Dim lastName As String = Nothing Dim cust As New Customer cust.AddNewCustomer(firstName, lastName) End Sub End Module In the preceding example, firstName is okay because it has a good name in it. However, notice that lastName is set to null (Nothing in VB). This would cause a NullReferenceException if AddNewCustomer tried to call a string operation on the parameter, the code that AddNewCustomer calls could potentially throw a NullReferenceException, or (assuming that null is considered invalid in this case) you 362 Microsoft Visual Studio 2010: A Beginner’s Guide could end up saving bad data. Since AddNewCustomer doesn’t have an implementation, this is all speculation, but this outlines a few of the many problems that can occur if you allow your business objects to accept data that is bad for your program. The macro demonstrated in this section will show how to check a string parameter for null, empty, or white space and throw an ArgumentNullException. This will prevent callers from passing bad data and give them a meaningful message. To create a macro, you will need to locate the position in the code where the macro starts (if applicable), start recording, perform VS actions, and stop recording. It’s somewhat like using a video recorder where you have to find a TV show, start the recording, allow the show to play, and then stop recording. Perform the following steps to create the parameter validation macro: 1. Click the firstName parameter of the AddNewCustomer method so that the cursor is inside of the firstName parameter identifier. This is important because we need the parameter name in the code. 2. Start the macro recorder by selecting Tools | Macros | Record TemporaryMacro or press CTRL-SHIFT-R. 3. For C#, press CTRL-LEFT ARROW, CTRL-SHIFT-RIGHT ARROW, and CTRL-C. For VB, press CTRL-LEFT ARROW, CTRL-SHIFT-RIGHT ARROW, SHIFT-LEFT ARROW, and CTRL-C. This copies the parameter name. 4. For C#, press CTRL-F to bring up the Find And Replace window, type { into Find What, click Find Next, Close the Find And Replace window, press END, and press ENTER. For VB, press END and press ENTER. This positions the cursor to begin entering code. 5. Type if and press TAB twice (the if snippet), type string.IsNullOrWhiteSpace( into the condition, press CTRL-V to paste the parameter name as the argument, and type ). For C#, press ENTER. For VB, press DOWN ARROW. The cursor moves to the body of the if statement (as you would expect with the if snippet). This sets up the validation check for the parameter, seeing if it is null (Nothing in VB), an empty string, or some white space character such as space or tab. 6. Type throw new ArgumentNullException(", press CTRL-V to paste the parameter name, type ", ", press CTRL-V to paste the parameter name, type a space, and type value is not valid."). For C#, add a semicolon, ;, to the end of the line. This is the action to perform when the value is not valid, throwing an exception to let the caller know that the value is not good. 7. Press DOWN ARROW and press ENTER. This positions the cursor after the code, which might be convenient if you want to continue typing from this point. 8. Select Tools | Macros | Stop Recording TemporaryMacro or press CTRL-SHIFT-R to stop recording. Chapter 12: Customizing the Development Environment 363 You’ve now recorded a macro. To check the preceding steps against what you’ve produced, here’s a revised AddNewCustomer method, showing what the results should look like: C#: using System; class Customer { public int AddNewCustomer(string firstName, string lastName) { if (string.IsNullOrWhiteSpace(firstName)) { throw new ArgumentNullException( "firstName", "firstName value is not valid."); } int newCustID = 0; // Logic to add customer return newCustID; } } VB: Public Class Customer Function AddNewCustomer( ByVal firstName As String, ByVal lastName As String) As Integer If String.IsNullOrWhiteSpace(firstName) Then Throw New ArgumentNullException( "firstName", "firstName value is not valid.") End If Dim newCustID As Integer = 0 ' Logic to add customer Return newCustID End Function End Class 364 Microsoft Visual Studio 2010: A Beginner’s Guide In the preceding code, I’ve moved the ArgumentNullException arguments to separate lines to fit the book’s line length, but this is what you should see. Next, you can test the macro by running it. Click the lastName parameter and select Tools | Macros | Run TemporaryMacro or press CTRL-SHIFT-P. That will produce the following code: public int AddNewCustomer(string firstName, string lastName) { if (string.IsNullOrWhiteSpace(lastName)) { throw new ArgumentException("lastName", "lastName value is not valid."); } if (string.IsNullOrWhiteSpace(firstName)) { throw new ArgumentException("firstName", "firstName value is not valid."); } int newCustID = 0; // Logic to add customer return newCustID; } Now, you can run this macro on any of the string parameters of methods in your class and quickly add validation support. The only problem at the present time is that the macro is overwritten as soon as you begin recording a new macro and the macro is gone if you close VS. The next section addresses this problem by showing you how to save the macro. Saving a Macro You can save macros to be reused in later sessions. To save the macro, select Tools | Macros | Save TemporaryMacro. VS will save TemporaryMacro and open the Macro Explorer window, shown in Figure 12-8. VS uses TemporaryMacro as the name of whatever macro it will record. Therefore, you must rename the macro if you want to keep it because the next recording will overwrite this macro. Rename the file macro to ValidateStringParameter by right- clicking TemporaryMacro in Macro Explorer, showing the context menu, and selecting Rename. Chapter 12: Customizing the Development Environment 365 In the Macro Explorer, you can add new Macro Projects, which are containers for holding macro modules, by right-clicking Macros and selecting New Macro Project. If someone shares their Macro Project with you, right-click Macros and select Load Macro Project to find the project in the file system and load it. Macro modules hold macros, and you can right-click any macro project; such as MyMacros or Samples in Figure 12-8, and select New Module to add new macro modules. You can find all of these commands on the Tools | Macros menu too. To run an existing macro, double-click the macro in Macro Explorer. To change a macro, you can either re-record or edit an existing macro. The next section explains how to edit a macro. Editing Macros Macros are editable, allowing you to modify previously recorded macros or create a brand new macro. To edit a macro, right-click the macro in Macro Explorer and select Edit. You’ll see the Macro editor, shown in Figure 12-9, which contains the code for the ValidateStringParameter macro created in the preceding section. In Figure 12-9, you can see that the editor opens the macro in a code editing window. The language is VB, so if the language you normally program with is C#, you might want to review the VB portions of Chapters 2 through 4 as a refresher. The features of Macro editor are very similar to the normal VS IDE, except that now you must work with Macro Projects and Modules. Listing 12-3 shows the macro code from Figure 12-9. In Listing 12-3, both the C# and VB macros are written in VB. However, the C# code is for a macro that works on C# code and the VB code is for a macro that works on VB code. Figure 12-8 The Macro Explorer window 366 Microsoft Visual Studio 2010: A Beginner’s Guide Listing 12-3 Code for the ValidateStringParameter macro C#: Option Strict Off Option Explicit Off Imports System Imports EnvDTE Imports EnvDTE80 Imports EnvDTE90 Imports EnvDTE90a Imports EnvDTE100 Imports System.Diagnostics Public Module RecordingModule Sub ValidateStringParameter() DTE.ActiveDocument.Selection.WordLeft() DTE.ActiveDocument.Selection.WordRight(True) DTE.ActiveDocument.Selection.Copy() DTE.ExecuteCommand("Edit.Find") Figure 12-9 The Macro editor Chapter 12: Customizing the Development Environment 367 DTE.Windows.Item("Customer.cs").Activate() DTE.Windows.Item("{CF2DDC32-8CAD-11D2-9302-005345000000}") .Activate() 'Find and Replace DTE.Windows.Item("Customer.cs").Activate() DTE.Find.FindWhat = "{" DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument DTE.Find.MatchCase = False DTE.Find.MatchWholeWord = False DTE.Find.Backwards = False DTE.Find.MatchInHiddenText = False DTE.Find.PatternSyntax = vsFindPatternSyntax .vsFindPatternSyntaxLiteral DTE.Find.Action = vsFindAction.vsFindActionFind If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then Throw New System.Exception("vsFindResultNotFound") End If DTE.Windows.Item( "{CF2DDC32-8CAD-11D2-9302-005345000000}").Close() DTE.Windows.Item("Customer.cs").Activate() DTE.ActiveDocument.Selection.EndOfLine() DTE.ActiveDocument.Selection.NewLine() DTE.ActiveDocument.Selection.Text = "if" DTE.ExecuteCommand("Edit.InsertTab") DTE.ExecuteCommand("Edit.InsertTab") DTE.ActiveDocument.Selection.Text = "string.IsNullOrWhiteSpace(" DTE.ActiveDocument.Selection.Paste() DTE.ActiveDocument.Selection.Text = ")" DTE.ExecuteCommand("Edit.BreakLine") DTE.ActiveDocument.Selection.Text = "throw new ArgumentNullException(""" DTE.ActiveDocument.Selection.Paste() DTE.ActiveDocument.Selection.Text = """, """ DTE.ActiveDocument.Selection.Paste() DTE.ActiveDocument.Selection.Text = " value is not valid."");" DTE.ActiveDocument.Selection.LineDown() DTE.ActiveDocument.Selection.NewLine() End Sub End Module VB: Option Strict Off Option Explicit Off Imports System Imports EnvDTE 368 Microsoft Visual Studio 2010: A Beginner’s Guide Imports EnvDTE80 Imports EnvDTE90 Imports EnvDTE90a Imports EnvDTE100 Imports System.Diagnostics Public Module RecordingModule Sub ValidateStringParameter() DTE.ActiveDocument.Selection.WordLeft() DTE.ActiveDocument.Selection.WordRight(True) DTE.ActiveDocument.Selection.CharLeft(True) DTE.ActiveDocument.Selection.Copy() DTE.ActiveDocument.Selection.EndOfLine() DTE.ActiveDocument.Selection.NewLine() DTE.ActiveDocument.Selection.Text = "if" DTE.ExecuteCommand("Edit.InsertTab") DTE.ExecuteCommand("Edit.InsertTab") DTE.ActiveDocument.Selection.Text = "string.IsNullOrEmpty(" DTE.ActiveDocument.Selection.Paste() DTE.ActiveDocument.Selection.Text = ")" DTE.ActiveDocument.Selection.LineDown() DTE.ActiveDocument.Selection.Text = "throw new ArgumentNullException(""" DTE.ActiveDocument.Selection.Paste() DTE.ActiveDocument.Selection.Text = """, """ DTE.ActiveDocument.Selection.Paste() DTE.ActiveDocument.Selection.Text = " value is not valid."")" DTE.ActiveDocument.Selection.LineDown() DTE.ActiveDocument.Selection.NewLine() End Sub End Module In Listing 12-3, all of the namespaces that begin with EnvDTE have code that allows you to manipulate the VS environment. The macro itself is a Sub within a Module. Each of the statements corresponds to the steps used to create the macro in the preceding section. For example, the Find And Replace window has several options, which this macro populates, regardless of whether they contribute toward the purpose of the macro. Opening a macro in the editor can be very useful if you want to make a quick change, without needing to re-record the entire macro. For example, what if you missed a keystroke or misspelled something? You can just edit the code, save the file, close the Macro editor, and then re-run the macro. In fact, there is a problem with the macro for C#; it will only Chapter 12: Customizing the Development Environment 369 work on the file you ran it in. This problem doesn’t occur in the macro for VB. I’ll show you how to fix this problem, but let’s open the macro editor first. You can open the Macro editor through VS by selecting Tools | Macros | Macros IDE, start a new project, add a module to the project, and add a Sub to the Module as a new macro. Then code the macro by typing DTE. and using Intellisense to find various parts of the IDE. The cryptic parameter to Windows.Item, {CF2DDC32-8CAD-11D2-9302- 005345000000}, for the Find And Replace window is called a Globally Unique Identifier (GUID). A GUID is often used as a special identifier for software components and is the method used in VS to uniquely identify tools. So, DTE.Windows.Item("{CF2DDC32- 8CAD-11D2-9302-005345000000}").Activate() is a way to reference and open the Find And Replace window. There is a problem with the macro for C# in Listing 12-3, because it will only work in the Customer.cs file in VS. The VB code below is provided for your convenience, but this problem only occurs with the macro written for C# code; the VB macro works fine on the VB code below. If you created a new class named Product in a file named Product.cs and added an AddNewProduct method like the following, the macro will try to open and write into the Customer.cs file, which is not the result you want: C#: using System; namespace ConsoleApplication1 { class Product { public int AddNewProduct(string productName) { int newProdID = 0; // Logic to add product return newProdID; } } } VB (doesn’t have problem that occurs in C# code): Public Class Product Function AddNewProduct(ByVal productName As String) As Integer Dim newProdID As Integer = 0 [...].. .370 Microsoft Visual Studio 2010: A Beginner’s Guide ' Logic to add product Return newProdID End Function End Class To fix the problem with the macro (for the C# code) opening the Customer.cs file, notice that the macro... write is to start the macro recorder in VS (CTRL-SHIFT-R), use the VS feature you want to code, stop recording (CTRL-SHIFT-R), and save the macro Then inspect the code in the Macro editor and copy the parts you need This technique is especially valuable to figure out how to open windows, such as the Find And Replace window discussed in the preceding paragraph For even more help, there are several example . AddNewProduct(ByVal productName As String) As Integer Dim newProdID As Integer = 0 370 Microsoft Visual Studio 2010: A Beginner’s Guide ' Logic to add product Return newProdID End. NullReferenceException, or (assuming that null is considered invalid in this case) you 362 Microsoft Visual Studio 2010: A Beginner’s Guide could end up saving bad data. Since AddNewCustomer doesn’t have. Logic to add customer Return newCustID End Function End Class 364 Microsoft Visual Studio 2010: A Beginner’s Guide In the preceding code, I’ve moved the ArgumentNullException arguments