How to attach an instance of a custom .NET class to an AutoCAD drawing

How to attach an instance of a custom .NET class to an AutoCAD drawing

jwe03
Advocate Advocate
1,549 Views
6 Replies
Message 1 of 7

How to attach an instance of a custom .NET class to an AutoCAD drawing

jwe03
Advocate
Advocate

I've seen posts which discuss how to add data to an AutoCAD drawing particularly in: https://forums.autodesk.com/t5/net/xrecord/td-p/7784239. 

 

This is great. But what i need is a way to assign an instance of a class which contains some properties and functions to a document and save it. 

Is that possible?

 

My class looks something like this:

Public Class ReinforcementDocument


    Public property name as String
    Public Property slabsLayer As String
    Public Property slabThickness As Double


    Public Sub New(ByRef name As String)

        Me.name = name

    End Sub
	
    Public Sub New(ByRef name As String, ByRef slabsLayer As String, ByRef slabThickness As Double)

        Me.name = name
        Me.slabsLayer = slabsLayer
        Me.slabThickness = slabThickness

    End Sub
    Public Sub updateDocument(ByRef slabsLayer As String, ByRef slabThickness As Double)

        Me.slabsLayer = slabsLayer
        Me.slabThickness = slabThickness

    End Sub

End Class

I need to store an instance of that class into the current opened drawing.

 

Thank you in advance.

0 Likes
Accepted solutions (1)
1,550 Views
6 Replies
Replies (6)
Message 2 of 7

_gile
Consultant
Consultant

Hi,

 

The easiest way should be storing the properties of the instance in an Xrecord so that you can easily re-create a new instance of the class passing these values to the constructor.

Another way (not so trivial) should be using serialization (you can see this topic).



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 of 7

_gile
Consultant
Consultant

Here's a little example assuming the Name property have to be unique in a drawing.

 

    public class ReinforcementDocument
    {
        public string Name { get; }
        public string SlabsLayer { get; private set; } = "";
        public double SlabThickness { get; private set; }

        public ReinforcementDocument(string name)
        {
            Name = name;
        }

        public ReinforcementDocument(string name, string slabsLayer, double slabThickness)
        {
            Name = name;
            SlabsLayer = slabsLayer;
            SlabThickness = slabThickness;
        }

        public void UpdateDocument(string slabsLayer, double slabThickness)
        {
            SlabsLayer = slabsLayer;
            SlabThickness = slabThickness;
        }

        public void Save()
        {
            var db = HostApplicationServices.WorkingDatabase;
            using (var tr = db.TransactionManager.StartOpenCloseTransaction())
            {
                var NOD = (DBDictionary)tr.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForRead);
                DBDictionary dict;
                if (NOD.Contains("ReinforcementDocument"))
                {
                    dict = (DBDictionary)tr.GetObject(NOD.GetAt("ReinforcementDocument"), OpenMode.ForRead);
                }
                else
                {
                    NOD.UpgradeOpen();
                    dict = new DBDictionary();
                    NOD.SetAt("ReinforcementDocument", new DBDictionary());
                    tr.AddNewlyCreatedDBObject(dict, true);
                }
                Xrecord xrec;
                if (dict.Contains(Name))
                {
                    xrec = (Xrecord)tr.GetObject(dict.GetAt(Name), OpenMode.ForWrite);
                }
                else
                {
                    if (!dict.IsWriteEnabled) dict.UpgradeOpen();
                    xrec = new Xrecord();
                    dict.SetAt(Name, dict);
                    tr.AddNewlyCreatedDBObject(xrec, true);
                }
                xrec.Data = new ResultBuffer(new TypedValue(1, SlabsLayer), new TypedValue());
                tr.Commit();
            }
        }

        public static bool TryGetInstance(string name, out ReinforcementDocument instance)
        {
            var db = HostApplicationServices.WorkingDatabase;
            using (var tr = db.TransactionManager.StartOpenCloseTransaction())
            {
                var NOD = (DBDictionary)tr.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForRead);
                if (NOD.Contains("ReinforcementDocument"))
                {
                    var dict = (DBDictionary)tr.GetObject(NOD.GetAt("ReinforcementDocument"), OpenMode.ForRead);
                    if (dict.Contains(name))
                    {
                        var xrec = (Xrecord)tr.GetObject(dict.GetAt(name), OpenMode.ForRead);
                        var data = xrec.Data.AsArray();
                        instance = new ReinforcementDocument(name, (string)data[0].Value, (double)data[1].Value);
                        return true;
                    }
                }
            }
            instance = null;
            return false;
        }
    }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 4 of 7

jwe03
Advocate
Advocate

Hi @_gile

Thank you for your prompt reply.

 

In the example you provided, you are saving the property slabLayer in the xRecord.

That's good, but ultimately what I would want is to save the whole ReinforcementDocument instance into the current drawing instead of saving individual properties.

 

Is that possible? 

0 Likes
Message 5 of 7

_gile
Consultant
Consultant

In the example I provided, I save the Name property (as Xrecord key) and the SlabsLayer and SlabThickness properties (as Xrecord key) which is all you need to re-create a new instance of ReinforcementDocument with the TryGetInstance() method.

ReinforcementDocument instance = null;
if (ReinforcementDocument.TryGetInstance(someName, out instance)) { // an instance of ReinforcementDocument with Name == someName have been previously saved // you can do your stuff with 'instance' } else { // none instance of ReinforcementDocument with Name == someName have been previously saved }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 6 of 7

jwe03
Advocate
Advocate

Thank you @_gile, yes sure it is all I need to recreate the instance.

So, as a rule of thumb, if i need to save an instance of a class to a drawing, I would have to save all its properties (rather than the instance itself) and then recreate it when i try to get that data back. Is that right?

 

0 Likes
Message 7 of 7

_gile
Consultant
Consultant
Accepted solution

@jwe03  a écrit :

Thank you @_gile, yes sure it is all I need to recreate the instance.

So, as a rule of thumb, if i need to save an instance of a class to a drawing, I would have to save all its properties (rather than the instance itself) and then recreate it when i try to get that data back. Is that right?

 


You could also use seralization like shown in the link I provided upper, but with such a simple class as yours, it seems to me it's not necessary.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes