I want to get a .NET Element from a COM Element...
Element
using Bentley.DgnPlatformNET; using Bentley.DgnPlatformNET.Elements; using Bentley.MstnPlatformNET; using BCOM = Bentley.Interop.MicroStationDGN;
Element GetElementFromComElement (BCOM.Element oElement, bool addToModel) { if (addToModel) { BCOM.Application app = Bentley.MstnPlatformNET.InteropServices.Utilities.ComApp; app.ActiveModelReference.AddElement(oElement); } IntPtr pointer = (IntPtr)oElement.MdlElementRef(); Element el = Element.GetFromElementRef(pointer); return el; }
If I call the above function with addToModel True, it works. If I call the function with addToModel False, it returns a null. But I don't want to write the COM element to file: I want an in-memory .NET Element. What's going on?
addToModel
I've marked this thread as solved, because a work-around exists. The question: 'Can we obtain a .NET Element from COM?' remains unanswered.
Hi Jon,
be aware you posted your question to a wrong forum...
Jon Summers said:What's going on?
I think you cannot expect pointer from COM is the same as pointer from NET. I do not recall any such feature described.
Without knowing and compare complete code both for COM/Interop and NET APIs, it's hard to say what is happening internally and whether it's feature or bug. Because GetFromElementRef calls internally some "convert" and "element factory" methods, I can imagine that it does find in-memory element, when not written to DGN file.
With regards,
Jan
Bentley Accredited Developer: iTwin Platform - AssociateLabyrinth Technology | dev.notes() | cad.point
Jan Šlegr said:you posted your question to a wrong forum
Oops! Thanks for pointing that out.
Jan Šlegr said:I think you cannot expect pointer from COM is the same as pointer from NET
It's an ElementRef pointer that is used: the code gets that pointer from COM, then uses it in .NET. As shared by Yongan.Fu in his csAddIns project.
ElementRef
IntPtr pointer = (IntPtr)oElement.MdlElementRef();
So why does that COM function exist if the pointer it obtains cannot be used anywhere?
Element.GetFromElementRef(pointer);
Why does that function exist if it can't construct a .NET Element from an ElementRef pointer?
Regards, Jon Summers LA Solutions
Jon Summers said: As shared by Yongan.Fu in his csAddIns project.
Can you share this project? I found a project with the same name, but I do not see such code used, so it's probably different one.
Jon Summers said:So why does that COM function exist if the pointer it obtains cannot be used anywhere?
How you can say that? In VBA, which is the same COM API, MdlElementRef is useful in many situations.
Jon Summers said:Why does that function exist if it can't construct a .NET Element from an ElementRef pointer?
As you wrote, it works when element is persisted in DGN file. So you contradict yourself.
The right question in my opinion is what is internal difference between in-memory-only and persisted representation, so the output is different.
BTW Did you read this blog? Even when it's about C++/CLI, it provides a good insight into casting process from one API to another (because to use C++/CLI is primarily about handling these types of conversions ;-).
Regards,
Jan Šlegr said:Can you share this project?
As long as it's OK with Yongan.Fu...
5165.csAddins.zip
Hmmm ... I still do not see any MdlElementRef or GetFromElementRef in the code. Or maybe something was lost when unzziped (my antivirus complains about some dll file)?
Hi Jon Summers,
Does populating the ModelRef via GetFromElementRefAndModelRef work and provide desired results?
e.g.
IntPtr elemRef = new IntPtr(interopElement.MdlElementRef()); IntPtr modelRef = new IntPtr(interopElement.ModelReference.MdlModelRefP()); return Bentley.DgnPlatformNET.Elements.Element.GetFromElementRefAndModelRef(elemRef, modelRef);
Bob
Hi,
A whiIe back, I searched for the same thing and found this: https://communities.bentley.com/communities/other_communities/bdn_other_communities/w/chinabdn-wiki/41035/c-cli-addins - I guess, the code speaks for itself (or you could translate the rest with google or so). More importantly, it works. Provided that a small c++/cli helper lib is not off limits.. (Would be nice to have such function in the sdk)
regards
Harmen große Deters said:A whiIe back, I searched for the same thing and found this
The same content, but in English, I linked in my earlier post.
My bad, I did not read you post carefully enough. (Also nice to have that blog post in English). An elemRef seems to be a reference to a persisted element, so the behavior Jon is describing is somehow logical. And Bobs example throws an AccesViolationException if the element is new.
Jon Summers said:If I call the above function with addToModel True, it works. If I call the function with addToModel False, it returns a null
When an element is first manufactured, underneath the paraphernalia of C++, .NET or VBA, it exists as a C++ ElementDescriptor. Until the element is persisted (added to a DGN model) the elementRef in that descriptor is NULL. Once the element is added to a model, an elementRef is created and (a) stored in the model cache and (b) assigned in the ElementDescriptor. At that point it becomes possible to use the conversion mechanism above to obtain a .NET Element.
ElementDescriptor
elementRef
So, if I want to create a .NET element in memory from a COM source, using the conversion shown above won't work. I must find some other procedure. Is there a way to construct a .NET Element from an MdlElementDescriptor, which is available from a COM element? There is a .NET Element constructor that takes a C++ ElementHandle, but there's no way to obtain an ElementHandle from a COM Element. What I could use is a .NET Element constructor that takes an MdlElementDescriptor, but unfortunately doesn't exist.
MdlElementDescriptor
ElementHandle
Robert Hook said:Does populating the ModelRef via GetFromElementRefAndModelRef work and provide desired results?
No, for the same reason explained above. The elementRef doesn't exist before the element has been added to a DGN model.