API interface casting

Programming and macros
User avatar
bnemec
Posts: 1865
Joined: Tue Mar 09, 2021 9:22 am
Answers: 10
Location: Wisconsin USA
x 2458
x 1338

API interface casting

Unread post by bnemec »

I'm not not exactly in love with how the SW API uses inheritance to deal with allowing backward compatibility as new features come out. But I'm also no professional programmer so... I run into casting exceptions a little too often when skipping several generations.

For example, I'm changing state on a file that was accessed from search result. When search result object type is file we can cast to IEdmFile5. Fine, but I want to change state and although I don't need ChangeState3, it was driven into me a long time ago to avoid deprecated functions unless there's a good reason. So I get IEdmFile5 but just found out that cannot be cast to IEdmFile13 (the first generation to have ChangeState3). Now I'm going to Christopher Columbus my way to finding out the allowable steps of what IEdmFile** can be cast to other IEdmFile**.

Would be super if there is a list of allowable casts somewhere in the help. Has anyone see this? I cannot find it if there is.
by JSculley » Tue Oct 12, 2021 1:45 pm
bnemec wrote: Tue Oct 12, 2021 12:10 pm So I get IEdmFile5 but just found out that cannot be cast to IEdmFile13 (the first generation to have ChangeState3).
The SW API uses Microsoft COM (Component Object Model). One of the primary rules of COM is backward compatibility. Every new version of an interface (IEdmFile5, IEdmFile6, etc...) should be backward compatible. If I am handed an object which I know to be an IEdmFile, I should be able to cast it to any interface from IEdmFile5 all the way up to IEdmFile17. I just did exactly this in a simple PDM test add-in.

You problem appears to be a limitation specific to IEdmSearchResult and is probably a bug. The documentation states that for the object type EdmObject_File, the object is a file, and it supports the IEdmFile5 interface. You can cast it to any interface from 5 all the way up to 11 with no problem. Once you get to 12, things break. The workaround is simple though. You have a IEdmFile5, you can just call GetObject for the vault, passing in the ID from the IEdmFile5 and then cast the returned object to whatever you need:

Code: Select all

IEdmSearch10 search = vault.CreateSearch2() as IEdmSearch10;
search.FileName = "499 OR 434";
IEdmSearchResult6 result = search.GetFirstResult() as IEdmSearchResult6;
if (result.ObjectType == EdmObjectType.EdmObject_File)
{
    IEdmFile5 theFile = (IEdmFile5)result;
    IEdmFile12 theFile12 = null;
    try
    { 
         theFile12 = (IEdmFile12)theFile;                
    } catch (InvalidCastException ice)
    {
        theFile12 = (IEdmFile12) vault.GetObject(EdmObjectType.EdmObject_File, theFile.ID);
        Debug.Print("Cast failed, object retrieved from vault directly");
    }
}
Go to full post
User avatar
JSculley
Posts: 586
Joined: Tue May 04, 2021 7:28 am
Answers: 54
x 7
x 821

Re: API interface casting

Unread post by JSculley »

bnemec wrote: Tue Oct 12, 2021 12:10 pm So I get IEdmFile5 but just found out that cannot be cast to IEdmFile13 (the first generation to have ChangeState3).
The SW API uses Microsoft COM (Component Object Model). One of the primary rules of COM is backward compatibility. Every new version of an interface (IEdmFile5, IEdmFile6, etc...) should be backward compatible. If I am handed an object which I know to be an IEdmFile, I should be able to cast it to any interface from IEdmFile5 all the way up to IEdmFile17. I just did exactly this in a simple PDM test add-in.

You problem appears to be a limitation specific to IEdmSearchResult and is probably a bug. The documentation states that for the object type EdmObject_File, the object is a file, and it supports the IEdmFile5 interface. You can cast it to any interface from 5 all the way up to 11 with no problem. Once you get to 12, things break. The workaround is simple though. You have a IEdmFile5, you can just call GetObject for the vault, passing in the ID from the IEdmFile5 and then cast the returned object to whatever you need:

Code: Select all

IEdmSearch10 search = vault.CreateSearch2() as IEdmSearch10;
search.FileName = "499 OR 434";
IEdmSearchResult6 result = search.GetFirstResult() as IEdmSearchResult6;
if (result.ObjectType == EdmObjectType.EdmObject_File)
{
    IEdmFile5 theFile = (IEdmFile5)result;
    IEdmFile12 theFile12 = null;
    try
    { 
         theFile12 = (IEdmFile12)theFile;                
    } catch (InvalidCastException ice)
    {
        theFile12 = (IEdmFile12) vault.GetObject(EdmObjectType.EdmObject_File, theFile.ID);
        Debug.Print("Cast failed, object retrieved from vault directly");
    }
}
User avatar
bnemec
Posts: 1865
Joined: Tue Mar 09, 2021 9:22 am
Answers: 10
Location: Wisconsin USA
x 2458
x 1338

Re: API interface casting

Unread post by bnemec »

JSculley wrote: Tue Oct 12, 2021 1:45 pm The SW API uses Microsoft COM (Component Object Model). One of the primary rules of COM is backward compatibility. Every new version of an interface (IEdmFile5, IEdmFile6, etc...) should be backward compatible. If I am handed an object which I know to be an IEdmFile, I should be able to cast it to any interface from IEdmFile5 all the way up to IEdmFile17. I just did exactly this in a simple PDM test add-in.

You problem appears to be a limitation specific to IEdmSearchResult and is probably a bug. The documentation states that for the object type EdmObject_File, the object is a file, and it supports the IEdmFile5 interface. You can cast it to any interface from 5 all the way up to 11 with no problem. Once you get to 12, things break. The workaround is simple though. You have a IEdmFile5, you can just call GetObject for the vault, passing in the ID from the IEdmFile5 and then cast the returned object to whatever you need:

Code: Select all

IEdmSearch10 search = vault.CreateSearch2() as IEdmSearch10;
search.FileName = "499 OR 434";
IEdmSearchResult6 result = search.GetFirstResult() as IEdmSearchResult6;
if (result.ObjectType == EdmObjectType.EdmObject_File)
{
    IEdmFile5 theFile = (IEdmFile5)result;
    IEdmFile12 theFile12 = null;
    try
    { 
         theFile12 = (IEdmFile12)theFile;                
    } catch (InvalidCastException ice)
    {
        theFile12 = (IEdmFile12) vault.GetObject(EdmObjectType.EdmObject_File, theFile.ID);
        Debug.Print("Cast failed, object retrieved from vault directly");
    }
}
oh, I just assumed I was doing it wrong. Ok, so I'll use getObject as you detailed. Fortunately searchResult has parentFolder.
Post Reply