Validating Enum Values#

You were a good developer and created an enum to represent the integer values that are being passed into your method.

It makes life easy for everyone.  Good job.

But now you realize that ANY integer can be passed into your function, even though your type only defines a handful of values.

Well, you need to validate the enum values that are coming into your method.

This can be done quickly with the following code snippet:

If Not [Enum].IsDefined(localId.GetType, localId) Then
    Throw New System.ComponentModel.InvalidEnumArgumentException("Invalid local value.")
End If

In this example localId is the variable name of type LocalType.

Categories:  |  | 
Thursday, July 24, 2008 12:55:29 PM (Central Standard Time, UTC-06:00) #    Comments [0]  | 

 

Using My.Settings on a referenced project#

I recently ran into some seemingly strange behavior as I was testing a couple windows services I had written.

In my case, I had a test harness program that was referencing the service (an exe) but this could also apply to references to dlls if you are using the projects application settings (My.Settings.Whatever in VB.Net).

After figuring it out, it all makes sense.

When you create an application setting by providing a value in the project's "Settings" tab, the value is written out into a special <applicationSettings> block in your config file.

But, in order to make those values accessible via a strongly typed/intellisense method, a class is created to wrap those values.  The class is in the Settings.vb file that is generated when you first add an application setting to your project.

But there is one more interesting thing to note:  If the settings class doesn't find the item it expects in the config file, it will return the last supplied value by default. 

So what this means is that if create an application setting for XYZ for the value "123" and then change the app.config file directly to change the "123" to "abc", then "abc" will be returned when you run the program.  However, if you were to then alter the config file to remove or rename the XYZ item, then your application would return "123" again when it ran.

Also, if you directly modify the config file, and then try to edit the projects applications settings, it will alert you to the fact that some values have changed, and ask if you want to use the updated values from the config file.  If you say yes, it will overwrite the Settings.vb file to use the new values that you had supplied in the config file.

So, I was referencing a project that used these settings, but when I would update the config file, those updated settings were not seen.  All I had to do was go into the project settings tab, allow it to refresh the Settings.vb file, and rebuild the project.

 

Categories:  |  |  | 
Wednesday, August 22, 2007 7:07:09 AM (Central Standard Time, UTC-06:00) #    Comments [0]  | 

 

Webservices Compression#
Categories:  |  |  |  | 
Wednesday, May 02, 2007 2:34:54 PM (Central Standard Time, UTC-06:00) #    Comments [0]  | 

 

TypeOf VB.NET vs C##

If you are Microsoft, why do you create a function "TypeOf" that has totally differnet applications in VB and C#?

Typeof in C# is like GetType in VB, where VB uses TypeOf to see if 2 types are the same or check for interface implementation.

Kinda dumb.

Categories:  |  |  | 
Friday, April 06, 2007 7:59:58 AM (Central Standard Time, UTC-06:00) #    Comments [3]  | 

 

VB Keyboard Shortcut Poster#

Shows all the vs.net ide shortcuts for vb.net.

Categories:  |  | 
Sunday, February 04, 2007 11:15:33 PM (Central Standard Time, UTC-06:00) #    Comments [0]  | 

 

Printing Vb.Net Forms with PrintForm Component#

Microsoft has released their first 3 Power Packs for Visual Basic 2005, which are "free Add-Ins, Controls, Components, and Tools for you to use with Visual Basic 2005 to make developing great applications even easier."

1 of the first 3 is the Microsoft PrintForm Component 1.0 , which gives you the ability to easily print a form.

I could have really used this on my last project, where I manually wrote the code to do just that.

Categories:  |  |  | 
Monday, October 09, 2006 1:58:15 PM (Central Standard Time, UTC-06:00) #    Comments [0]  | 

 

Convert a String to a Byte Array in VB.Net#

I had a snippet on my site for converting a byte array to a string, but I didn't have anything for going the other way.

This function should do the trick.

Public Shared Function StringByByteArray(ByVal s As String) As Byte()
    Return System.Text.Encoding.UTF8.GetBytes(s)
End Function


Categories:  |  | 
Wednesday, October 04, 2006 2:44:23 PM (Central Standard Time, UTC-06:00) #    Comments [0]  | 

 

VS.Net Macro to Narrow VB.Net Method Signatures and Function Calls#

Lately I have been doing some refactoring of code as I go through it.

Trying to name variables correctly, breaking up long methods, trying to adhere to some coding standards.

