Using Namespaces

Autodesk University is done and finished, but no rest for the wicked … I am now on the Western European stage of the

Devdays

conference tour, with a first stop in London.
On the trip here from Las Vegas, I started to write about polygon area calculation and determining the outer boundary loop for floor slabs and walls for the next post or two,
and ran into another little issue that I thought might be worth discussing first.
Like many other aspects of life, it has to do with the principle of KISS … keep it simple, stupid.
This is mostly very sound advice for every human being, and especially applicable to programming.
The temptation to introduce complexity in software development is huge and mostly detrimental.
The best solution is mostly the simplest.
One important starting point is keeping source code minimal and easy to read,
and one aspect related to readability in .NET is namespace handling.

In .NET programming, every class has a name, which is defined within a namespace.
The fully qualified class name is the class name itself together with the namespace prefix, using the dot ‘.’ as a separator.
For instance, the entire Revit API is encapsulated in the Autodesk.Revit namespace.
That namespace defines some classes and interfaces directly, such as the CommandData class and the IExternalCommand interface.
It also defines additional nested namespaces, for instance the Geometry one, and so on.
One class inside the Autodesk.Revit.Geometry namespace is the class XYZ, whose fully qualified class name is Autodesk.Revit.Geometry.XYZ.

You may have noticed that I avoid explicitly using fully qualified class names in the code.
Instead, I make use of using statements in the module header, enabling me to make local use of the unqualified class names from those namespaces.
In some cases, we need to make use of a class that has an ambiguous name, i.e. two classes with the same name occur in different namespaces, and we would like to make use of both namespaces at the same time.
In this case, we can disambiguate the two classes by defining different aliases for them.
For instance, we have done this for the Element classes residing in the Autodesk.Revit and Autodesk.Revit.Geometry namespaces in the CmdWallProfile.cs module:


using RvtElement = Autodesk.Revit.Element;
using GeoElement = Autodesk.Revit.Geometry.Element;

We could avoid the need for this disambiguation by avoiding making simultaneous global use of both these namespaces.
That is the approach we used so far in the Util.cs module, which currently has the following namespace header:


using System;
using System.Collections.Generic;
using System.Diagnostics;
using Autodesk.Revit;
using Autodesk.Revit.Elements;
using Curve = Autodesk.Revit.Geometry.Curve;
using CylindricalFace = Autodesk.Revit.Geometry.CylindricalFace;
using Edge = Autodesk.Revit.Geometry.Edge;
using PlanarFace = Autodesk.Revit.Geometry.PlanarFace;
using Transform = Autodesk.Revit.Geometry.Transform;
using XYZ = Autodesk.Revit.Geometry.XYZ;
using XYZArray = Autodesk.Revit.Geometry.XYZArray;

Instead of including the entire Geometry namespace and disambiguating the duplicate Element class,
we defined individual aliases for each single geometry class that we make use of.
To begin with, there were just one or two of these required, but the list started growing and has now reached a size
at which I prefer to eliminate it, include the entire Geometry namespace instead, which introduces the Element class ambiguity,
and add the same disambiguation aliases for that instead, so I am replacing the lines above by


using System;
using System.Collections.Generic;
using System.Diagnostics;
using Autodesk.Revit;
using Autodesk.Revit.Elements;
using Autodesk.Revit.Geometry;
using RvtElement = Autodesk.Revit.Element;

Quite a bit shorter than the list above. This initially produces an error message

‘Element’ is an ambiguous reference between ‘Autodesk.Revit.Element’ and ‘Autodesk.Revit.Geometry.Element’

This expected error is obviously fixed by replacing the occurrences of Element by RvtElement.

So much for that.
As said, I am working on an area calculation algorithm for the floor slab and wall boundary loops.
Initially, we thought that the outer loop was always listed first in the Revit Face class EdgeLoops property, followed by the inner loops representing holes, i.e. openings such as shafts, doors or windows.
We now have a case where this is not true, so we will calculate each boundary loop polygon’s area in order to determine which is the largest one.
Stay tuned and walk in beauty.


Comments

