Author Topic: Dataset persistence for an AutoCAD session  (Read 3884 times)

0 Members and 1 Guest are viewing this topic.

Chris K

  • Guest
Dataset persistence for an AutoCAD session
« on: December 30, 2008, 11:45:56 AM »
First let me start by saying I very green when it comes to C# and AutoCAD programming
so please forgive my overlooking the obvious, right now nothing is obvious to me.

The Mission:
I'm trying to create a class that contains a dataset with information that will be used
to evaluate a drawings name.  This wasn't that tough until I want to fill the dataset
once at the beginning AutoCAD session and then use the data for all drawings that are
loaded or will be loaded for that session.

I've created a test class to help me understand how the class is instantiated. It appears
that for each drawing a new instance of the class created.  It seems I need the class to
operate in the application, not in the document.  I not sure how to go about doing this or
if this is the correct approach.

Any suggestions?

MickD

  • King Gator
  • Posts: 3637
  • (x-in)->[process]->(y-out) ... simples!
Re: Dataset persistence for an AutoCAD session
« Reply #1 on: December 30, 2008, 03:08:37 PM »
Have a look at the IExtensionApplication (I think from memory) Interface class, this is the one and only class type that autocad looks for at start up of your dll/application.
In this class you may also need to make your data set 'static', maybe not but it's worth studying ;)
"Programming is really just the mundane aspect of expressing a solution to a problem."
- John Carmack

"Short cuts make long delays,' argued Pippin.”
- J.R.R. Tolkien

Chris K

  • Guest
Re: Dataset persistence for an AutoCAD session
« Reply #2 on: December 30, 2008, 05:17:30 PM »
Have a look at the IExtensionApplication (I think from memory) Interface class, this is the one and only class type that autocad looks for at start up of your dll/application.
In this class you may also need to make your data set 'static', maybe not but it's worth studying ;)

MickD, thanks for the suggestion.  That is the direction that I was headed.  I don't think I've got the implementation correct though.

This is a piece of test code that I'm play with to get the concept down.  I think I'm in left field with this, it bombs in 'cmdInitialize' at pt.Initialize(). 
 
Code: [Select]
namespace IMFTFilenameParse
{
    public class PersistenceTest : Autodesk.AutoCAD.Runtime.IExtensionApplication
    {
        private bool _initiated = default(bool);

        public string Status
        {
            get
            {
                return _initiated.ToString();
            }
        }

        public void Initialize()
        {
            _initiated = true;
        }

        public void Terminate()
        {
        }
    }
   
    public class PersistenceUI
    {
        PersistenceTest pt = default(PersistenceTest);

        [LispFunction("TestInitialize")]
        public ResultBuffer cmdInitialize(ResultBuffer rb)
        {
            if ((pt == default(PersistenceTest)))
            {
                pt.Initialize();
            }
            return rb;
        }

        [LispFunction("TestStatus")]
        public ResultBuffer cmdStatus(ResultBuffer rb)
        {
            if ((pt != default(PersistenceTest)))
            {
                MessageBox.Show("FilenameParse initialized: " + pt.Status, "FilenameParse.Status", MessageBoxButtons.OK);
            }
            else
            {
                MessageBox.Show("FilenameParse not initialized.", "FilenameParse.Status", MessageBoxButtons.OK);
            }
            return rb;
        }
    }
}

Any ideas where I'm going wrong?

TonyT

  • Guest
Re: Dataset persistence for an AutoCAD session
« Reply #3 on: December 30, 2008, 06:19:26 PM »
Classes with CommandMethod or LispFunction attributes applied to
non-static methods are document-specific, meaning that
the AutoCAD managed runtime will create a separate instance of the
class for each open document, the first time the command or lisp
function is invoked in each document.

So, if you don't want multiple instances of the class for each open
document, you must make the methods that have CommandMethod
or LispFunction attributes applied to them static.

First let me start by saying I very green when it comes to C# and AutoCAD programming
so please forgive my overlooking the obvious, right now nothing is obvious to me.

The Mission:
I'm trying to create a class that contains a dataset with information that will be used
to evaluate a drawings name.  This wasn't that tough until I want to fill the dataset
once at the beginning AutoCAD session and then use the data for all drawings that are
loaded or will be loaded for that session.

I've created a test class to help me understand how the class is instantiated. It appears
that for each drawing a new instance of the class created.  It seems I need the class to
operate in the application, not in the document.  I not sure how to go about doing this or
if this is the correct approach.

Any suggestions?


Chris K

  • Guest
Re: Dataset persistence for an AutoCAD session
« Reply #4 on: December 30, 2008, 07:26:17 PM »
TonyT, thanks that may be the piece of info I needed to get this done.

Chris K

  • Guest
Re: Dataset persistence for an AutoCAD session
« Reply #5 on: January 05, 2009, 06:25:36 PM »
TonyT, MikeD, thanks for the help.  Below is the test project that I created.  Seems to work.  Is there anything that I may want to do differently?

Code: [Select]
using System;
using System.Data;
using System.Windows.Forms;
using Autodesk.AutoCAD;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;

namespace FilenameParse
{
    public class PersistenceTest : Autodesk.AutoCAD.Runtime.IExtensionApplication
    {
        private bool _initiated = false;

        public bool Status
        {
            get
            {
                return _initiated;
            }
        }

        public void Initialize()
        {
            _initiated = true;
        }