One way that I have been employing to clean up code is to convert very long method signatures, or calls to methods with many parameters from LONG single line entities to shorter multi-line blocks.

This is simple, but tedious.  So I wrote a VS.Net macro to do it for me.

Simply copy and paste the macro code (paste into wordpad first to get rid of the missing newline problem) at the bottom of this article into a macro.  Then all you have to do is highlight the entire row you want to "narrow", and run the macro.  You can always Cntl+z out of it if you want to undo the changes.

The results are good!  The following are examples of a long method signature, and a call to a method with a lot of arguments, and then the refactored results.

'*** Long method signature
Public Function ActivitySave(ByVal Activity As MyNamespace.Business.Equipment.Activity, ByVal StartTime As DateTime, ByVal EndTime As DateTime, ByVal StatusOverride As System.Nullable(Of MyNamespace.Business.Data.Criteria.Equipment.ActivityStatusEnum), ByVal Clerk As Integer) As Integer

'*** long method call
ActivityID = MainActivity.ActivitySave(Activity.ActivityID, Activity.Status, Activity.PurposeNotes, Activity.JobIndex, Activity.CategoryID, Activity.RequestedStartDate, Activity.RequestedEndDate, Activity.EquipmentID, Activity.PlanStartDate, Activity.PlanEndDate, Activity.ActualStartDate, Activity.ActualEndDate, Activity.DiscountScheduleID, Activity.DiscountOffset, Activity.CodeID, Activity.RentalRate, Activity.RowVersion, Clerk)

Here is the result of the refactoring:

'*** Refactored long method signature
Public Function ActivitySave(ByVal Activity As MyNamespace.Business.Equipment.Activity, _
ByVal StartTime As DateTime, _
ByVal EndTime As DateTime, _
ByVal StatusOverride As System.Nullable(Of MyNamespace.Business.Data.Criteria.Equipment.ActivityStatusEnum), _
ByVal Clerk As Integer) As Integer

'*** Refactored long call
ActivityID = MainActivity.ActivitySave(Activity.ActivityID, _
Activity.Status, _
Activity.PurposeNotes, _
Activity.JobIndex, _
Activity.CategoryID, _
Activity.RequestedStartDate, _
Activity.RequestedEndDate, _
Activity.EquipmentID, _
Activity.PlanStartDate, _
Activity.PlanEndDate, _
Activity.ActualStartDate, _
Activity.ActualEndDate, _
Activity.DiscountScheduleID, _
Activity.DiscountOffset, _
Activity.CodeID, _
Activity.RentalRate, _
Activity.RowVersion, _
Clerk)

 

Here is the macro.

 Public Sub NarrowMethodsAndCalls()
'Create an Undo context object so all the changes can be
'undone by CTRL+Z
Dim oUnDo As UndoContext = DTE.UndoContext

'Supress the User Interface. This will make it run faster
'and make all the changes appear once
DTE.SuppressUI = True
Try


Dim oTextSelection As TextSelection = DTE.ActiveWindow.Selection
Dim sOrigText As String = oTextSelection.Text

Dim RegExp As New System.Text.RegularExpressions.Regex("([ .=_a-zA-Z0-9]*)\(")
Dim Match As System.Text.RegularExpressions.Match = RegExp.Match(sOrigText)
If Match.Success Then
Dim sMethod As String = Match.ToString
Dim sParametersAndReturn() As String = sOrigText.Replace(sMethod, "").Split(",")
Dim sFirstLineWhiteSpace As String
Dim sb As New System.Text.StringBuilder
sb.Append(" ", Trim(sMethod).Length)
sFirstLineWhiteSpace = sb.ToString

'*** redo the first line
oTextSelection.Text = sMethod & sParametersAndReturn(0) & ", _"
oTextSelection.NewLine()
oTextSelection.Text = sFirstLineWhiteSpace

For i As Integer = 1 To sParametersAndReturn.Length - 2
oTextSelection.Text = Trim(sParametersAndReturn(i)) & ", _"
oTextSelection.NewLine()
Next
oTextSelection.Text = Trim(sParametersAndReturn(sParametersAndReturn.Length - 1))
oTextSelection.NewLine()



Else
MsgBox("failed to find function regexp match")
End If
Catch ex As Exception
MsgBox("Error: " & ex.ToString)
Finally

'If an error occured, then need to make sure that the undo context is cleaned up.
'Otherwise, the editor can be left in a perpetual undo context
If oUnDo.IsOpen Then
oUnDo.Close()
End If

