Hi,
I need to make my application compatible with 2008 and have one error saying that ObjectClass is not a member of SubEntId (As ObjectID) in my InsertBlock routine. Can anyone suggest a solution here?
Public Sub InsertBlock(ByVal blockname As String, ByVal trans As Transaction) Dim db As Database = Application.DocumentManager.MdiActiveDocument.Database ' Test if block exists in the block table Dim bt As BlockTable = DirectCast(trans.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable) Dim id As ObjectId = bt(blockname) Dim btr As BlockTableRecord = trans.GetObject(id, OpenMode.ForRead, False, True) Dim br As New BlockReference(New Point3d(0, 0, 0), id) Dim MS As BlockTableRecord = DirectCast(trans.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite), BlockTableRecord) MS.AppendEntity(br) trans.AddNewlyCreatedDBObject(br, True) If btr.HasAttributeDefinitions Then Dim AtDef As AttributeDefinition, AttRef As AttributeReference For Each SubEntId As ObjectId In btr If SubEntId.ObjectClass.Name = "AcDbAttributeDefinition" Then AtDef = trans.GetObject(SubEntId, OpenMode.ForRead, False, True) AttRef = New AttributeReference AttRef.SetAttributeFromBlock(AtDef, br.BlockTransform) br.AttributeCollection.AppendAttribute(AttRef) trans.AddNewlyCreatedDBObject(AttRef, True) AtDef.Dispose() AttRef.Dispose() End If Next End If BlockRefID = br.ObjectId End Sub
ObjectId.ObjectClass property was only made available since AutoCAD 2009.
Norman Yuan
Hi,
if gettype(trans.getobject(SubEntId,OpenMode.ForRead, False, False).Equals(gettype(DatabaseServices.AttributeReference)) then
- alfred -
Alfred,
Adding that now says that "trans.getobject" is not defined.
A bit strange bit intellisense doesn't register what "trans" is within the gettype() function.
Hi,
in your sample-code the variable "trans" was the transaction you used, I just used it again.
But just because I reread your post, you are searching for a DatabaseServices.AttributeDefinition and not for an DatabaseServices.AttributeReference, so please correct that in my line.
But the rest should work.
- alfred -
Oh, oh, oh, one bracket missing! It should be:
if gettype(trans.getobject(SubEntId,OpenMode.ForRead, False, False)).Equals(gettype(DatabaseServices.AttributeDefinition)) then
(I know I should have tried it, sorry!)
- alfred -
Hi,
I'm not sure what's happened to the trans variable. It doesn't register within the gettype function for some reason.
Screenshot attached.
Hi,
have you seen my previous message with "missing brackets"?
At leat the GetObject is used the same way as you had it one line after the if, so it has to work.
The lines can also be tried in that way (simplier then:
Dim tDbObj as DatabaseServices.DBObject = trans.GetObject(SubEntId,OpenMode.ForRead,False,False)
if tDbObj.Gettype.Equals(Gettype(DatabaseServices.AttributeDefinition)) then
'now you can use your attribute-defintion
AtDef = ctype(tDbObj, DatabaseServices.AttributeDefinition)
Hoping not to have additional typos!
- alfred -
I've added the ).
Still no dice. I may just be throwing in a useless and confusing bit of information but this version uses .NET 3.0
our posts crossed again! 😉
Try to add bracket after IF:
if (gettype(trans.getobject(SubEntId,OpenMode.ForRead, False, False))).Equals(gettype(DatabaseServices.AttributeDefinition)) then
...
Hi,
what about using as (C#) or TryCast (VB) ?
C#
AttributeDefinition attDef = trans.getObject(SubEntId,OpenMode.ForRead, False, False) as AttributeDefinition; if (attDef != null) { }
VB (not certain about syntax)
Dim attDef As AttributeDefinition = TryCast(trans.getobject(SubEntId,OpenMode.ForRead, False, False), AttributeDefinition) If attDef IsNot Nothing Then
@Alfred.NESWADBA wrote:Hi,
have you seen my previous message with "missing brackets"?
At leat the GetObject is used the same way as you had it one line after the if, so it has to work.
The lines can also be tried in that way (simplier then:
Dim tDbObj as DatabaseServices.DBObject = trans.GetObject(SubEntId,OpenMode.ForRead,False,False)
if tDbObj.Gettype.Equals(Gettype(DatabaseServices.AttributeDefinition)) then
'now you can use your attribute-defintion
AtDef = ctype(tDbObj, DatabaseServices.AttributeDefinition)
Hoping not to have additional typos!
- alfred -
I would recommend that *you* should probably hit the books and become more familar with the correct way to do typecasting and type discovery.. Consider googling TryCast().
It might also help if you didn't post example code that calls GetType() on the result of Transaction.GetObject(), which discards the result of GetObject(), even though it is perfectly obvious from the OP's original code that he needs to use the object after successfully casting it to an AttributeDefinition.
@SRSDS wrote:I've added the ).
Still no dice. I may just be throwing in a useless and confusing bit of information but this version uses .NET 3.0
Hi. The solution to your problem is quite simple, if you first disregard what you've been trying to follow up to this point.
The TryCast() method will attempt to cast the object to the destination type, and return the object cast to that type, if it is of the requested type. Othewise, it will return Nothing.
See gile's response for an intelligent example.
Hi,
>> I would recommend that *you* should probably hit the books and become more familar
>> It might also help if you didn't post example code that calls GetType() on the result of Transaction.GetObject(),
I normally don't include any error handling mechanism to make a sample as short and understandable as possible.
So I assumed that SubEntId is valid (and is proofed to be valid) and so <Transaction>.GetObject always returns something based on DatabaseServices.DbObject.
And in that case when I know it's a valid result with a valid type for the following function I'm on a better way to use CType then to use TryCast because of time differences, TryCast is a quite slower than CType is it does not include any testing mechanism in it.
At least back to OP:
yes, you might include the line
if (SubEntID.isValid) andalso (Not SubEntID.IsErased) then
or you use the method mentioned by Gile's or DiningPhilosopher's TryCast.
Again sorry for my bracket mistakes!
- alfred -
@Alfred.NESWADBA wrote:Hi,
I normally don't include any error handling mechanism to make a sample as short and understandable as possible.
So I assumed that SubEntId is valid (and is proofed to be valid) and so <Transaction>.GetObject always returns something based on DatabaseServices.DbObject.
And in that case when I know it's a valid result with a valid type for the following function I'm on a better way to use CType then to use TryCast because of time differences, TryCast is a quite slower than CType is it does not include any testing mechanism in it.
At least back to OP:
yes, you might include the line
if (SubEntID.isValid) andalso (Not SubEntID.IsErased) then
or you use the method mentioned by Gile's or DiningPhilosopher's TryCast.
Again sorry for my bracket mistakes!
- alfred -
It doesn't really have anything to do with error handling.
It would be inaccurate to compare TryCast() to CType() because TryCast() is also doing what your other code does (e.g., calling GetType(), and then Equals()), only TryCast() is doing it more correctly, where you code is not.
TryCast() tests if a given object is an instance of a type, or any derived type, whereas your use of Equals() only tells if the object's runtime type is a specific type but not a derived type. While it may be that there will never be an object derived from AttributeDefinition, that doesn't make the use of Equals() to do type discovery any more correct.
So why am I objecting to your example? because it should be obvious that the OP is just starting out and is looking for guidance on how to do generic type discovery and casting correctly, rather than incorrectly.
There's no need for IsErased or IsValid here, since there is no way that either of those can be true.
Hi,
>> It would be inaccurate to compare TryCast() to CType()
Point of view? TryCast tests first and if ok it casts, CType casts without test (resulting in exception if fails), at least both functions do casting (so they can be compared ... my personal oppinion).
>> [...]because TryCast() is also doing what your other code does (e.g., calling GetType(), and then Equals()),
So with your words now my code is not as wrong as you wrote? 😉
>> While it may be that there will never be an object derived from AttributeDefinition
There may be ... yes may be, but here the code searches for an object of type AttributeDefinition and not of "may be anything else". Is my english that bad that I overread something and it was any other objecttype searched for?
Or do you mean that the OP has created a dervived class based on AttributeReference and in that case GetType().Equals does not work? Well ok, but in that case I don't think that this is the case here and again, we want to make simple samples and not split any letter of code into whens and whys (what we are doing at the moment, I know).
>> TryCast() tests if a given object is an instance of a type, or any derived type, whereas your use of Equals()
You are absolutly right, yes .... but the job here works perfect, So you mentioned one additional option that TryCast can handle, but it's not needed here. Against that you now wrote:
>> [...] for guidance on how to do generic type discovery and casting correctly,
As started, I guess it's a point of view what to prefere, Gile's code (and your suggestion) is working in similar ways and both results are correct (I see mine code running faster in case of a big data amount).
>> There's no need for IsErased or IsValid here, since there is no way that either of those can be true.
If someone did first a _PURGE and so erased the Blockdefinition then the ObjectID of an erased Entity within a BlockTableRecords might be marked as erased. (Well the OP might have checked that before, I haven't seen that code)
I have biggest respect of you and your work, but I don't know why a simple (working) code is that criticised.
- alfred -
Hi SRSDS,
In VB if you know for sure what the object is DiredtCast is the fastest, but casting is not the point.
In case you did not pick up on what gile and DinningPhilospher were pointing out, they were trying to show you how to avoid extra calls to GetObject.
I am repeating what gile and DiningPhilosopher have already pointed out but you have an Objectid and your intrested in the type of DbObject it points to in memory. From your original example it looks like that if it is the type your intrested in then you would like to use the object.
They mentioned TryCast because it is a clean way to test and to get the object.
The reason you are having problems getting the first example to work is there are 2 different GetTypes.
The GetType operator and the GetType method of the type Type.
The operator GetType takes a argument that is the Type name, and the GetType method is used with a object variable.
To get it to compile and look at it a little closer
Dim AttRef As AttributeReference For Each SubEntId As ObjectId In btr If trans.GetObject(SubEntId, OpenMode.ForRead, False, False).GetType().Equals(GetType(AttributeReference)) Then AttRef = trans.GetObject(SubEntId, OpenMode.ForRead, False, True) End If Next
I think the main point others were trying to make is notice how the result of GetObject is thrown away in testing for the type.
Perhaps he meant something along the lines of
Dim AttRef As AttributeReference For Each SubEntId As ObjectId In btr Dim dbo As DBObject = trans.GetObject(SubEntId, OpenMode.ForRead, False, True) If dbo.GetType().Equals(GetType(AttributeReference)) Then AttRef = dbo End If Next
That still does another check, but not as costly as calling GetObject 2 times for every object you want to know the type from its ObjectId.
Or even
Dim AttRef As AttributeReference For Each SubEntId As ObjectId In btr Dim dbo As DBObject = trans.GetObject(SubEntId, OpenMode.ForRead, False, True) If TypeOf dbo Is AttributeReference Then AttRef = dbo End If Next
Now knock it all out at once.
Dim AttRef As AttributeReference For Each SubEntId As ObjectId In btr AttRef = TryCast(trans.GetObject(SubEntId, OpenMode.ForRead, False, True), AttributeReference) If Not AttRef Is Nothing Then '''''' End If Next
That was the point I think they were trying to make and were not trying to argue if TryCast is faster than CType which is still not as fast as DirectCast but TryCast it is much cleaner a quicker if you do not know the type. In a situation where you would use Ctype there is no need for any of this because already know type your dealing with.
No matter how you look it, it is still VB so it sucks but the TryCast is a little less sucky.
Since the post is this long I might as well finish it with a idiotic story to bring home the point.
There are 2 parcel companies(UPS and FedEx are examples) called Ctype ans TryCast delivery.(I still do not understand how Ctype got involved but going with it.) Now Ctype is faster than TryCast but TryCast is still fast.(DirectCast is still the fastest). So one day living in America you and 2 buddies need packages from Europe and you tell the Ctype guy I think i have this package in Europe could you go check and get it? So he flies to Europe comes back and is like "great news your package was there". Then you stand there for a moment waiting for the package and you ask "well can i have it?" and he is like "I do not have it I just checked for you." Now your standing there in a awkward moment staring at the guy thinking there is no way this tard flew all the way to Europe to check for a package I needed and flew all the way back to tell me it was there. Then he tells you if the package is not there and I try to get we have to start handling exceptions, and about that time running a little behind is the Trycast guy who your buddies used and tell one buddy your package was not there so I have nothing and the other it was and here is your package. This is really getting stupid.
@Alfred.NESWADBA wrote:Well ok, but in that case I don't think that this is the case here and again, we want to make simple samples and not split any letter of code into whens and whys (what we are doing at the moment, I know).
I have biggest respect of you and your work, but I don't know why a simple (working) code is that criticised.
- alfred -
First off Alred I have read many of your post and I am sure many would agree with me when I say they have been very helpful and thanks.
I got to call you out on that comment and hopefully you understand it is only because I have respect for you and know your a smart guy.
That is one the biggest problems it seems that the when the whens and whys are never covered it only leads to assumptions and lack of understanding. I do not think anyone could disagree that Tony understands the fundamentals and how important they are and is trying to pass that on to beginners.
I can not count the hours I wasted googling for subjects skimming through webages quickly just to get enough info(don't forget time for looking at porn) just to end up with unconnected concepts and not gaining any real new knowledge, and you have helped many to gain knowledge and seemed like somrthing you would not say, but maybe I mis-understood it.
Hi sorry don't have time to go point-by-point with you.
Here are some facts:
First you posted code that discarded the result of the call to GetObject().
Then you posted revised code that used it, and did a comparision using GetType() and Equals().
And then you erroneously suggested that CType() is faster than TryCast(), while completely ignoring the fact that CType() cannot be used without also calling GetType() and Equals() or (more correctly) IsAssignableFrom() first.
I trust most here got the jist of my comments, so I'm not going to waste time debating that with you.