Now begin the porting work. The following sections outline the main steps in porting. Code from the stock subassembly DaylightBench.vb is used as an illustration.
Adding the namespaces Autodesk.Civil.Roadway and Autodesk.Civil is recommended because members in these two namespaces are frequently used in subassemblies. Your subassembly may require additional namespaces. These are the namespaces imported in the stock Civil 3D subassemblies (from C3DStockSubassemblies.vbproj):
Remove the On Error statements in the GetLogicalNamesImplement(), GetInputParametersImplement(), and GetOutputParametersImplement() methods. Comment these statements out in DrawImplement (), because you will re-use the code in Step 14.
Regular expression:
Remove all the Exit Sub and Error Handler: statements at the end of each subroutine. In VBA, you may see following code at the end of each subroutine - remove it, or move it into the appropriate Catch statement when converting error handling logic in step 14.
Exit Sub ErrorHandler: RecordError Err.Number, Err.Description, Err.Source
Regular expression:
Remove the following code at the beginning of each subroutine:
' Get the roadway state object Dim oRwyState As AeccRoadwayState Set oRwyState = GetRoadwayState()
The corridorState object is already passed in by the argument of the subroutine, so it is not necessary to get it yourself.
Regular expression:
All instances of the variable oRwyState used in VBA should be renamed corridorState in .NET. The corridorState variable is passed in by argument.
Regular expression:
In VBA, the parameter Value() method returns null if the key does not exist. In the .NET API, the same code will throw an exception. Where you access a parameter, you need to use a Try / Catch block to catch this case:
' VBA: vCutSlope = oParamsDouble.Value("CutSlope") If IsEmpty(vCutSlope) Then vCutSlope = c_dCutSlopeDefault
This code can be changed to:
' .NET: Try vCutSlope = oParamsDouble.Value("CutSlope ") Catch vCutSlope = c_ dCutSlopeDefault End Try
Regular expression:
The global function RecordError() is replaced by Utilities.RecordError().
' VBA: RecordError(aeccRoadwayErrorValueTooLarge, "RoundingTesselation", "DaylightBench")
Change to:
'.NET: Utilities.RecordError(corridorState, CorridorError.ValueTooLarge, "RoundingTesselation", "DaylightBench")
Regular expression:
In VBA subassembly code, you will see global variables such as g_iRight, g_sSide, which have a "g_" prefix. Most of these global variables have been moved to the Utilities class and renamed.
The following table lists some commonly used global variables and their corresponding ones in the Utilities class. Refer to the definition of the Utilities class for more information.
From | To |
---|---|
g_sSide | Utilities.Side |
g_iLeft | Utilities.Left |
g_iRight | Utilities.Right |
g_iTrue | Utilities.ITrue |
Rounding_Option.NoneType | Utilities.RoundingOption.NoneType |
CutSituation | Utilities.FillOrCut.FillSituation |
SubbaseType | Utilities.ShoulderSubbaseType.Subbase |
In VBA subassembly code, nearly all the COM enumerations have an "aecc" prefix, such as aeccParamLogicalNameTypeAlignment. Replace them with corresponding .NET enumerations.
As a rule, the corresponding .NET enumerations are named by removing the "aecc" prefix and making the detail category a child member. For example, aeccParamLogicalNameTypeAlignment becomes ParamLogicalNameType.Alignment.
The following table lists some commonly used COM enumerations and their corresponding .NET enumerations.
From | To |
---|---|
aeccParamLogicalNameTypeAlignment | ParamLogicalNameType.Alignment |
aeccRoadwayModeLayout | CorridorMode.Layout |
aeccParamAccessOutput | ParamAccessType.Output |
Replace COM types with their corresponding .NET types.
The following table lists some commonly used COM types and their corresponding .NET types.
From | To |
---|---|
IAeccParamsDouble | ParamDoubleCollection |
IAeccRoadwayLinks | LinkCollection |
IAeccParam | Param |
AeccRoadwayLink | Link |
AeccParamLong | ParamLong |
Regular expressions:
Convert IAeccParamsAlignment and AeccParamsAlignment to ParamAlignmentCollection
Convert: IAeccRoadwayLinks to LinkCollection
Convert AeccRoadwayLink to Link
Convert AeccParamLong to ParamLong
These four regular expressions do not cover all the required changes, so you will have to make additional changes manually.
Where the subassembly uses Object, it should be changed to a built-in type, as Object is not type-safe.
' .NET Before: Dim vSide As Object Try vSide = oParamsLong.Value(Utilities.Side) Catch vSide = SideDefault End Try
' .NET After: Dim vSide As Long Try vSide = oParamsLong.Value(Utilities.Side) Catch vSide = SideDefault End Try
Remove the g_All, g_s and s prefixes in each variable name to match the new convention for code names.
From | To |
---|---|
g_AllCodes.g_sHinge_Cut.sCode | Codes.HingeCut.Code |
g_AllCodes.g_sDaylight.sCode | Codes.Daylight.Code |
g_AllCodes.g_sDaylight_Cut.sCode | Codes.DaylightCut.Code |
Regular expression:
In VBA, many arrays are defined with a lower bound at index “1”. This is not allowed in .NET, so you should modify their definitions.
In most situations, you can just modify the array definition do not need to make any other changes. The array element 0 is defined but left unused.
' .NET Before: Dim sPointCodeArray(1 To 9, 0 To 1) As String
' .NET After: Dim sPointCodeArray(0 To 9, 0 To 1) As String
If this array is passed as an argument to a method, you will need to do more work. In this case, the array is most likely used from index “0”. You need to modify all the code that uses this array to take into account the change in index numbering.
In VBA, On Error Resume Next and On Error GoTo ErrorHandler statements are used to handle errors. But in .NET, exceptions are used instead. Modify all cases where errors are detected to use Try…Catch blocks.
' VBA: On Error Resume Next Dim oTargetDTM As IAeccSurface Set oTargetDTM = oParamsSurface.Value("TargetDTM") If oTargetDTM Is Nothing Then ' Error handling code goes here Exit Sub End If On Error GoTo ErrorHandler
Change error handling to:
' .NET: Dim oTargetDTMId As ObjectId Try oTargetDTMId = oParamsSurface.Value("TargetDTM") Catch ' Error handling code goes here Exit Sub End Try
In the COM API, the arguments and return values all refer to a database object instance. However, in the .NET API, arguments and return values are the ObjectId of the database object, not the object itself.
' VBA: Dim oTargetDTM As IAeccSurface Set oTargetDTM = oParamsSurface.Value("TargetDTM")
In .NET this would be:
' .NET: Dim oTargetDTMId As ObjectId Try oTargetDTMId = oParamsSurface.Value("TargetDTM") Catch End Try
Then, to use the database object's instance, you have to use TransactionManager.GetObject() to open the database object.
' VBA: Dim oCurrentAlignment As AeccAlignment GetAlignmentAndOrigin(oRwyState, oCurrentAlignment, oOrigin)
In .NET:
' .NET: Dim currentAlignmentId As ObjectId Dim currentAlignment As Alignment Utilities.GetAlignmentAndOrigin(corridorState, currentAlignmentId, origin) ' ... Dim db As Database = Autodesk.AutoCAD.DatabaseServices.HostApplicationServices.WorkingDatabase Dim tm As Autodesk.AutoCAD.DatabaseServices.TransactionManager = db.TransactionManager currentAlignment = tm.GetObject(currentAlignmentId, OpenMode.ForRead, false, false)