Author Topic: C# Extension Methods  (Read 4834 times)

0 Members and 1 Guest are viewing this topic.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8691
  • AKA Daniel
C# Extension Methods
« on: November 20, 2007, 02:19:00 AM »
Code: [Select]

    public static class EntityExtensions
    {
        internal static ObjectId AddToModelSpace(this Entity ent)
        {
            ObjectId objId = new ObjectId();
            if (ent == null)
            {
                throw new ArgumentNullException();
            }
            Database Db = HostApplicationServices.WorkingDatabase;
            AcDb.TransactionManager Tm = Db.TransactionManager;
            using (Transaction tr = Tm.StartTransaction())
            {
                BlockTable tb = (BlockTable)Tm.GetObject
                  (Db.BlockTableId, OpenMode.ForRead, false);
                objId = ((BlockTableRecord)Tm.GetObject
                  (tb[BlockTableRecord.ModelSpace], OpenMode.ForWrite, false)).AppendEntity(ent);
                Tm.AddNewlyCreatedDBObject(ent, true);
                tr.Commit();
            }
            return objId;
        }
    }


and now

Code: [Select]
     [CommandMethod("test")]
      static public void cmdtest()
      {
          Line ln = new Line(new Point3d(0,0,0),new Point3d(100,100,0));
          ln.AddToModelSpace();

      }
« Last Edit: November 20, 2007, 02:21:02 AM by Daniel »

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: C# Extension Methods
« Reply #1 on: November 20, 2007, 08:22:24 AM »

Daniel, how about passing the Db ? do you think that would be more efficient ??
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.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8691
  • AKA Daniel
Re: C# Extension Methods
« Reply #2 on: November 20, 2007, 08:45:11 AM »

Daniel, how about passing the Db ? do you think that would be more efficient ??

I don’t quite follow you..

I was attempting to show the idea behind Extension Methods, it’s to extend or add
methods to an existing class. In this case I have added a new method AddToModelspace()
to the Autodesk.AutoCAD.DatabaseServices.Entity class. So now all the classes that are
derived from the Entity class now have this method. Also take note of the “this” in the method signature

internal static ObjectId AddToModelSpace(this Entity ent)…

another example

Code: [Select]
          Line ln = new Line(new Point3d(0,0,0),new Point3d(100,100,0));
          ln.AddToModelSpace();

          Circle cr = new Circle(new Point3d(0, 0, 0), new Vector3d(1, 1, 1), 12.2);
          cr.AddToModelSpace();

As you can see the new method is now imbedded in the Circle and Line Classes
We are going to need more cleaning supplies  :laugh:

« Last Edit: November 20, 2007, 08:46:50 AM by Daniel »

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8691
  • AKA Daniel
Re: C# Extension Methods
« Reply #3 on: November 20, 2007, 08:55:21 AM »
piccy


Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: C# Extension Methods
« Reply #4 on: November 20, 2007, 09:11:52 AM »
yep, got that.
Currently each method call must re-establish the db variable.

I'm wondering about a design that allowed you to pass the db var from the calling method.
... may even be able to access a non-active db that way ..

.. or am I being puerile  ??
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.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8691
  • AKA Daniel
Re: C# Extension Methods
« Reply #5 on: November 20, 2007, 09:38:11 AM »


Ah Ok, how about overloading?   

Code: [Select]
public static class EntityExtensions
    {
        internal static ObjectId AddToModelSpace(this Entity ent)
        {
            ObjectId objId = new ObjectId();
            if (ent == null)
            {
                throw new ArgumentNullException();
            }
            Database Db = HostApplicationServices.WorkingDatabase;
            AcDb.TransactionManager Tm = Db.TransactionManager;
            using (Transaction tr = Tm.StartTransaction())
            {
                BlockTable tb = (BlockTable)Tm.GetObject
                  (Db.BlockTableId, OpenMode.ForRead, false);
                objId = ((BlockTableRecord)Tm.GetObject
                  (tb[BlockTableRecord.ModelSpace], OpenMode.ForWrite, false)).AppendEntity(ent);
                Tm.AddNewlyCreatedDBObject(ent, true);
                tr.Commit();
            }
            return objId;
        }
        internal static ObjectId AddToModelSpace(this Entity ent , Database Db)
        {
            ObjectId objId = new ObjectId();
            if (ent == null)
            {
                throw new ArgumentNullException();
            }
            if (Db == null)
            {
                throw new ArgumentNullException();
            }
            AcDb.TransactionManager Tm = Db.TransactionManager;
            using (Transaction tr = Tm.StartTransaction())
            {
                BlockTable tb = (BlockTable)Tm.GetObject
                  (Db.BlockTableId, OpenMode.ForRead, false);
                objId = ((BlockTableRecord)Tm.GetObject
                  (tb[BlockTableRecord.ModelSpace], OpenMode.ForWrite, false)).AppendEntity(ent);
                Tm.AddNewlyCreatedDBObject(ent, true);
                tr.Commit();
            }
            return objId;
        }
    }

