Author Topic: Proxy & AEC Clean/Remove  (Read 16032 times)

0 Members and 1 Guest are viewing this topic.


  • Newt
  • Posts: 77
  • wishbonesr
Proxy & AEC Clean/Remove
« on: July 02, 2013, 01:53:30 PM »
Looking for a sure fire method to purge, remove proxies programatically (especially AEC remnants).
Acceptable methods: .NET(c#) or Vlisp, or both
I posted here because lisp if preferable, but some things can't be done in lisp, but I like to expand lisp and keep working in it.
If, the moderator feels this conversation moves to a .net only topic, then perhaps it can be moved?  Don't know if that's possible for the mod to do here (otherwise I will delete and repost in .net).  Sorry ahead of time.

Attached example file that will not bind-insert due to 'proxies'.

  • Keep graphical objects that are proxies by exploding to primitives.
  • Removing all proxy records from those graphical entities.
  • Remove all Entities are not proxies, but are called proxies by autocad at a xref-bind operation.
  • Using LM:ODBX as dbx processing wrapper, so rules of dbx (if lisp) must be applicable.
I've been researching for three days, and have no idea which direction to go.  There are leads, but nothing solid.  And with that I'm forced to ask a question of how, in an overall sense, instead of asking for guidance on a very specific function.  So this post is going to sound a little emotional, because dangit, it's frustrating.

My problems are the things I don't know...
  • Why autocad says there are proxy's preventing xref-bind-insert, yet the implementation of Augusto's or Nagy's never actually remove anything, because the litmus of AcDbZombieObject or .IsAProxy never returns true (AEC junk) thus never makes an attempt at exploding, handtoent, or deletion on ents or NODs. MGDDB shows a boat load of AEC Symbol Tables and Dictionaries but none are listed as .IsAProxy
  • I don't know what exactly needs to be removed from the DB in order to programatically recreate the results of EXPORTTOAUTOCAD or it's alias.  Is the test a regex for AEC? Is there another property of the Civil3d junk that can determine?
  • Will there be repricusions of removing AEC dictionaries?  ie. Could there be inter-dictionary links that could cause a crash if I don't remove those as well?  What about objects?
  • Irnerb's post on Augi, "Remove data link from drawing", doesn't reveal all of the dicts displayed in mgddb, so I don't know if I should persue lisp, although it's my favorite (ie better at lisp than .net). Nor does MP's doc object counter

So here's my merge of Augusto and Nagy's proxy cleaner into a lisp function.  Not that it does anything against AEC, but does appear to work will with other proxy's. It cleaned the clock of CADWorx, lol, thus the filter.
Code - C#: [Select]
  1. //
  2. //
  3. [LispFunction("cd:ProxyClean")]
  4. public Boolean ProxyClean(ResultBuffer rb)
  5. {
  6.         if (rb == null)
  7.         { return false; }
  8.         TypedValue[] args = rb.AsArray();
  9.         if (args.Length != 1 || (LispDataType)args[0].TypeCode != LispDataType.ObjectId)
  10.         { return false; }
  11.         //we accept any object from the drawing that is to be processed.  I trend in sending modelspace, but it doesn't matter
  12.         //just need an object so the owning database can be retrieved
  13.         ObjectId objId = (ObjectId)args[0].Value;
  14.         Database db = objId.Database;
  15.         using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
  16.         {
  17.                 //first let's run through the blocks
  18.                 BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
  19.                 foreach (ObjectId btrId in bt)
  20.                 {
  21.                         BlockTableRecord btr = (BlockTableRecord)tr.GetObject(btrId, OpenMode.ForRead);
  22.                         foreach (ObjectId entId in btr)
  23.                         {
  24.                                 Entity ent = (Entity)tr.GetObject(entId, OpenMode.ForRead);
  25.                                 if (ent.IsAProxy)
  26.                                 {
  27.                                         //Might should be a wilcard filter from function caller
  28.                                         ProxyEntity proxyEnt = ent as ProxyEntity;
  29.                                         if (proxyEnt.ApplicationDescription.IndexOf("cadworx", 0, StringComparison.OrdinalIgnoreCase) >= 0)
  30.                                                 continue;
  31.                                         proxyEnt.UpgradeOpen();
  32.                                         using (DBObject newEnt = new Line())
  33.                                         {
  34.                                                 ent.HandOverTo(newEnt, false, false);
  35.                                                 newEnt.Erase();
  36.                                         }
  37.                                 }
  38.                         }
  39.                 }
  40.                 //call recursive call to remove dict proxies
  41.                 RemoveProxiesFromNamedObjDict(db.NamedObjectsDictionaryId, tr);
  43.                 tr.Commit();
  44.                 return true;
  45.         }
  46. }
  49. private void RemoveProxiesFromNamedObjDict(ObjectId dictId, Transaction tr)
  50. {
  51.         using (ObjectIdCollection proxyIds = new ObjectIdCollection())
  52.         {
  53.                 DBDictionary dict = (DBDictionary)tr.GetObject(dictId, OpenMode.ForRead);
  54.                 foreach (DBDictionaryEntry entry in dict)
  55.                 {
  56.                         DBObject dictObj = tr.GetObject(entry.Value, OpenMode.ForRead);
  57.                         if (dictObj.IsAProxy || entry.Value.ObjectClass.Name == "AcDbZombieObject")
  58.                                 proxyIds.Add(entry.Value); //collect them so we only have the namedobjdict open while removing
  59.                         else if (entry.Value.ObjectClass == RXClass.GetClass(typeof(DBDictionary)))
  60.                                 RemoveProxiesFromNamedObjDict(entry.Value, tr);
  61.                 }
  62.                 if (proxyIds.Count > 0)
  63.                 {
  64.                         dict.UpgradeOpen();
  65.                         foreach (ObjectId proxyId in proxyIds)
  66.                         {
  67.                                 ProxyObject proxyObj = (ProxyObject)tr.GetObject(proxyId, OpenMode.ForRead);
  68.                                 if (proxyObj.ApplicationDescription.IndexOf("cadworx", 0, StringComparison.OrdinalIgnoreCase) >= 0)
  69.                                         continue;
  70.                                 proxyObj.UpgradeOpen();
  71.                                 using (DBObject newRec = new Xrecord())
  72.                                 {
  73.                                         proxyObj.HandOverTo(newRec, false, false);
  74.                                         newRec.Erase();
  75.                                 }
  76.                         }
  77.                 }
  78.         }
  79. }

Test Calling from command line (express .net debugging)
Code: [Select]
(setq doc (vla-get-activedocument (vlax-get-acad-object)))
(setq edoc (vlax-vla-object->ename (vla-get-modelspace doc)))
(cd:ProxyClean edoc)

Side Note/Tip:
I love the code type formatting, but copying to your own editor creates (for me at least) a single line of text with the row numbers in line of the code...
If using Notepad++ or equivilent Find/Replace w/ RegEx.
Find: [0-9]+\.
Replace: \r\n
« Last Edit: July 02, 2013, 03:25:45 PM by CADDOG »


  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Proxy & AEC Clean/Remove
« Reply #1 on: July 03, 2013, 02:12:20 AM »
Yep, these are irritating at best.

I think the reason some are not shown in MP's and my code is that they're "hidden" as some sort of dictionary only attached to entities (instead of listed as a DWG dictionary). It's probably possible to get at these even through lisp, only you'd need to step through each entity in the entire DWG database (including non-graphic stuff such as dimstyles, layers, etc.). It might even be possible that they use some custom stuff which is totally unaccessible from ActiveX or even raw DXF - in which case Lisp won't be able to get to it.

I'm sorry to say this, but even .Net is not necessarily going to enable absolutely all possibilities. Most (if not all) these AEC (and other) stuff are generated by the ARX addons and/or verticals, so it's possible that they might have used something which is not opened through the managed wrappers which is available in ACad's .Net API's. But obviously chances are better that .Net would be able to get to those which Lisp can't.

BTW, usually when something fails with proxies, it means you don't have the object enablers installed. These are ARX addons (usually freely available from ADesk) which are like "viewers" for those proxy elements. Acad "should" download and install the appropriate one when it finds such a proxy ... in theory ... but as we've encountered in many aspects of ACad, this is only a utopic vision which doesn't always work. What I've found is that sometimes I need to search for the enabler and manually download + install it ... only then do the proxies work properly, enabling you to explode them into their constituent objects and clearing their extraneous data.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.


  • Newt
  • Posts: 77
  • wishbonesr
Re: Proxy & AEC Clean/Remove
« Reply #2 on: July 03, 2013, 03:33:32 AM »

heheheheheee..... Although I was hoping you'd be the one to take on this, I knew it could be a double-edged sword; In that you'd say what you said.

Ignoring that it could possibly be an enabler I don't have installed, although I have proxynotify enabled, and don't have any notifications.  The .net function attached does iterate all block objects and NODs, but is it possible for proxies to not be blocks, but plain entities?  Should I be iterating other graphical objects other than blocks?
The attached file was a file generated in house, and although we have xdata on the centerlines (CADWorx), it's not proxy objects (CADWorx 2012 - pre-proxy).  The only other proxy source is Civil3d which is the version one Structural guy has in our organization, and I have the object enabler for Civil3d manually installed.  Because there's nothing wrong with dicts that are littered in a drawing, unless it bloats a file, therefore I don't care that there happens to be tons in this particular file.

In addition, what about an effort to simply clean AEC/Civil3D from a drawing.  At least doing that, I'd be able to identify if AEC was the reason Vanilla CAD says it can't bind "because of proxies".  I couldn't fine efforts at this forum, but is anybody aware of efforts at this forum to programatically clean AEC from a drawing? (CAB?) lol.


  • Water Moccasin
  • Posts: 2283
  • Marseille, France
Re: Proxy & AEC Clean/Remove
« Reply #3 on: July 03, 2013, 12:30:03 PM »

Coincidently, I was playing to this right now.
Here's where I am using .NET (work in progress inspired by this thread).
The routine try to scan the whole database searching for proxy entities / objects in block table records, named dictionaries, symbol table records and in eventual extension dictionaries for all.

Code - C#: [Select]
  1.         [CommandMethod("RemoveProxies")]
  2.         public void RemoveProxies()
  3.         {
  4.             EraseAllProxies(HostApplicationServices.WorkingDatabase);
  5.         }
  7.         private void EraseAllProxies(Database db)
  8.         {
  9.             RXClass proxyEntity = RXClass.GetClass(typeof(ProxyEntity));
  10.             ObjectIdCollection entries = new ObjectIdCollection();
  11.             using (BlockTable bt = (BlockTable)db.BlockTableId.Open(OpenMode.ForRead))
  12.             {
  13.                 foreach (ObjectId btrId in bt)
  14.                 {
  15.                     using (BlockTableRecord btr = (BlockTableRecord)btrId.Open(OpenMode.ForRead))
  16.                     {
  17.                         foreach (ObjectId id in btr)
  18.                         {
  19.                             using (Entity ent = (Entity)id.Open(OpenMode.ForWrite))
  20.                             {
  21.                                 if (id.ObjectClass.IsDerivedFrom(proxyEntity))
  22.                                 {
  23.                                     ent.Erase();
  24.                                 }
  25.                                 SearchInExtensionDictionary(ent, entries);
  26.                             }
  27.                         }
  28.                     }
  29.                 }
  30.             }
  32.             ObjectId[] tableIds =
  33.                 {
  34.                     db.BlockTableId,
  35.                     db.LinetypeTableId,
  36.                     db.DimStyleTableId,
  37.                     db.LayerTableId,
  38.                     db.RegAppTableId,
  39.                     db.TextStyleTableId,  
  40.                     db.UcsTableId,
  41.                     db.ViewTableId,
  42.                     db.ViewportTableId
  43.                 };
  44.             foreach (ObjectId tableId in tableIds)
  45.             {
  46.                 SearchInTable(tableId, entries);
  47.             }
  49.             using (DBDictionary NOD = (DBDictionary)db.NamedObjectsDictionaryId.Open(OpenMode.ForRead))
  50.             {
  51.                 SearchInDictionaries(NOD, entries);
  52.                 foreach (ObjectId id in entries)
  53.                 {
  54.                     using (DBDictionary newDict = new DBDictionary())
  55.                     using (DBObject proxy = (DBObject)id.Open(OpenMode.ForWrite))
  56.                     {
  57.                         try
  58.                         {
  59.                             proxy.HandOverTo(newDict, true, true);
  60.                         }
  61.                         catch { }
  62.                     }
  63.                 }
  64.             }
  65.         }
  67.         private void SearchInTable(ObjectId tableId, ObjectIdCollection entries)
  68.         {
  69.             using (SymbolTable table = (SymbolTable)tableId.Open(OpenMode.ForRead))
  70.             {
  71.                 foreach (ObjectId strId in table)
  72.                 {
  73.                     using (SymbolTableRecord record = (SymbolTableRecord)strId.Open(OpenMode.ForRead))
  74.                     {
  75.                         SearchInExtensionDictionary(record, entries);
  76.                     }
  77.                 }
  78.             }
  79.         }
  81.         private void SearchInExtensionDictionary(DBObject dbObj, ObjectIdCollection entries)
  82.         {
  83.             ObjectId xdictId = dbObj.ExtensionDictionary;
  84.             if (xdictId != ObjectId.Null)
  85.             {
  86.                 using (DBDictionary xdict = (DBDictionary)xdictId.Open(OpenMode.ForRead))
  87.                 {
  88.                     SearchInDictionaries(xdict, entries);
  89.                 }
  90.             }
  91.         }
  93.         private void SearchInDictionaries(DBDictionary dict, ObjectIdCollection entries)
  94.         {
  95.             RXClass proxyObject = RXClass.GetClass(typeof(ProxyObject));
  96.             RXClass dictionary = RXClass.GetClass(typeof(DBDictionary));
  97.             SearchInExtensionDictionary(dict, entries);
  98.             foreach (DBDictionaryEntry entry in dict)
  99.             {
  100.                 ObjectId id = entry.Value;
  101.                 if (id.ObjectClass.IsDerivedFrom(proxyObject))
  102.                 {
  103.                     try
  104.                     {
  105.                         using (DBObject obj = (DBObject)id.Open(OpenMode.ForWrite))
  106.                         {
  107.                             obj.Erase();
  108.                         }
  109.                     }
  110.                     catch
  111.                     {
  112.                         entries.Add(id);
  113.                     }
  114.                 }
  115.                 else if (entry.Value.ObjectClass == dictionary)
  116.                 {
  117.                     using (DBDictionary subDict = (DBDictionary)id.Open(OpenMode.ForRead))
  118.                     {
  119.                         SearchInDictionaries(subDict, entries);
  120.                     }
  121.                 }
  122.             }
  123.         }
« Last Edit: July 03, 2013, 12:37:08 PM by gile »
Speaking English as a French Frog


  • Newt
  • Posts: 77
  • wishbonesr
Re: Proxy & AEC Clean/Remove
« Reply #4 on: July 03, 2013, 02:33:31 PM »
I have only an entry level understanding of proxies, so perhaps that lack of knowledge is the reason I can't find the proxy in the file attached in first post (there are hundreds).

As mentioned, I only know of two ways to identify a proxy object:
[Entity].IsAProxy and [objectId].Value.ObjectClass.Name == "AcDbZombieObject"
or one way in lisp:
(vlax-get obj 'ObjectName)

Alternatives?  What to look for on an object?

My understanding is that a proxy is a proxy because the object enablers are not present.  If the xml object type definition of a custom ARX object is present, then it is no longer a proxy object, therefore testing for a proxy is irrelevant as the object is no longer an AcDbZombieObject, rather the name of the actual object class.  Also, if object enablers were present, then autocad would not be restricting a bind-insert on an xref, as the enabler would handle the operation (presumably).  So in the .net example above, it does iterate the entire db in both model and layouts.

The only thing I'm not doing is iterating the block definitions, as I remember reading that autocad doesn't allow proxies to be inside the blocks themselves.  Actually I read that in the source of SuperFlatten.  Even that being stated in the comments, Joe still takes the time to cycle the block definition, as he states (line 296), it is "very rare case since the block command does not allow proxies to bew included in a block definition".  Who knows with ObjectARX?

While I was composing this, gile posted...
Coincidently, I was playing to this right now.
Here's where I am using .NET (work in progress inspired by this thread).
This thread also started my journey.
My only goal difference, is that I want to keep the primatives of any graphical object, if possible - so I use HandOverTo() for everything.

Question premise...  I don't want any non-vanila acad data to get through.  I noticed that you are using IsDerivedFrom.  Property of IsAProxy evaluates false if object enablers installed for that object type.
Question... Will IsDerivedFrom RXClass.GetClass(typeof(ProxyObject)) return true even if object enablers for that object are installed?


  • Newt
  • Posts: 77
  • wishbonesr
Re: Proxy & AEC Clean/Remove
« Reply #5 on: July 03, 2013, 02:35:09 PM »

Looks like this is going to be a .net solution.
If possible, can this be moved to the .net forum.



  • Newt
  • Posts: 77
  • wishbonesr
Re: Proxy & AEC Clean/Remove
« Reply #6 on: July 03, 2013, 05:51:40 PM »
symbol table records and in eventual extension dictionaries for all.

My problem was in here (quote above).  I stopped overthinking and ran your code.
So my problems reside in either SymbolTableRecords or in Extension Dictionaries.

You know that giddy feeling, when you realize this might work?   :ugly:

Ok.. pulled the symbol table run out, and it still cleaned successfully so it was extension dictionaries.  Which btw, you are the only one, I'm aware of, that's checking extension dictionaries and symbol tables for proxies.

Amazing gile.

I looked, and couldn't find - and is probably the reason you aren't using such a thing, but is there a collection of symbol tables to iterate, or must the default nine be iterated explicitly?

Jeff H

  • Needs a day job
  • Posts: 6103
Re: Proxy & AEC Clean/Remove
« Reply #7 on: July 03, 2013, 08:02:10 PM »
The attached drawing is creating a proxy object from a custom object defined by Civil3D as shown in picture below.
AutoCAD is responsible for creating proxy objects.
There are 2 different types created a ProxyEntity and ProxyObject.
So if a custom object is saved in drawing and the object enabler is not present then a ProxyEntity is created for objects derived from AcDbEntity(Objects with graphics)  and a ProxyObject is created for objects derived from just AcDbObject.
When these custom objects are created and the classes are first loaded the ACRX_DXF_DEFINE_MEMBERS macro is used which has a PROXY_FLAGS argument.
AcDbProxyEntity::kEraseAllowed = 0x1
AcDbProxyEntity::kTransformAllowed = 0x2
AcDbProxyEntity::kColorChangeAllowed = 0x4
AcDbProxyEntity::kLayerChangeAllowed = 0x8
AcDbProxyEntity::kLinetypeChangeAllowed = 0x10
AcDbProxyEntity::kLinetypeScaleChangeAllowed = 0x20
AcDbProxyEntity::kVisibilityChangeAllowed = 0x40
AcDbProxyEntity::kCloningAllowed = 0x80
AcDbProxyEntity::kLineWeightChangeAllowed = 0x100
AcDbProxyEntity::kPlotStyleNameChangeAllowed = 0x200
AcDbProxyEntity::kAllButCloningAllowed = 0x37F
AcDbProxyEntity::kAllAllowedBits = 0x3FF
Looking at your drawing the ProxyFlag property is 129 so looks like allows cloning and erasing.
There is much info and other considerations which can be read in ObjectARX docs, but to keep it simple and short say a application is loaded into autocad that creates custom objects. That custom object must derive from a AcDbObject if it will be able to be saved in the drawing. If it has graphics it must derive from a AcDbEntity or another object that does.
The object enabler tells AutoCAD or gives implementation on what to do when selected, how to transform it, display, etc......
Not always true but proxy objects exists in memory, and give access to the custom object data for members defined by AcDbEntity or AcDbObject. The PROXY_FLAGS setting can limit edit capabilities. And as I sure you can gues a ProxyObject derives from a DbObject and a ProxyEntity derives from a Entity.
Quickly looking at code from ADN blog the reason it misses proxy object is it searches all the entries in the Dictionaries in the NamedObjectDictionary, but the proxy object is a entry in the NameObjectDictionary, so if  it searched the entries in the NameObjectDictionary it would find it.
There is a lot more to it, but basically proxies are just data holders for custom objects allowing you to read the data for members it derive from.
A ProxyEntity should only be in BlockTablerecords and ProxyObjects can be anywhere a AcDbObject can be stored but you should be able to find all them.


  • Water Moccasin
  • Posts: 2283
  • Marseille, France
Re: Proxy & AEC Clean/Remove
« Reply #8 on: July 04, 2013, 01:33:08 AM »

Thanks for these precisions Jeff.

I don't know much about proxies, but from time to time, I'm asked for cleaning a drawing from proxies. The files I was working on yesterday came from MicroStation and had a proxy object in a line type record extension dictionary.

I never searched for proxies in symbol tables extension dictionaries before...

This made me think: as proxies are made by AutoCAD every times it encounters an object it do not recognize, whatever the application which created it, rather than adding some new location to search every time I encounter a new one, I should search everywhere it can be.
So, may be there never been a proxy in an extension dictionary of an UCS table record but as an application can create a custom object using an ucs table record, I have to search here to.

That said, the code posted upper is still a 'work in progress' and haven't been deeply tested yet.
Speaking English as a French Frog


  • Bull Frog
  • Posts: 450
Re: Proxy & AEC Clean/Remove
« Reply #9 on: July 04, 2013, 02:43:41 PM »
Great stuff guys! I've wondered about this before but haven't actually had the time to address it.

Alexander Rivilis

  • Bull Frog
  • Posts: 213
  • Programmer from Kyiv (Ukraine)
Re: Proxy & AEC Clean/Remove
« Reply #10 on: July 04, 2013, 04:45:55 PM »
Hi, Gile!
What about direct iteration of database as I've proposed in comment?


  • Water Moccasin
  • Posts: 2283
  • Marseille, France
Re: Proxy & AEC Clean/Remove
« Reply #11 on: July 04, 2013, 04:55:01 PM »
Yes Alexander, thanks.
My intent was to try this too as soon as I have some free time.
Speaking English as a French Frog


  • Water Moccasin
  • Posts: 2283
  • Marseille, France
Re: Proxy & AEC Clean/Remove
« Reply #12 on: July 04, 2013, 05:38:10 PM »
Alexander's algorithm

<EDIT: safer (and a little fater) implementation>
Code - C#: [Select]
  1. private void EraseProxies(Database db)
  2.         {
  3.             RXClass zombieEntity = RXClass.GetClass(typeof(ProxyEntity));
  4.             RXClass zombieObject = RXClass.GetClass(typeof(ProxyObject));
  5.             ObjectId id;
  6.             for (long l = db.BlockTableId.Handle.Value; l < db.Handseed.Value; l++)
  7.             {
  8.                 if (!db.TryGetObjectId(new Handle(l), out id))
  9.                     continue;
  10.                 if (id.ObjectClass.IsDerivedFrom(zombieObject) && !id.IsErased)
  11.                 {
  12.                     try
  13.                     {
  14.                         using (DBObject proxy = id.Open(OpenMode.ForWrite))
  15.                         {
  16.                             proxy.Erase();
  17.                         }
  18.                     }
  19.                     catch
  20.                     {
  21.                         using (DBDictionary newDict = new DBDictionary())
  22.                         using (DBObject proxy = id.Open(OpenMode.ForWrite))
  23.                         {
  24.                             try
  25.                             {
  26.                                 proxy.HandOverTo(newDict, true, true);
  27.                             }
  28.                             catch { }
  29.                         }
  30.                     }
  31.                 }
  32.                 else if (id.ObjectClass.IsDerivedFrom(zombieEntity) && !id.IsErased)
  33.                 {
  34.                     try
  35.                     {
  36.                         using (DBObject proxy = id.Open(OpenMode.ForWrite))
  37.                         {
  38.                             proxy.Erase();
  39.                         }
  40.                     }
  41.                     catch { }
  42.                 }
  43.             }
  44.         }
« Last Edit: July 05, 2013, 03:13:35 AM by gile »
Speaking English as a French Frog


  • Bull Frog
  • Posts: 450
Re: Proxy & AEC Clean/Remove
« Reply #13 on: July 05, 2013, 12:04:27 PM »
How do these compare in speed?

Jeff H

  • Needs a day job
  • Posts: 6103
Re: Proxy & AEC Clean/Remove
« Reply #14 on: July 05, 2013, 05:57:28 PM »
This might help speed it up a bit, and have not tested it, but could check ProxyFlags property to see if it can be erased instead of using catch block.
Since the ProxyEntity and Proxyobject use a int for its ProxyFlags property maybe something like
Code - C#: [Select]
  2.          public static bool IsErasable(this ProxyEntity proxy)
  3.        {
  4.            return (proxy.ProxyFlags & 1) == 1;
  5.        }