DTE.SuppressUI = False
End Try

End Sub
Categories:  |  |  | 
Wednesday, September 27, 2006 9:52:05 AM (Central Standard Time, UTC-06:00) #    Comments [0]  | 

 

Checking an objects type or implemented interfaces#

A common thing people might want to do is check if a object is a certain type, or inherits a type, or implements a type.

This can be done in VB.Net with the following code:

TypeOf someObject Is ClassName

This works for inheritance heirarchy as well as checking for interface implementation.

Here is a sample app showing it in practice.

imports Microsoft.VisualBasic
imports System
Imports System.Collections.Generic

public module MyModule
    sub Main
dim o as new subclass
        WL(typeof o is subclass)
        WL(typeof o is baseclass)
        WL(typeof o is IWhatever)
        RL()
    end sub

    #region "Helper methods"

    sub WL(text as object)
        Console.WriteLine(text)
    end sub

    sub WL(text as object, paramarray args as object())
        Console.WriteLine(text.ToString(), args)
    end sub
        
    sub RL()
        Console.ReadLine()
    end sub
    
    sub Break()
        System.Diagnostics.Debugger.Break()
    end sub

#end region

end module


public interface IWhatever
end interface
public class BaseClass

end class

public class SubClass
inherits BaseClass
implements IWhatever

end class
Categories:  |  | 
Wednesday, September 06, 2006 3:35:02 PM (Central Standard Time, UTC-06:00) #    Comments [0]  | 

 

VS.Net Macro for Generating Simple and CSLA Property Accessors#

Here are a few macros I wrote to generate property accessors from your class level variables.

These Macros are absolutely not an example of great coding.  They are really pretty crappy, but they do the job, so as I kept tweaking them I never went back to clean up the code or look into more elegant ways to accomplish this stuff.

Some notes about these macros:

1) dasBlog's code display tools somehow screws up the LFs, so if you cut and paste this code you might want to first paste it into Word, or WordPad.

2) These macros need some space between your last bit of code and the end of your class.  In other words, the line directly above "End Class" can't have code in it.  Fixing this bug wouldn't be a big deal but I haven't done it yet.

3) These macros will allow formatting of your variables/accessors in any of the following ways:

private csClassLevelString as String '*** property name "ClassLevelString"
private mModuleLevelInt as Integer '*** property name "ModuleLevelInt"
private _SomeObject as Object '*** property name "SomeObject"
private camelCaseBoolean as Boolean '*** WON'T work: property will be named "CaseBoolean"

4) To use these macros, simply declare your class level (instance) variables.  Then with your mouse, highlight the ones you want to create property accessors for.  You need to highlight the entire definition from "private" to data type, and of course you can highlight a bunch at 1 time.  i.e. I could highlight the entire code block above and it would produce 4 property accessors.

5) Again... this code... well it kinda sucks.  So if you are looking for a lesson on producing good code, avert your eyes, but the output is good.

 

Imports System
Imports EnvDTE
Imports EnvDTE80
Imports System.Diagnostics

