TheSwamp

Code Red => .NET => Topic started by: 57gmc on June 07, 2012, 10:53:30 AM

Title: Problem with AttributeCollection
Post by: 57gmc on June 07, 2012, 10:53:30 AM
I created this extension method for the AttributeCollection. The problem is that although it erases all objects, it leaves one erased one. When finished, the Count is 1, but if you try to access it, you get eWasErased. I've come up with an alternative, but I'm curious as to what causes this.
Code - C#: [Select]
  1.       public static void Clear(this AttributeCollection ac, Transaction tr)
  2.       {        
  3.          foreach (ObjectId attRef in ac.)
  4.          {
  5.             DBObject att = tr.GetObject(attRef, OpenMode.ForWrite);
  6.             att.Erase();
  7.          }
  8.       }
Title: Re: Problem with AttributeCollection
Post by: 57gmc on June 08, 2012, 10:44:14 AM
Through further testing, I found that there is apparently a bug in the api. Although you can erase all the objects in the collection, whatever was stored at index = 0 will not clear from the Count. Here is a workaround method.

Code - C#: [Select]
  1.       public static void Clear(this AttributeCollection ac)
  2.       {
  3.          foreach (ObjectId attId in ac)
  4.          {
  5.             // This test is due to a bug in the api.
  6.             // The item at index = 0 will not clear from the collection.
  7.             if (!attId.IsErased)
  8.             {
  9.                AttributeReference attref = attId.GetObject(OpenMode.ForWrite) as AttributeReference;
  10.                attref.Erase(true);
  11.             }
  12.          }
  13.       }
Title: Re: Problem with AttributeCollection
Post by: 57gmc on June 08, 2012, 11:03:00 AM
Keep in mind that once you use this method, anytime you iterate the AttributeCollection there is the potential that you'll hit the erased object and so you should add a check for IsErased to any method that iterates the collection.
Title: Re: Problem with AttributeCollection
Post by: It's Alive! on June 08, 2012, 11:18:13 PM
Code: [Select]
namespace Autodesk.AutoCAD.DatabaseServices
{
  [Wrapper("AcTransaction")]
  public class Transaction : RXObject
  {
    protected internal Transaction(IntPtr unmanagedPointer, bool autoDelete);

    public virtual TransactionManager TransactionManager { get; }

    public virtual void Abort();
    public virtual void AddNewlyCreatedDBObject(DBObject obj, bool add);
    public virtual void Commit();
    protected override void DeleteUnmanagedObject();
    public DBObjectCollection GetAllObjects();
    public virtual DBObject GetObject(ObjectId id, OpenMode mode);
    public virtual DBObject GetObject(ObjectId id, OpenMode mode, bool openErased);///<-==-==**
    public virtual DBObject GetObject(ObjectId id, OpenMode mode, bool openErased, bool forceOpenOnLockedLayer);
  }
}
and
Code: [Select]
    public DBObject GetObject(OpenMode mode);
    public DBObject GetObject(OpenMode mode, bool openErased);//<<<------
    public DBObject GetObject(OpenMode mode, bool openErased, bool forceOpenOnLockedLayer);
Title: Re: Problem with AttributeCollection
Post by: 57gmc on June 11, 2012, 11:17:13 AM
Thanks Dan, that would provide this alternative implementation of the method:
Code - C#: [Select]
  1.       public static void Clear(this AttributeCollection ac)
  2.       {
  3.          foreach (ObjectId attId in ac)
  4.          {
  5.             // This openErased = false option is used due to a bug in the api.
  6.             // The item at index = 0 will not clear from the collection.
  7.             AttributeReference attref = attId.GetObject(OpenMode.ForWrite, false) as AttributeReference;
  8.             attref.Erase(true);
  9.          }
  10.       }
  11.  
Title: Re: Problem with AttributeCollection
Post by: Jeff H on June 11, 2012, 02:54:29 PM
What year are you using?
Title: Re: Problem with AttributeCollection
Post by: 57gmc on June 11, 2012, 05:47:57 PM
2010
Title: Re: Problem with AttributeCollection
Post by: 57gmc on June 12, 2012, 11:30:39 AM
Hi Dan, this is from the arx reference for the AcDbTransactionManager::getObject method:
Quote
If the openErasedObject Boolean is Adesk::kTrue, then even an erased object can be obtained. If openErasedObject is Adesk::kFalse, then trying to obtain an erased entity results in an error return value.

From the .Net reference, which doesn't give any info, the assumption would be that it would skip trying to get the object if it had been erased.
So in this situation, only my first example works. The second example still throws an eWasErased exception. Even if the second one did work, I think you would still need to test for erased objects when iterating the AttributCollection elsewhere because the count is off by one.