19 responses to “Using Namespaces”

  1. Jeremy:
    Sorry to post off topic, but I’m coming up empty on internet searches. I’m trying to find an example of consuming an asp.net web service in the revit api. Do you know of any?

  2. Hi Dave,
    No problem, and nice to hear from you. Unfortunately I don’t.
    Cheers, Jeremy.

  3. Hi Dave, I’ve recently built an automated skills assessment add-in for Revit, and it uses web services to exchange data with our servers. Is this the kind of thing you mean?
    cheers
    Ed

  4. Ed:
    Yes, that would be great. I don’t want you to send me all your code, but just the basic hook ups on the server and client side would be perfect.
    Cheers (as y’all say),
    Dave

  5. I’ve developed and used web services before, just not from a windows class. So you don’t need to explain everything you’ve done.

  6. Hi Ed,
    I would also like to thank you for helping out! I will be posting a short little note on web services in a day or two … basically, it will just say that you can add your own Revit.exe.config file in the folder where Revit.exe is located to define some additional settings …
    Best regards, Jeremy.

  7. Jeremy:
    So I can use a Revit.exe.config to get the parameters for the client and bindings? That was specifically the problem I was having, because the dll wasn’t picking up the config for the app. I’ve already programmed around it, but I’ll probably switch back now. Is that file used for anything else by Revit itself?

  8. Hi Dave, if you’ve done it before I’m not sure what you need to know.
    Drop me a line myfirst [dot] mysecondname [at] cadsmart [dot] net
    have a nice day as ya’ll say ;)

  9. Dear Dave,
    No, by default that file is not used by Revit at all, as far as I know. Assuming it is not present :-) If you create it, I guess it will be read in and evaluated automatically by the .NET framework, so you should probably try to minimise the amount of stuff you put in. I just posted a new little item on this topic and look forward to further comments on that.
    Best regards, Jeremy.

  10. I tried it yesterday, using it to store the client and bindings that are created by doing the service reference in the client. It worked exactly like it was supposed to.
    Thanks!

  11. Hi Jeremy,
    I found your blog related to my problem. I am newbie in Revit API and for Visual Basic as well. I try to write my first application and don’t succeed. Here it is:
    Imports System
    Imports System.Windows.Forms
    Imports Autodesk.Revit
    ‘ _
    Public Class MyTest
    Implements Autodesk.Revit.IExternalCommand
    Public Function Execute(ByVal commandData As Autodesk.Revit.ExternalCommandData, _
    ByRef message As String, _
    ByVal elements As Autodesk.Revit.ElementSet) _
    As Autodesk.Revit.IExternalCommand.Result _
    Implements Autodesk.Revit.IExternalCommand.Execute
    MsgBox(“Hi!”)
    Return Autodesk.Revit.IExternalCommand.Result.Succeeded
    End Function
    End Class
    The Build give the log:
    Error 1 Class ‘MyTest’ must implement ‘Function Execute(commandData As ExternalCommandData, ByRef message As String, elements As ElementSet) As Result’ for interface ‘Autodesk.Revit.IExternalCommand’.
    Error 2 ‘ExternalCommandData’ is ambiguous in the namespace ‘Autodesk.Revit’.
    Error 3 ‘ElementSet’ is ambiguous in the namespace ‘Autodesk.Revit’.
    Can you help me telling how to resolve the problem? Sorry for the stupid question.
    Regards,
    EK

  12. Dear Evgeny,
    I am a newbie to Visual Basic as well, and hope to remain so forever.
    For information on your first steps into Revit programming, I suggest you have a look at the DevTV recording:
    http://thebuildingcoder.typepad.com/blog/2009/12/updated-devtv-introduction-to-revit-programming.html
    This is not targeted at helping you learn VB or C# and .NET programming. For that, you would have to look for other resources, e.g.
    http://thebuildingcoder.typepad.com/blog/2009/07/a-net-language-learning-resource.html
    Rod Howarth also covers getting started resources for both Revit API and generic .NET in his AU class:
    http://thebuildingcoder.typepad.com/blog/2009/12/au-winds-down.html
    Cheers, Jeremy.

  13. Jeremy,
    I found the reason for the problem. I used VB.NET code for VSTA. And they should be arranged to application in different ways.
    So thank you for opportunity to ask a question and excuse me for that stupid question.
    Evgeny.

  14. Jeremy,
    Thanks a lot for the useful links.
    Best wishes,
    Evgeny.

  15. Dear Evgeny,
    Congratulations on finding the solution and thank you for letting us know. You are welcome.
    Cheers, Jeremy.

  16. Hi, Jeremy:
    I tried to use the namespace as you listed such as
    using GeoElement = Autodesk.Revit.Geometry.Element;
    but my MSVS cannot find the namespace.
    Do I need to add some other reference other than RevitAPI.dll and RevitAPIUI.dll.
    Thakns very much.
    Rui

  17. I just looked at the RevitLookup file and it has a Utility folder in the project. How can I have this folder in my project?

  18. Dear Rui Liu,
    Nope, you do not need any other than those two references to obtain access to the full Revit API.
    The namespace Autodesk.Revit.Geometry was provided in the Revit 2010 API, though.
    In Revit 2011 and 2012 the geometry elements were moved into the namespace Autodesk.Revit.DB.
    Cheers, Jeremy.

  19. Dear Rui Liu,
    To create a folder within a Visual Studio project, right click on the project in the solution view and select Add > New Folder.
    If you open the RevitLookup solution RevitLookup.sln provided in C:\a\lib\revit\2012\SDK\RevitLookup\CS or wherever you installed the Revit 2012 SDK, it already contains a subfolder Utils.
    Cheers, Jeremy.

Leave a Reply