Public Module Module1

    Public Sub AddClassProperties()
        Call AddClassProperties(False)
    End Sub
    Public Sub AddCslaProperties()
        Call AddClassProperties(True)
    End Sub

    ' highlight the private properties
    Private Sub AddClassProperties(ByVal useCsla As Boolean)

        Dim oTextSelection As TextSelection = DTE.ActiveWindow.Selection
        Dim iLinesSelected = oTextSelection.TextRanges.Count
        Dim colPropertyList As New Collection()
        Dim iIndex As Integer
        Dim oStart As EditPoint = oTextSelection.TopPoint.CreateEditPoint()
        Dim oEnd As TextPoint = oTextSelection.BottomPoint

        'Create an Undo context object so all the changes can be
        'undone by CTRL+Z
        Dim oUnDo As UndoContext = DTE.UndoContext

        'Supress the User Interface. This will make it run faster
        'and make all the changes appear once
        DTE.SuppressUI = True

        Try

            oUnDo.Open("Comment Line")

            Dim sProperty As String
            Dim sLineOfText As String

            Do While (oStart.LessThan(oEnd))

                sLineOfText = oStart.GetText(oStart.LineLength).Trim
                '*** do some kind of simple check to make sure that this line
                '*** isn't blank and isn't some other kind of code or comment
                If (sLineOfText.IndexOf(" As ") >= 0 And ( _
                    (sLineOfText.IndexOf("Public ") >= 0) Or _
                    (sLineOfText.IndexOf("Private ") >= 0) Or _
                    (sLineOfText.IndexOf("Dim ") >= 0) Or _
                    (sLineOfText.IndexOf("Protected ") >= 0) Or _
                    (sLineOfText.IndexOf("Friend ") >= 0) Or _
                    (sLineOfText.IndexOf("ReDim ") >= 0) Or _
                    (sLineOfText.IndexOf("Shared ") >= 0) Or _
                    (sLineOfText.IndexOf("Static ") >= 0) _
                    )) Then

                    sProperty = oStart.GetText(oStart.LineLength).Trim.Replace(" New ", " ").Replace("()", "")

                    colPropertyList.Add(sProperty)
                End If

                oStart.LineDown()
                oStart.StartOfLine()

            Loop

            If colPropertyList.Count > 0 Then

                For Each sProperty In colPropertyList
                    Call InsertProperty(sProperty, useCsla)
                Next

            Else
                MsgBox("You must select the class properties")
            End If

        Catch ex As System.Exception

            Debug.WriteLine(ex)
            If MsgBoxResult.Yes = MsgBox("Error: " & ex.ToString & vbCrLf & "Undo Changes?", MsgBoxStyle.YesNo) Then
                oUnDo.SetAborted()
            End If

            Return
        Finally

            'If an error occured, then need to make sure that the undo context is cleaned up.
            'Otherwise, the editor can be left in a perpetual undo context
            If oUnDo.IsOpen Then
                oUnDo.Close()
            End If

            DTE.SuppressUI = False
        End Try


    End Sub

    Private Sub InsertProperty(ByVal sProp As String, Optional ByVal UseCsla As Boolean = False)
        Dim oTextSelection As TextSelection = DTE.ActiveWindow.Selection
        Dim sMember As String = sProp.Substring(sProp.IndexOf(" ")).Trim
        Dim sDataType As String
        Dim sName As String
        Dim i As Integer
        Dim iAscVal As Integer

        i = sMember.IndexOf("(")
        If Not i = -1 Then
            sMember = sMember.Substring(0, i)
        End If

        i = sMember.IndexOf("=")
        If Not i = -1 Then
            sMember = sMember.Substring(0, i)
        End If

        sDataType = sMember.Substring(sMember.IndexOf(" As ") + 1)

        For i = 0 To sMember.Length - 1
            'iAscVal = Asc(Mid(sName, i, 1))
            iAscVal = Asc(sMember.Chars(i))
            If iAscVal > 64 And iAscVal < 91 Then
                sName = sMember.Substring(i)
                Exit For
            End If
        Next i

        sName = sName.Substring(0, sName.IndexOf(" As ") + 1).Trim

        If sName.Length = 0 Then
            MsgBox("Unable to process the class property: " & sMember & ".  This is usually caused by an incorrect naming convention (e.g. not cxName)")
            Return
        End If

        sMember = sMember.Substring(0, sMember.Length - sDataType.Length).Trim

        With oTextSelection
            Dim pt As TextPoint = .ActivePoint.CodeElement(vsCMElement.vsCMElementClass).GetEndPoint(vsCMPart.vsCMPartWhole)
            If pt Is Nothing Then
                pt = .ActivePoint.CodeElement(vsCMElement.vsCMElementStruct).GetEndPoint(vsCMPart.vsCMPartWhole)
            End If
            .MoveToPoint(pt)
            .LineUp()
            .EndOfLine()

            .Text = "Public Property " & sName & "() " & sDataType
            .NewLine()
            If UseCsla Then
                .Text = "CanReadProperty(True)"
                .NewLine()
            End If
            .Text = "Return " & sMember
            .StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText)
            .StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstColumn, True)
            .Copy()
            .LineDown(False, 3)
            DTE.ExecuteCommand("Edit.Paste")
            If UseCsla Then
                .Text = "CanWriteProperty(True)"
                .NewLine()
                .Text = "If Me." & sMember & " <> Value then"
                .NewLine()
            End If
            .Text = "Me." & sMember & " = Value"
            If UseCsla Then
                .NewLine()
                .Text = "PropertyHasChanged()"
            End If
            .LineDown(False, 2)
            If UseCsla Then
                .LineDown(False, 1)

            End If
            .NewLine(2)

        End With

    End Sub


End Module