We are in the process of migrating our COM/.NET Interop application from compiling against .NET 2.0 CLR to .NET 4.0 CLR. We are seeing a problem where we have to change our code because of the automatic interpretation of an ‘object’ return value as ‘dynamic’ by the compiler only under .NET 4.0.
Our code has been executing in the .NET 4.0 runtime using the following content in our exe.config even though it compiled against .NET 2.0/3.5, so we are sure it can run properly in .NET 4.0:
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0.30319"/>
</startup>
The issue appears to be methods that return variant/object type. We have a COM TLB and Primary Interop Assembly that define an interface with method that returns an object. Here’s the COM definition and the IL for that interface method in the PIA:
IDL Definition:
[id(10), helpstring("Gets active components matching name passed in.")]
HRESULT GetCompByName([in] BSTR CompName, [out, retval] VARIANT *Components);
PIA IL:
.method public hidebysig newslot abstract virtual
instance object
marshal( struct)
GetCompByName([in] string marshal( bstr) CompName) runtime managed internalcall
{
.custom instance void [mscorlib]System.Runtime.InteropServices.DispIdAttribute::.ctor(int32) = ( 01 00 0A 00 00 00 00 00 )
} // end of method ISession::GetCompByName
The VARIANT (object) always contains an array of IDispatch objects (VT_ARRAY | VT_DISPATCH).
When our projects target .NET 2.0/3.5, the following code compiles and runs:
System.Array v =null;
//Try to get privileges from Session
v = (System.Array)(session.GetCompByName("Some Prog ID"));
privileges = (JFW.IPrivileges)(v.GetValue(v.GetLowerBound(0)));
Now that we migrated the project to .NET 4.X, we get a runtime error for the same code. Some quick googling has shown that we can’t cast the object return type to an Array until we first get it into an Object. Using the object browser, we see that the return type of GetCompByName is no longer ‘Object’, but is instead ‘Dynamic’. Here’s what we had to change our client code to do:
System.Array v =null;
//Try to get privileges from Session
v = (System.Array)(object)(session.GetCompByName("SomeProg ID")); ç Exception at runtime without extra object cast
privileges = (JFW.IPrivileges)(v.GetValue(v.GetLowerBound(0)));
My ultimate question is, how can we get the project and compiler to not interpret the PIA’s return value as ‘Dynamic’ and instead leave it alone as ‘Object’? We don’t want to change our code as we have this call in thousands of places and our application clients would all have to change as well.
See the document I have that includes screen captures of the same method VS with .NET 2 vs 4
https://onedrive.live.com/embed?cid=AE1D3AA8CFE3192F&resid=AE1D3AA8CFE3192F%21116
Thanks,
Brian R.