We have a .Net assembly, A, that makes use of a class Foo
from a COM library, B.
We've created an interop for B (Interop.b.dll
) and A makes use of Foo
via the interop.
If I decompile Interop.b.dll
I can see the following interface defined within it:
using System.Runtime.InteropServices;
namespace Interop.b
{
[Guid("SOME-GUID")]
[CoClass(typeof (FooClass))]
[ComImport]
public interface Foo : _Foo
{
}
}
In the references settings of .Net assembly A, I have the option to embed the interop types for Interop.b.dll
. If I set this to true
the interfaces defined within Interop.b.dll
are embedded within A.dll
. If I then decompile A.dll
I can see the same interface as I found in the interop:
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Interop.b
{
[CompilerGenerated]
[Guid("SOME-GUID")]
[CoClass(typeof (object))]
[TypeIdentifier]
[ComImport]
public interface Foo : _Foo
{
}
}
Except that it's not the same. In this version we have [TypeIdentifier]
as an additional attribute and the parameter of the CoClass
attribute has changed from typeof(FooClass)
to typeof(object)
.
I note that Interop.b.dll
contains the type FooClass
, which I believe is a wrapper class for the COM type Foo
that is responsible for marshalling parameter types between .Net and COM, but this type has not been embedded in A.dll
.
Within A.dll
, Foo
is used like this:
using Interop.b;
namespace My.Product
{
public class AClass: IAClass
{
private Foo LocalFoo { get; }
public AClass()
{
LocalFoo = new Foo();
}
}
}
On a clean install, this fails with the following exception:
System.InvalidCastException: Unable to cast COM object of type 'System.__ComObject' to interface type 'Interop.b.Foo'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{SOME-GUID}' failed due to the following error: Error loading type library/DLL. (Exception from HRESULT: 0x80029C4A (TYPE_E_CANTLOADLIBRARY)).
(Interop.b.dll
has been installed to the GAC by the product installer)
On a development machine, reinstalling the product and running from installed binaries fails in the same way. Subsequently recompiling the product, which overwrites the installed binaries, and running from either code (in debug) or the fresh binaries then works.
Now, I believe the error is that the code in A.dll
should be instantiating FooClass
rather than Foo
. i.e. something like this:
LocalFoo = new FooClass();
...because Foo
is an interface (in the interop) and FooClass
is the thing that handles the marshalling of the parameter types between .Net and COM.
So, questions:
1) Am I correct that the code should be instantiating FooClass
rather than Foo
?
2) Why does it work at all on a dev machine?
3) Why is the embedded interface using typeof(object)
instead of typeof(FooClass)
?
4) What is the benefit of embedding the interfaces from the interop in A.dll
when we will still need Interop.b.dll
on the target machine to allow us to make use of FooClass
?
User contributions licensed under CC BY-SA 3.0