        public void Terminate()
        {
        }
    }
   
    public static class PersistenceUI
    {
        private static FilenameParse.PersistenceTest _pt = new FilenameParse.PersistenceTest();

        [CommandMethod("TestInitialize")]
        public static void cmdInitialize()
        {
            if (_pt.Status == false)
            {
                _pt.Initialize();
            }
        }
        [LispFunction("TestInitialize")]
        public static ResultBuffer lspInitialize(ResultBuffer rb)
        {
            cmdInitialize();
            return rb;
        }

        [CommandMethod("TestStatus")]
        public static void cmdStatus()
        {
            MessageBox.Show("FilenameParse initialized: " + _pt.Status.ToString(), "FilenameParse.Status", MessageBoxButtons.OK);
        }

        [LispFunction("TestStatus")]
        public static ResultBuffer lspStatus(ResultBuffer rb)
        {
            cmdStatus();
            return rb;
        }
    }
}

sinc

  • Guest
Re: Dataset persistence for an AutoCAD session
« Reply #6 on: January 05, 2009, 08:01:08 PM »

Initialize() and Terminate() get called automatically by Autocad.

Code: [Select]
using System;
using System.Data;
using System.Windows.Forms;
using Autodesk.AutoCAD;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;

namespace FilenameParse
{
    public class FilenameParse : Autodesk.AutoCAD.Runtime.IExtensionApplication
    {
        private static bool _initiated = false;

        public static bool Status
        {
            get
            {
                return _initiated;
            }
        }

        public void Initialize()
        {
            _initiated = true;
        }

        public void Terminate()
        {
        }
    }

    public static class PersistenceUI
    {
        [CommandMethod("TestStatus")]
        public static void cmdStatus()
        {
            MessageBox.Show("FilenameParse initialized: " + FilenameParse.Status.ToString(), "FilenameParse.Status", MessageBoxButtons.OK);
        }

        [LispFunction("TestStatus")]
        public static ResultBuffer lspStatus(ResultBuffer rb)
        {
            cmdStatus();
            return rb;
        }
    }
}

The above code will always return TRUE as the initialization status, because Initialize() is called automatically as the DLL is loaded.

I also remember something about names that start with underscores are frowned-upon in .NET.  I can't remember exactly why, but I think it had something to do with the way that .NET managed languages all get compiled to MSIL, and the MSIL can be decompiled to any of the languages.

TonyT

  • Guest
Re: Dataset persistence for an AutoCAD session
« Reply #7 on: January 06, 2009, 10:40:59 AM »
You need to read up on IExtensionApplication, because you
are not understanding how it is used.

Your code is creating an instance of this class, and then is
calling the Initialize() method, both of  which is a no-no.

When your assembly loads, AutoCAD creates an instance
of the class that implements IExtensionApplication, and then
calls its Initialize() method, so you should never create an
instance of that class, and should never call the Initialize()
or terminate methods.

That also means there is no point to the '_initiated' variable,
because no code in your assembly can read that variable
before it is set to true.

From your CommandMethods and LispFunctions, you can
rely on the fact that an instance of your PersistenceTest
class has already been created and its Initialize() method
called (by AutoCAD).

When you use IExtensionApplication on a class, and need to
access the instance of the class (which AutoCAD creates
for you), the easiest way is to add a static property, like
this:

Code: [Select]

    public class PersistenceTest : IExtensionApplication
    {
        public PersistenceTest()
        {
            instance = this;
        }

        private static PersistenceTest instance = null;
 
        public static PersistenceTest Instance
        {
            get
            {
                 return instance;
            }
        }

        public void Initialize()
        {
              // TODO Initialize your app here
        }
 
        public void Terminate()
        {
             // TODO: clean up here
        }
    }



Given the above, you can get the instance of the PersistenceTest
class that AutoCAD creates, by referencing the "Instance" property.

TonyT, MikeD, thanks for the help.  Below is the test project that I created.  Seems to work.  Is there anything that I may want to do differently?

Code: [Select]
using System;
using System.Data;
using System.Windows.Forms;
using Autodesk.AutoCAD;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;

namespace FilenameParse
{
    public class PersistenceTest : Autodesk.AutoCAD.Runtime.IExtensionApplication
    {
        private bool _initiated = false;

        public bool Status
        {
            get
            {
                return _initiated;
            }
        }

        public void Initialize()
        {
            _initiated = true;
        }

        public void Terminate()
        {
        }
    }
   
    public static class PersistenceUI
    {
        private static FilenameParse.PersistenceTest _pt = new FilenameParse.PersistenceTest();

        [CommandMethod("TestInitialize")]
        public static void cmdInitialize()
        {
            if (_pt.Status == false)
            {
                _pt.Initialize();
            }
        }
        [LispFunction("TestInitialize")]
        public static ResultBuffer lspInitialize(ResultBuffer rb)
        {
            cmdInitialize();
            return rb;
        }

        [CommandMethod("TestStatus")]
        public static void cmdStatus()
        {
            MessageBox.Show("FilenameParse initialized: " + _pt.Status.ToString(), "FilenameParse.Status", MessageBoxButtons.OK);
        }

        [LispFunction("TestStatus")]
        public static ResultBuffer lspStatus(ResultBuffer rb)
        {
            cmdStatus();
            return rb;
        }
    }
}
« Last Edit: January 08, 2009, 10:38:53 AM by TonyT »