Author Topic: Best practices for simple lookup functions  (Read 9011 times)

0 Members and 1 Guest are viewing this topic.

jmaeding

  • Bull Frog
  • Posts: 304
  • I'm just here for the Shelties.
Best practices for simple lookup functions
« on: January 12, 2007, 01:18:10 PM »
I am in the process of building my library of subroutines for .net programming with acad.
I have one that retrieves a table record, like a layer or linetype, based on the name or objectID.
I have only done it for the layer name so far, and want to mutate this so it looks up any kind of table object based on the name:

Public Function getLayerObjNet(ByVal name As String) As LayerTableRecord
        Dim db As Database = HostApplicationServices.WorkingDatabase()
        Dim tm As Autodesk.AutoCAD.DatabaseServices.TransactionManager = db.TransactionManager
        Dim layTblRec As LayerTableRecord = Nothing
        Using myT As Transaction = tm.StartTransaction()
            Try
                Dim layTbl As LayerTable = CType(myT.GetObject(db.LayerTableId, OpenMode.ForRead, False), LayerTable)
                If layTbl.Has(name) Then
                    layTblRec = CType(myT.GetObject(layTbl.Item(name), OpenMode.ForRead), LayerTableRecord)
                End If
                myT.Commit()
            Catch
                layTblRec = Nothing
            Finally
                myT.Dispose()
            End Try
        End Using
        Return layTblRec
    End Function

I am wondering these things:
1) To make this work for ObjectID input, I think I can just make another function to set up an overload:
Public Function getLayerObjNet(ByVal oID as ObjectID) As LayerTableRecord
...
Is that a good way to do this? (may be the only way...)

2) Is my error checking ok, any comments welcome.

3) If I want to add a param to make this work for all tables, it would be like this:
Public Function getAnyObjNet(ByVal name As String, ByVal tableType As String) As LayerTableRecord

Now, of course, the return type cannot be LayerTableRecord, it has to switch to the type specified in the tableType param.
Is there an easy way to do this?  Can I somehow tell it to look up the object type from a string name?  Maybe that is what CType can do, I thought that only casts one object type to another though.
Once I know how to look up an object type with a string, I can make much more generic code, that adapts to the object types I am feeding in.
It would be great if there was something like:
GetObjectType("LayerTableRecord")  because I would use a variable for the string of course.  I have a feeling that is super easy...

thanks for any help.




James Maeding

Chuck Gabriel

  • Guest
Re: Best practices for simple lookup functions
« Reply #1 on: January 12, 2007, 01:31:32 PM »
Take a look at the SymbolTable and SymbolTableRecord types for starters.  All of the symbol tables (i.e. BlockTable, LayerTable) inherit from SymbolTable, so you can treat them all generically as SymbolTable objects.  The same relationship exists between SymbolTableRecord and, for instance, BlockTableRecord.

jmaeding

  • Bull Frog
  • Posts: 304
  • I'm just here for the Shelties.
Re: Best practices for simple lookup functions
« Reply #2 on: January 12, 2007, 01:32:56 PM »
One more thing, is it a bad idea to get an object with such a routine, and not do anything to "close" it?
It seems like if I get a reference to an object, I must release that at some point.
Maybe that is only if I open it for write.  I get confused between lisp/VB/ and .net...
James Maeding

jmaeding

  • Bull Frog
  • Posts: 304
  • I'm just here for the Shelties.
Re: Best practices for simple lookup functions
« Reply #3 on: January 12, 2007, 01:39:25 PM »
wow, things get deep fast.  I have read a bunch on inheritance, but not used it much in this way.
Can I use those object types generically, like:
Public Function getLayerObjNet(ByVal name As String) As SymbolTableRecord ?

if I can, is this a form of late binding?
Also, do I need to cast that at some point to the desired type so I can use the props and methods of, say, a layer object?
To me, this casting business is the strangest thing to me compared to VB6.  Its funny how it does not get a lot of press in tutorials.

I hate to seem so ignorant, I don't forget though once I understand it. thanks a bunch
James Maeding

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Best practices for simple lookup functions
« Reply #4 on: January 12, 2007, 01:43:36 PM »
Hi James.

I'm horrible with VB .. it give me a mental block.
I hope you have good fortune with it.

1) Personally, Yes I'd just overload the Method.

2) see initial comment.

3) For now, I'm write purpose built routines.





kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Chuck Gabriel

  • Guest
Re: Best practices for simple lookup functions
« Reply #5 on: January 12, 2007, 01:48:18 PM »
I don't know much about how garbage collection works in .NET, so I can't really answer your first question.

This is a form of late binding, and will have some runtime cost, though I doubt that cost will be significant.

You will need to cast the object to its specific type if you want to access any methods or properties that are not part of the base class interface.