So Now....

Code: [Select]
          Line ln = new Line(new Point3d(0,0,0),new Point3d(100,100,0));
          ln.AddToModelSpace();

          or
Code: [Select]
          Database Db = HostApplicationServices.WorkingDatabase;
          Line ln = new Line(new Point3d(0, 0, 0), new Point3d(100, 100, 0));
          ln.AddToModelSpace(Db);

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: C# Extension Methods
« Reply #6 on: November 20, 2007, 09:50:20 AM »


That looks like the trick ...

It's a great language, yeah !
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.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8691
  • AKA Daniel
Re: C# Extension Methods
« Reply #7 on: November 20, 2007, 09:53:09 AM »
A cleaner version

Code: [Select]
public static class EntityExtensions
    {
        internal static ObjectId AddToModelSpace(this Entity ent)
        {
            Database Db = HostApplicationServices.WorkingDatabase;
            return AddToModelSpace(ent , Db);
        }
        internal static ObjectId AddToModelSpace(this Entity ent , Database Db)
        {
            ObjectId objId = new ObjectId();
            if (ent == null)
            {
                throw new ArgumentNullException();
            }
            if (Db == null)
            {
                throw new ArgumentNullException();
            }
            AcDb.TransactionManager Tm = Db.TransactionManager;
            using (Transaction tr = Tm.StartTransaction())
            {
                BlockTable tb = (BlockTable)Tm.GetObject
                  (Db.BlockTableId, OpenMode.ForRead, false);
                objId = ((BlockTableRecord)Tm.GetObject
                  (tb[BlockTableRecord.ModelSpace], OpenMode.ForWrite, false)).AppendEntity(ent);
                Tm.AddNewlyCreatedDBObject(ent, true);
                tr.Commit();
            }
            return objId;
        }
    }

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: C# Extension Methods
« Reply #8 on: November 20, 2007, 10:23:26 AM »

Would/could another variation take a collection of Entitys ?? .. for when building compound stuff ; and pass back a collection of ObjId's perhaps ?

I know that more often than not I want to add more than a single Entity to the Db ...

.. just a thought as I wobble off to bed.
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.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8691
  • AKA Daniel
Re: C# Extension Methods
« Reply #9 on: November 20, 2007, 11:07:05 AM »
Sure, I would agree that this would be very useful, but not as en extension method to the Entity class.
Maybe adding methods to the DBObjectCollection might fit this case better ?

Code: [Select]
   internal static class DBObjectCollectionExtension
    {
        internal static ObjectIdCollection AddToModelSpace(this DBObjectCollection ents)
        {
            Database Db = HostApplicationServices.WorkingDatabase;
            return AddToModelSpace(ents, Db);
        }
        internal static ObjectIdCollection AddToModelSpace(this DBObjectCollection ents, Database Db)
        {
            ObjectIdCollection objIdCollection = new ObjectIdCollection();
            if (ents == null)
            {
                throw new ArgumentNullException();
            }
            if (Db == null)
            {
                throw new ArgumentNullException();
            }
            AcDb.TransactionManager Tm = Db.TransactionManager;
            using (Transaction tr = Tm.StartTransaction())
            {
                BlockTable tb = (BlockTable)Tm.GetObject
                  (Db.BlockTableId, OpenMode.ForRead, false);
                BlockTableRecord btr = (BlockTableRecord)Tm.GetObject
                  (tb[BlockTableRecord.ModelSpace], OpenMode.ForWrite, false);
                foreach (Entity e in ents)
                {
                    objIdCollection.Add(btr.AppendEntity(e));
                    Tm.AddNewlyCreatedDBObject(e, true);
                }
                tr.Commit();
            }
            return objIdCollection;
        }
    }

example

