Now let's take a look at a second technique in .NET for storing transient (non-persisted) data with an AutoCAD document, the UserData property. The managed framework for AutoCAD associates a hash table with each document, which can be accessed using the UserData property. Hash tables are a great way to store and access data quickly: each object you store in a hash table is associated with a particular key, or lookup value. You then use this key to get at the data you've stored in the hash table.

The UserData property returns an object of the standard .NET class, System.Collections.Hashtable, so it’s advised to look on MSDN for further examples of usage.

I've written some code to demonstrate how you might store and access per-document data in the UserData property. The below C# code declares and implements a simple class called MyData to store custom data, and then two commands that store data in and use data from the UserData hash table.

The “inc” command checks whether there’s an object under a particular key, and if not, it creates and adds a MyData object. It then goes on to increment the integer value stored in that object (and therefore in the hash table)

The “bogus” command has some fun with the hash table, storing a bogus object (a Point2D object) in the place where the "inc" command expects to find a MyData object. This can only be run on a fresh drawing – one that has not had “inc” executed – otherwise there will already be an object stored in the hash table

Here's the code:

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.Runtime;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Geometry;

using System.Collections;

[assembly: CommandClass(typeof(CommandClasses.UserDataClass))]

namespace CommandClasses

{

publicclassUserDataClass

{

// Specify a key under which we want

// to store our custom data

conststring myKey = "AsdkData";

// Define a class for our custom data

publicclassMyData

{

publicint counter;

public MyData()

{

counter = 0;

}

}

[Autodesk.AutoCAD.Runtime.CommandMethod("inc")]

publicstaticvoid increment()

{

Document doc =

Application.DocumentManager.MdiActiveDocument;

Editor ed = doc.Editor;

Hashtable ud = doc.UserData;

MyData md;

md = ud[myKey] asMyData;

if (md == null)

{

object obj = ud[myKey];

if (obj == null)

{

// MyData object not found - first time run

md = newMyData();

ud.Add(myKey, md);

}

else

{

// Found something different instead

ed.WriteMessage(

"Found an object of type \"" +

obj.GetType().ToString() +

"\" instead of MyData.");

}

}

if (md != null)

{

ed.WriteMessage("\nCounter value is: " +

md.counter++);

}

}

[Autodesk.AutoCAD.Runtime.CommandMethod("bogus")]

publicstaticvoid addBogus()

{

Document doc =

Application.DocumentManager.MdiActiveDocument;

Editor ed = doc.Editor;

Hashtable ud = doc.UserData;

Point2d pt = newPoint2d();

try

{

ud.Add(myKey, pt);

}

catch

{

ed.WriteMessage(

"\nCould not add bogus object at \"" +

myKey +

"\", must be something there already.");

}

}

}

}

Now let's take a look at that running:

[From first drawing...]

Command: inc

Counter value is: 0

Command: inc

Counter value is: 1

Command: inc

Counter value is: 2

Command: inc

Counter value is: 3

Command: new

[From second drawing...]

Command: inc

Counter value is: 0

Command: inc

Counter value is: 1

Command: inc

Counter value is: 2

Command: bogus

Could not add bogus object at "AsdkData", must be something there already.

Command: new

[From third drawing...]

Command: bogus

Command: inc

Found an object of type "Autodesk.AutoCAD.Geometry.Point2d" instead of MyData.