The nice part is you probably can reduce what might otherwise have been a group of functions into a single one (I say probably because I haven't actually tried this in .NET just C++).

jmaeding

  • Bull Frog
  • Posts: 304
  • I'm just here for the Shelties.
Re: Best practices for simple lookup functions
« Reply #6 on: January 12, 2007, 01:51:33 PM »
cool, I'll post what I come up with.
This is all for that modeless dialog tool I wrote about in another post so I'll post the whole project when done.
James Maeding

jmaeding

  • Bull Frog
  • Posts: 304
  • I'm just here for the Shelties.
Re: Best practices for simple lookup functions
« Reply #7 on: January 12, 2007, 02:14:45 PM »
So this is what I have so far for the "generic" table functions:

Public Function getAnyObjNet(ByVal name As String, ByVal tableType As String) As SymbolTableRecord
        Dim db As Database = HostApplicationServices.WorkingDatabase()
        Dim tm As Autodesk.AutoCAD.DatabaseServices.TransactionManager = db.TransactionManager
        Dim symTblRec As SymbolTableRecord = Nothing
        Using myT As Transaction = tm.StartTransaction()
            Try
                Dim symTbl As SymbolTable = CType(myT.GetObject(db.LayerTableId, OpenMode.ForRead, False), tableType) '<---- not correct
                'cannot use tableType as variable for object type, must use explicit name like LayerTable, need ideas here
                If symTbl.Has(name) Then
                    symTblRec = CType(myT.GetObject(symTbl.Item(name), OpenMode.ForRead), SymbolTableRecord) '<---- works but
                    'I would prefer to send back correct cast of object even though function says "As SymbolTableRecord.."
                End If
                myT.Commit()
            Catch
                symTblRec = Nothing
            Finally
                myT.Dispose()
            End Try
        End Using
        Return symTblRec
    End Function

So while I can stay generic in most places, I must specify what kind of table I want to look up at some point.
I am also wondering if I can return a specific object type like LayerTableRecord, even though my function says "as SymbolTableRecord".
thanks
James Maeding

Chuck Gabriel

  • Guest
Re: Best practices for simple lookup functions
« Reply #8 on: January 12, 2007, 02:25:36 PM »
Having taken a closer look at it, I'm not sure this can be done in .NET the way I would do it in C++.

I would use template programming to do something like this in C++ :

Code: [Select]
AcDbSymbolTablePointer<TableType> symbolTable(pDb, AcDb::kForRead);

where TableType is a template parameter to the function that defines the type of symbol table I am interested in opening.

The paradigm in .NET seems to be something like:

Code: [Select]
Database db = HostApplicationServices.WorkingDatabase;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
  LayerTable table = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead);
}

I can't find anything in AutoCAD's managed API that offers the same genericness as the C++ version.

Sorry for the bum steer.

jmaeding

  • Bull Frog
  • Posts: 304
  • I'm just here for the Shelties.
Re: Best practices for simple lookup functions
« Reply #9 on: January 12, 2007, 02:34:45 PM »
ah, a challenge.  Lets see how this develops.  I'll post on the adesk NG's too..
James Maeding

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Best practices for simple lookup functions
« Reply #10 on: January 12, 2007, 03:00:41 PM »
I think Tony T. might have an example of this.  I will see if I can find it, or if I just imaged it out of thin air.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Best practices for simple lookup functions
« Reply #11 on: January 12, 2007, 03:10:20 PM »
Okay I think this is what I'm talking about < Link >

Here is something else from the same topic by Ton T. < Link >
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

Chuck Gabriel

  • Guest
Re: Best practices for simple lookup functions
« Reply #12 on: January 12, 2007, 03:17:17 PM »
Okay I think this is what I'm talking about < Link >

Here is something else from the same topic by Ton T. < Link >

Very nice.  Thanks.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8659
  • AKA Daniel
Re: Best practices for simple lookup functions
« Reply #13 on: January 12, 2007, 03:23:51 PM »
OT:
Just a question James, isn’t
Code: [Select]
Using myT As Transaction = tm.StartTransaction()And
Code: [Select]
myT.Dispose()
redundant? myT should be disposed at the end of the using block correct?

edit

I don’t think it hurts anything, I just wondered if the using statement in vb acted the same as in c#
« Last Edit: January 12, 2007, 03:30:20 PM by Danielm103 »

mohnston

  • Bull Frog
  • Posts: 305
  • CAD Programmer
Re: Best practices for simple lookup functions
« Reply #14 on: January 12, 2007, 07:22:24 PM »
Would passing the database along with the layer name be worth while?
Public Function getLayerTableRecordByName(dwgDB as Database, ByVal name As String) As LayerTableRecord
It's amazing what you can do when you don't know what you can't do.
CAD Programming Solutions