If you miss the free version of Reflector now that Red Gate's taken it over, and if you don't appreciate the functionality that Red Gate has added to it, then ILSpy is for you.
ILSpy will decompile any .NET DLL back to either Visual Basic or C# (your choice), and provide a viewer that lets you browse the results. If you want to find out how the code behind the framework DLLs works (or if you've just lost your source code), ILSpy will let you see it. There are even a few plugins for ILSpy that enhance the basic package (and they're also free).
ILSpy doesn't provide the tight integration with Visual Studio (and Visual Studio debugging) that Red Gate's Reflector does, but -- did I mention this? -- it won't cost you a dime.
Posted by Peter Vogel on 01/08/2014 at 1:17 PM0 comments
Over a series of articles about commenting, I discussed why the key issue is to write ROC (Really Obvious Code). If you do, then the only comments you need to provide for your methods should be what parameters the method expects, what your method will do with those parameters, what the method will return, and any side effects of executing the method (e.g., database updates). If you bought into that plan (and some readers did not), then the best place to put that documentation is where Visual Studio will make the best use of it: in IntelliSense, by using XML comments.
To create the structure for your XML comments, click your mouse before your method declaration; then, in Visual Basic, type three apostrophes ('''); in C#, type three forward slashes (///). In either case, Visual Studio will add a framework to hold the comments for your method, for each of the parameters the method accepts, and for your method's return value (if any). All you have to do is type in your content.
Not only will the programmers who work on your code find all the information they need when changing your code, the developers who use your methods will find that IntelliSense delivers your documentation to them when they use your methods.
Posted by Peter Vogel on 01/07/2014 at 9:23 AM0 comments
You're working with a variable, property, method or class and you need more information about it. If you hover your mouse over the item's name, IntelliSense displays the information for you. But when you need more information or, especially, if you want to make some changes to the item, clicking on the item's name and pressing F12 will take you to it.
When you're done making your changes, you probably want to go back to that original code. Pressing Control_- (<Ctrl> minus) will take you there (officially known as navigate backward or BrowsePrevious). If Control_- doesn't take you back to where you want to go immediately, it's only because it will stop at some other places where you rested between when you pressed F12 and where you are now. Just keep pressing Control_- and you'll eventually get back to where you want to be.
Posted by Peter Vogel on 12/09/2013 at 7:23 AM0 comments
Like everyone else, I like code-first Entity Framework (EF) development because it makes it so easy to integrate custom code with my EF entity code. But even in a pure code-first development, I suspect that most developers don't generate their databases from their entities because, most of the time, the database already exists (and, besides, the DBA won't let developers anywhere near the database's schema). That means you have to write all the repetitious property declaration in the entity objects to mimic the tables you'll be working with. Wouldn't it be nice if you had a tool to do it for you?
There are POCO generators out there, but you already have a tool: the ADO.NET Entity Framework database-first designer. The original versions of the designer generated a lot of peculiar code. More recent versions generate code that looks very much like the code you should write when doing code-first development. Why not take advantage of that?
Start by adding a new project to your solution. Then, to get the cleanest entity code possible, use NuGet to add Entity Framework 6.0 to the project. From Project | Add New Item, add the ADO.NET Entity Data Model and use the Wizard to work through adding the tables needed for your project. When you're done, close the designer to ensure that all the code for your entities is generated.
Now drill down beneath your edmx file in Solution Explorer to find your code files. You can skip the file called <NameOfYourModel>.cs/vb and <NameOfYourModel>.Designer.cs/vb (though, since the files have nothing in them, there's probably no harm in including them). Once you've found the files, still in Solution Explorer, drag them to your "real" data access project. Whenever you need to add another table you can return to the project with the designer and use it to generate your code for you.
This isn't a perfect solution: The edmx generator in EF 6.0 doesn't add any data annotations to the entities it generates, for instance (recently, I needed to add the Key attribute to the primary key properties on a project). This solution is also easier to implement in Visual Basic than in C# because of the embedded namespaces in the C# files. Even in C#, though, a project-wide search-and-replace will fix that problem. But by using a tool from the EF team to generate your EF code, you're guaranteed to be getting the best (and most up-to-date) EF code possible.
Posted by Peter Vogel on 12/04/2013 at 8:22 AM0 comments
I've been working on a Windows Forms application for one of my clients and, in the application, I use the CheckedBoxList and the DataGridView. Both of them have really useful collections: the CheckedBoxList has a CheckedItems collection that holds all the items that the user has checked, and the DataGridView has a SelectedRows collection that holds all the rows the user's selected, for instance. The CheckedItems collection can hold any object I want while the SelectedRows collection holds DataGridViewRow objects.
The problem is that neither of these collections will work with LINQ.
Fortunately, rather than use For…Each loops, I can use the OfType method to convert these collections into something that will work with LINQ. All I have to do is pass the OfType method the object type held in the collection. For instance, to use LINQ with the DataGridView's SelectedRows collection, I use this code; it converts the DataItem property for each row into the object associated with each row:
Dim coll = From rw In Me.gvInvoices.SelectedRows.OfType(Of DataGridViewRow)()
Select CType(rw.DataBoundItem, ClaimCededDetailClass
The following code processes the ClaimHeaderClass objects I hold in my CheckedBoxList, and hands back those object that have their AuthorizationLevel property set to "High":
Dim cc = cblClaims.CheckedItems.OfType(Of ClaimHeaderClass).
Where(Function(chc) chc.AuthorizationLevel = "High")
But wait, there's more! I have a Panel on the form with a set of RadioButtons in it. The Panel, of course, has a Controls collection that holds all of those RadioButtons. This code converts that collection into a LINQ-compatible collection of RadioButtons, then lets me find the name of the RadioButton the user selected:
strRadio = (From rb In Me.plStatusRadio.Controls.OfType(Of RadioButton)()
Posted by Peter Vogel on 11/15/2013 at 7:52 PM0 comments
About a year ago, Patrick Steele did a great job of describing AutoMapper: an absolutely necessary tool if you're using Data Transfer Objects to move data between parts of your application. AutoMapper will automatically move data from your business entities into the corresponding properties on your DTO, saving you many, many lines of repetitious assignment statements. It also means that if you add a new property to your DTO, AutoMapper will automatically pick up the corresponding property from the entity; no further changes to your code required.
You do need to be careful, however, when moving your data from a DTO and into an Entity Framework (EF) entity object. By default, AutoMapper creates a new instance of the object that the data is being moved into. If you write code like the following, for instance, the Customer object in custExisting that's returned from AutoMapper is a different object from the Customer object retrieved from the DbContext (even though the custExisting variable points to both of those objects):
Mapper.CreateMap(Of CustomerDTO, Customer)()
custExisting = dbs.Customers.Single(Function(c) c.Id = custDTO.Id)
custExisting = Mapper.Map(Of CustomerDTO, Customer)(custDTO)
That's bad, because EF won't track the changes made to that new custExisting object: When you call SaveChanges, nothing will be saved back to the database. This is a common-enough problem that there's even some misinformation about it floating around. I've seen a couple of forums, for instance, where people with this problem have been told that AutoMapper can't be used to update entities.
You can update entities with AutoMapper. Here's how: pass both the DTO and the entity object to AutoMapper's Map method. That's what this code does:
custExisting = Mapper.Map(Of CustomerDTO, Customer)(custDTO, custExisting)
Rather than creating a new entity object to return from the Map method, AutoMapper now updates the entity object passed in the second parameter and returns it to my custExisting variable. As a result, EF will track the changes made to the entity object; and, when you call SaveChanges, your updates will be sent to the database.
Posted by Peter Vogel on 11/06/2013 at 7:53 AM0 comments
I'm sure that by now, mentioning these three tools is almost redundant, but even if you're working on a single computer on your own, Subversion lets you have as much (or as little) source control as you want. Subversion is ridiculously easy to install and start running.
After installing Subversion on the computer that holds your repository, add TortoiseSVN to give you source control from Windows Explorer on whatever computer(s) you have files you care about. To connect the two, copy the URL for your Subversion installation (it's available from a context menu) and paste it into the dialog box that pops up when you start TortoiseSVN. To integrate with Visual Studio, shut down Visual Studio and install VisualSVN. When you start Visual Studio backup, go to your new VisualSVN menu to connect your project to your repository.
It's all free and takes only a few minutes to download, install, and start saving your work to a central repository that will manage your code and its versions.
That's just the simplest installation. If you don't like VisualSVN, there are several other tools for integrating with Visual Studio. Several of my friends speak highly of AnkhSVN, for instance, which is always free, while VisualSVN is only free under some scenarios.
I work on a single laptop with multiple virtual machines (typically one VM for each client/project). I have the Subversion server running on my host machine, and connect to it from each of my VMs, with a separate Subversion repository for each VM. When I switched over to Subversion I probably spent as much time adding the repository to my laptop's backup plans as I did installing the three packages.
Posted by Peter Vogel on 10/30/2013 at 10:00 AM0 comments
This isn't so much a tip as a clarification: I often find that people are confused about what happens when you press F5 vs. when you press Control_F5. Here's the best description I've found (and it's from the blog where I've found most of the Visual Studio tips that I talk about here).
However, the blog's claim that there isn't much difference between F5 and Control_F5 isn't quite true; there are a number of differences I keep stumbling upon. I suspect that, from a technical/internals point of view, the statement that there aren't many differences is true. But for a developer using Visual Studio, there are a number of "operational" differences.
For instance, if you want to test your user interface's error handling, use Control_F5. With plain old F5, Visual Studio stops on the line that throws the exception; with Control_F5, Visual Studio lets your Try…Catch blocks handle the exception.
Here's another one: If you run a Console application with plain old F5, the console window flashes on the screen and disappears, unless you add a Console.ReadLine to your code; with Control_F5, the console window is held on the screen until you hit the Return key.
I bet that's not all of the differences. What ones do you know about?
Posted by Peter Vogel on 10/22/2013 at 10:00 AM0 comments
I know that Windows Forms are considered old fashioned, but I've got clients with applications that still use them. As I noted in my previous tip, I recently had to support letting the user sort by any column in a grid. If I was going to do that, I felt I should let the user know what column and direction they'd just sorted the grid in. The DataGridView lets you do that through the column's SortGlyphDirection property: just set the property to one of SortOrder.Ascending (little arrow in the column header pointing up), SortOrder.Descending (little arrow pointing down), or SortOrder.None (no arrow in the header).
When the user clicks on a column the first time, I sort the column in ascending order; with a second click on the column, I reverse the order. If the user changes columns, I erase the glyph in the previous column. To keep track of the necessary information, I declare two variables outside of any method: The Headers collection keeps track of what direction each column is sorted in, and the OldColumn variable keeps track of the last column sorted:
Private Headers As New Dictionary(Of String, SortOrder)
Private OldColumn As DataGridViewColumn
I put the actual sort code in the DataGridView's ColumnHeaderMouseClick event, whose parameter includes the column position the user's clicked on (the ColumnIndex property). I use that parameter to get a reference to the column the user's selected:
Private Sub CustomersView_ColumnHeaderMouseClick(…
Dim col As DataGridViewColumn
col = Me.CustomersView.Columns(e.ColumnIndex)
In the event handler, I check to see if there's a setting for the current column in the Headers collection. If there isn't, I just sort in ascending order; if there is, I use that value to decide what order to sort the column in:
If Headers.ContainsKey(e.ColumnIndex) = False OrElse
Headers(e.ColumnIndex) = SortOrder.Descending Then
Headers(e.ColumnIndex) = SortOrder.Ascending
Customers = Customers.OrderBy(
Function(c) prop.GetValue(c, Nothing)).ToList
Headers(e.ColumnIndex) = SortOrderDescending
filteredInvoices = filteredInvoices.OrderByDescending(
Function(c) prop.GetValue(c, Nothing)).ToList
After I finish sorting, I refresh my grid's DataSource with the new collection, clear the sorting glyph in the previous column, set the glyph in the column I'd just sorted, and keep track of which column I've just sorted for next time:
CustomersView.DataSource = Customers
If OldColumn IsNot Nothing Then
OldColumn.HeaderCell.SortGlyphDirection = Windows.Forms.SortOrder.None
col.HeaderCell.SortGlyphDirection = Headers(e.ColumnIndex)
OldColumn = col
Now, by glancing at the grid's column headers, the user knows which column was sorted last, and in what order.
Posted by Peter Vogel on 10/17/2013 at 11:59 AM0 comments
In the bad old days (before LINQ), I used to concatenate together SQL statements. That left me open to SQL injection attacks, of course, but it was so convenient: I could dynamically put together whatever SQL I needed at runtime. With LINQ, however, not so much (though I understand that there is a version of Dynamic LINQ out there). Even with ordinary LINQ, though, you can select which properties in an object you want to use at runtime; at least when you're sorting (and, probably, elsewhere but I haven't tried it yet).
Recently, I needed to support a grid for a client who wanted to be able to sort on any column. I was setting the grid's DataSource to a collection of objects. While this simplified getting the objects displayed, it also turned off the grid's automatic sorting capability. To get around that, I added some code to the grid's ColumnHeaderMouseClick event to sort the grid. What I didn't want to do was write a separate method to sort on each grid column (especially because this client kept changing his/hers/its mind about what columns should or shouldn't be in the grid).
Fortunately, each grid column held the name of the property that the column was responsible for displaying from the objects in the grid's DataSource. Given a property's name, I retrieved the PropertyInfo for that property and used its GetValue method in my LINQ code.
First, I retrieve a sample object from the collection of objects (Customers, in this case):
Dim cust As Customer
cust = Customers.First
Then I retrieve the PropertyInfo object for the property whose name is in the PropertyName string variable:
Dim prop As PropertyInfo
prop = cust.GetType.GetProperties.First(
Function(pr) pr.Name = propertyName)
Now I use the PropertyInfo object's GetValue method in my LINQ statement to sort my list:
Customers = Customers.OrderBy(
Function(c) prop.GetValue(c, Nothing)).ToList
I'm looking forward to finding out how many places I can use this technique.
Posted by Peter Vogel on 10/07/2013 at 10:00 AM0 comments
You should get this tool.
Posted by Peter Vogel on 09/30/2013 at 10:23 AM0 comments
This tip is mostly for Visual Studio 2010 users: stop using Ctrl_F. Ctrl_F brings up the Find dialog where you can type in your search text, press the <Enter> key to search, and (eventually) close the dialog because it's blocking your view. Instead, use Ctrl_i (for "incremental search"). After pressing Ctrl_i, just start typing and your cursor will skip to the first occurrence of whatever you've typed so far, no dialog required. Often you'll find your cursor sitting on what you were looking for before you've typed in everything you thought you'd need to find it.
After entering your search text, pressing Ctrl_i again will take you to the next matching entry, as will F3 if you'd prefer something more familiar (Ctrl_Shift_i will take you to the previous entry). When you do find what you want, just press <Esc> to end the search and go back to making changes. There is one difference between using Ctrl_i and F3 to go to the next matching entry: when you've visited all the matching entries on the page, F3 pops up a dialog box to tell you so; Ctrl_i just cycles through the entries again.
The one downside of the incremental search is that it only searches within a document. However, that means that I use my Find dialog just for "Entire Solution" searches. While the incremental search ignores the scope setting on the Find dialog, it does pick up the dialog's other settings (e.g. "Match Case").
Why is this tip "mostly for Visual Studio 2010 users"? Because, in Visual Studio 2012, this is also the way that the Find dialog works: it starts searching as soon as you start typing.
Posted by Peter Vogel on 09/25/2013 at 4:15 PM0 comments