Code: [Select]
   [CommandMethod("test")]
      static public void cmdtest()
      {
          DBObjectCollection DbObjCollection = new DBObjectCollection();
          DbObjCollection.Add(new Line(new Point3d(0,0,0),new Point3d(100,0,0)));
          DbObjCollection.Add(new Line(new Point3d(100, 0, 0), new Point3d(100, 100, 0)));
          DbObjCollection.Add(new Line(new Point3d(100, 100, 0), new Point3d(0, 100, 0)));
          DbObjCollection.Add(new Line(new Point3d(0, 100, 0), new Point3d(0, 0, 0)));
          DbObjCollection.AddToModelSpace();
      }

LE

  • Guest
Re: C# Extension Methods
« Reply #10 on: November 20, 2007, 11:25:02 AM »
Daniel,

Did you used the function: postToDatabase(); - in your ARX coding?

Code: [Select]
bool postToDatabase (AcDbObjectId blkName, AcDbEntity *pEntity)
{
AcDbBlockTableRecordPointer pBlk(blkName, AcDb::kForWrite);
if (pBlk.openStatus() != Acad::eOk) return (false);
return (pBlk->appendAcDbEntity(pEntity) == Acad::eOk);
}

Where you can implement like:
acdbCurDwg()->currentSpaceId() == can be also the use of model or paper id's

Code: [Select]
AcGePoint3d pt(x, y, z);
AcDbPoint *pPoint = new AcDbPoint(pt);
if (pPoint && postToDatabase(acdbCurDwg()->currentSpaceId(), pPoint))
{
pPoint->setColorIndex(6);
pPoint->close();
}

And maybe in C# == could be [without any test] :

Code: [Select]
bool postToDatabase(ObjectId blkName, Entity pEntity)
{
    Database db = HostApplicationServices.WorkingDatabase;
    using (Transaction tr = db.TransactionManager.StartTransaction())
    {
        BlockTableRecord pBlk = tr.GetObject(blkName, OpenMode.ForWrite) as BlockTableRecord;
        if (pBlk is BlockTableRecord)
        {
            pBlk.AppendEntity(pEntity);
            tr.AddNewlyCreatedDBObject(pEntity, true);
            tr.Commit();
            return (true);
        } else {
            return (false);
        }
    }
}

If I have a chance, and if it is useful, will try to post a class that I been working, it is base on so many samples I have seen and studied and some of my own... One issue or something I do not like the extensive calls to for example: Database db = HostApplicationServices.WorkingDatabase;

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8691
  • AKA Daniel
Re: C# Extension Methods
« Reply #11 on: November 20, 2007, 11:59:05 AM »
Good call Luis, how about an AddToCurrentSpace() Method?

Code: [Select]
namespace CrapDraw.Runtime
{
    internal static class EntityExtension
    {
        internal static ObjectId AddToModelSpace(this Entity ent)
        {
            Database Db = HostApplicationServices.WorkingDatabase;
            return AddToModelSpace(ent , Db);
        }

        //
        internal static ObjectId AddToModelSpace(this Entity ent , Database Db)
        {
            ObjectId objId = new ObjectId();
            if (ent == null)
            {
                throw new ArgumentNullException();
            }
            if (Db == null)
            {
                throw new ArgumentNullException();
            }
            AcDb.TransactionManager Tm = Db.TransactionManager;
            using (Transaction tr = Tm.StartTransaction())
            {
                BlockTable tb = (BlockTable)Tm.GetObject
                  (Db.BlockTableId, OpenMode.ForRead, false);
                objId = ((BlockTableRecord)Tm.GetObject
                  (tb[BlockTableRecord.ModelSpace], OpenMode.ForWrite, false)).AppendEntity(ent);
                Tm.AddNewlyCreatedDBObject(ent, true);
                tr.Commit();
            }
            return objId;
        }

        //
        internal static ObjectId AddToCurrrentSpace(this Entity ent)
        {
            ObjectId objId = new ObjectId();
            if (ent == null)
            {
                throw new ArgumentNullException();
            }
            Database Db = AcAp.Application.DocumentManager.MdiActiveDocument.Database;
            AcDb.TransactionManager Tm = Db.TransactionManager;
            using (Transaction tr = Tm.StartTransaction())
            {
                BlockTableRecord curSpace = (BlockTableRecord)
                    tr.GetObject(Db.CurrentSpaceId, OpenMode.ForWrite);
                objId = curSpace.AppendEntity(ent);
                Tm.AddNewlyCreatedDBObject(ent, true);
                tr.Commit();
            }
            return objId;
        }
    }

