2

I am building an VB.NET application in Visual Studio using SOLIDWORKS API - my application connects to SOLIDWORKS application via COM, and performs some actions in it using various API calls. The API is accessed by adding project references to SOLIDWORKS .dll files. These files must be embedded to the executable of my application for legal reasons.

This question is not specific to that API, but I will try to explain what I want to do. There is a SOLIDWORKS API interface called Body2 that governs manipulation of model objects (bodies) in 3D space. For example, Body2 interface provides a method ApplyTransform that allows moving or rotating a certain body by applying a MathTransform (a transform matrix) to it:

ModelBody.ApplyTransform(rotationMatrix) 'rotates the body

Now, the Body2 objects do not store these transformation matrices - they are applied and forgotten. However, in my application, I need to persistently store that information, so that at some point, I can reverse all transformations, and return the body to it's original position.

Therefore, I want to extend the Body2 interface by adding a new property to it, called "CombinedTransformMatrix", so that every time I call ApplyTransform, I could also update the value of this property, for example:

ModelBody.ApplyTransform(rotationMatrix)
ModelBody.CombinedTransformMatrix.Multiply(rotationMatrix)
ModelBody.ApplyTransform(translationMatrix)
ModelBody.CombinedTransformMatrix.Multiply(translationMatrix)

And when I finally want to return the body to it's original position, I could call:

ModelBody.ApplyTransform(ModelBody.CombinedTransformMatrix.Inverse)
ModelBody.CombinedTransformMatrix = New MathTransform 'reset matrix

Ideally, it would be really nice to also extend the ApplyTransform method, so that it would update the CombinedTransformMatrix automatically, for example:

Overrides Function ApplyTransform(Xform As MathTransform) As Boolean
   'Do whatever SOLIDWORKS does in this function

   'My additional code:
   Me.CombinedTransformMatrix.Multiply(Xform)
End function

(I know I should do an extension rather than an override, but I don't know how)

If this is possible, then I could simplify the code for the body transformations, as the CombinedTransformMatrix would update automatically:

'Rotate and move
ModelBody.ApplyTransform(rotationMatrix)
ModelBody.ApplyTransform(translationMatrix)

'Return to original position
ModelBody.ApplyTransform(ModelBody.CombinedTransformMatrix.Inverse)
ModelBody.CombinedTransformMatrix = New MathTransform 'reset matrix

I would very much prefer this kind of a solution instead of creating some derived class from Body2, or making some kind of a wrapper class that stores CombinedTransformMatrix outside the Body2 object. I want to store that bit inside the object itself. As for derived class, Visual Studio doesn't even allow me to inherit from Body2 - says "'Body2Class' is not allowed when its assembly is configured to embed interop types.". And I must embed these .dll files because otherwise I would have to ship them along the .exe of my application, which is legally prohibited by SOLIDWORKS.

Is what I want possible? Can I add that CombinedTransformMatrix to the Body2 interface without creating a derived class? And is it possible to extend that ApplyTransform method with my additional code without knowing how that method is implemented?

If not, what is the next best solution to achieve what I want? Like I said, I would very much like to avoid wrappers or additional variables outside of Body2, because there will be lots of these Body2 objects, they will persist throughout the application's lifetime, each will have a different transformation, so having to store their transformation information outside themselves would seriously complicate my code.

  • To make an extension method, your method needs to be in a shared context (I know for sure a `Module` works, I suspect a `Shared Class` would work as well), it needs the `System.Runtime.CompilerServices.Extension` attribute, and the first argument needs to be the type that is being extended. – Craig Dec 06 '21 at 14:53
  • @Craig thanks for that info. But what about the main issue, adding a new property to that interface provided by the API? – Justinas Rubinovas Dec 06 '21 at 15:38
  • As far as I know, extensions only work as subs/functions. But you can certainly put an extension method on any interface---see Linq which is entirely implemented as extension methods on `IEnumerable(Of T)`. – Craig Dec 06 '21 at 17:34
  • @Craig I see, thanks. But I need to store some data on that Body2 object, and a method can't store it... I need to attach a property to it somehow. – Justinas Rubinovas Dec 06 '21 at 17:45
  • In that case, you need some sort of encapsulation. Maybe that's inheritance, maybe it's some kind of wrapper (composition). – Craig Dec 06 '21 at 17:55
  • @Craig well, like I wrote in my post, I want to find a way to do this without a wrapper, and preferably without inheritance either (I could live with it if there is really no other way, but I'd like to avoid it at all costs). Besides, I can't seem to make inheritance work for the reasons I wrote in my post. – Justinas Rubinovas Dec 06 '21 at 17:57
  • You can make a method `ReturnToOriginalPosition` that uses properties stored in you .NET class. This way, you get your extension method without the unpossibility of extended properties. – HackSlash Dec 14 '21 at 23:39
  • IANAL, I believe it would still be a breach of the copyright to include their library in your binary. It doesn't matter if it's shipped as a separate file or embedded. You are still distributing copyrighted material without a license. – HackSlash Dec 14 '21 at 23:41

1 Answers1

1

There is no universal way of doing this. You can maintain the separate dictionary with your COM object (e.g. IBody2 in this case) to be a key and the additional parameters (tags) to be a value. You will need to manually update the dictionary to remove the data when the pointer is destroyed. There are however some specific SW interfaces that do have some ways to associate custom data (similar to tags). For instance, IBody2 has the IBody2::AddPropertyExtension2 which allows associating custom data with the body itself, IEntity has the IEntity::CreateStringAttributeDefinition (note, this is not documented method) etc.

But there is no something like universal System::Windows::Forms::Tag property for Windows Controls or Dependency Property for DependencyObjects exists for COM classes.

Artem
  • 334
  • 2
  • 6