    //-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-

    internal static class DBObjectCollectionExtension
    {
        internal static ObjectIdCollection AddToModelSpace(this DBObjectCollection ents)
        {
            Database Db = HostApplicationServices.WorkingDatabase;
            return AddToModelSpace(ents, Db);
        }

        //
        internal static ObjectIdCollection AddToModelSpace(this DBObjectCollection ents, Database Db)
        {
            ObjectIdCollection objIdCollection = new ObjectIdCollection();
            if (ents == null)
            {
                throw new ArgumentNullException();
            }
            if (Db == null)
            {
                throw new ArgumentNullException();
            }
            AcDb.TransactionManager Tm = Db.TransactionManager;
            using (Transaction tr = Tm.StartTransaction())
            {
                BlockTable tb = (BlockTable)Tm.GetObject
                  (Db.BlockTableId, OpenMode.ForRead, false);
                BlockTableRecord btr = (BlockTableRecord)Tm.GetObject
                  (tb[BlockTableRecord.ModelSpace], OpenMode.ForWrite, false);
                foreach (Entity e in ents)
                {
                    objIdCollection.Add(btr.AppendEntity(e));
                    Tm.AddNewlyCreatedDBObject(e, true);
                }
                tr.Commit();
            }
            return objIdCollection;
        }

        //
        internal static ObjectIdCollection AddToCurrrentSpace(this DBObjectCollection ents)
        {
            ObjectIdCollection objIdCollection = new ObjectIdCollection();
            if (ents == null)
            {
                throw new ArgumentNullException();
            }
            Database Db = AcAp.Application.DocumentManager.MdiActiveDocument.Database;
            AcDb.TransactionManager Tm = Db.TransactionManager;
            using (Transaction tr = Tm.StartTransaction())
            {
                BlockTableRecord curSpace = (BlockTableRecord)
                    tr.GetObject(Db.CurrentSpaceId, OpenMode.ForWrite);

                foreach (Entity e in ents)
                {
                    objIdCollection.Add(curSpace.AppendEntity(e));
                    Tm.AddNewlyCreatedDBObject(e, true);
                }
                tr.Commit();
            }
            return objIdCollection;
        }
    }
}

LE

  • Guest
Re: C# Extension Methods
« Reply #12 on: November 20, 2007, 01:07:17 PM »
Looks good! - when I get some time, will give it a try.... thanks.

LE

  • Guest
Re: C# Extension Methods
« Reply #13 on: November 21, 2007, 09:54:12 AM »
No code, I know...

Daniel,

What I was or are more focus is to have a class where I can simple initialize my cad class and have all the instances available like:

Quote
Database
TransactionManager
Transaction
BlockTable
BlockTableRecord

In something like:

Quote
public class CAD : IDisposable
{

// all the private instances of:
Database
TransactionManager
Transaction
BlockTable
BlockTableRecord

// initialize it with something like:
public CAD(bool Called)
{

// doing the appropriate control here, define:
db = Application.DocumentManager.MdiActiveDocument.Database;
tm = db.TransactionManager;
tr = tm.StartTransaction();
bt = (BlockTable)tm.GetObject(db.BlockTableId, OpenMode.ForRead, false);

}

// then all the get's or/and set's definitions

// the public methods, like adding, removing, inserting, etc, etc of object(s) :

public ObjectId Add(Entity entity)
{
ObjectId id = btr.AppendEntity(entity);
tm.AddNewlyCreatedDBObject(entity, true);
return id;
}

// more methods ...

// and the Disposal cleaning like:
void IDisposable.Dispose()
{
if (wasCalled)
{
tr.Commit();
}
tr.Dispose();
}

// then having (an easy way of writing the code as much as possible) all the command methods possible like:
[CommandMethod("TESTER")]
static public void tester()
{
using (CAD tm = new CAD(true)) //easy access to the mojo...
{
tm.OpenBlockTableRecord(tm.db.CurrentSpaceId); // start some mojo...
Line lin = new Line(new Point3d(0, 0, 0), new Point3d(4, 4, 0)); // more mojo...
tm.Add(lin); //do more mojo...
}
}

}//end of cad class

Hope to make some sense...

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: C# Extension Methods
« Reply #14 on: November 22, 2007, 05:21:25 AM »

David Vincent

I got all excited there for a moment ... thought we had a new poster :lol:

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.