Когда вы связываете COM-объект с кодом .NET, VS создает межобъектную DLL, с классами interop.
Пример:
У вас есть foo.dll реализует COM-библиотеку Foo, которая включает в себя реализацию COM-интерфейса "IBar". Вы добавляете ссылку на foo.dll в проект .NET. в /bin, вы увидите файл Interop.FooLib.dll. В обозревателе объектов вы увидите Interop.FooLib, под которым вы увидите FooLib, под которым вы увидите BarClass, под которым вы увидите Base Types, под этой панелью и IBar.
В вашем .NET-коде при объявлении переменной вы можете ввести FooLib, а intellisense предоставит вам параметры Bar или BarClass().
Из того, что я понял, действительно не имеет значения, что вы используете в объявлении переменной, но это очень важно, что вы использовали для его конструктора.
То есть, оба из них должны работать:
FooLib.BarClass theBar = new FooLib.BarClass();
FooLib.Bar theBar = new FooLib.BarClass();
Но это не должно работать:
FooLib.Bar theBar = new FooLib.Bar();
Вот проблема. Мы просто отслеживали нечетную ошибку, где код, который работал для некоторых клиентов, и работал в наших средах разработки и тестирования, не работал на одном клиентском сайте, оказался программистом, использующим конструктор Bar().
Итак, может ли кто-нибудь объяснить, в чем разница между двумя конструкторами: Bar() и BarClass()?
Может кто-нибудь объяснить, почему, кажется, работает конструктор Bar()?
Может ли кто-нибудь предоставить метод для обеспечения того, чтобы никто не ошибочно вызывал неправильные конструкторы, не читая каждую строку кода?
- ADDED -
Было высказано предположение, что проблема была в нашей реализации COM. Это то, что мы делаем:
IDL:
[
object,
uuid(...),
dual,
helpstring("IBar Interface"),
pointer_default(unique),
nonextensible
]
interface IBar : IDispatch
{
[id(1), helpstring("method barify")]
HRESULT barify([out, retval] VARIANT_BOOL *rVal);
// ...
};
// ...
[
uuid(...),
version(1.0),
helpstring("Foo 1.0 Type Library")
]
library FooLib
{
importlib("stdole32.tlb");
importlib("stdole2.tlb");
// ...
[
uuid(...),
helpstring("Bar Class")
]
coclass Bar
{
[default] interface IBar;
};
// ...
};
Реализация:
class ATL_NO_VTABLE CBar :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CBar, &CLSID_Bar>,
public IDispatchImpl<IBar, &IID_IBar, &LIBID_FooLib>,
public ISupportErrorInfoImpl <&IID_IBar>
{
public:
CBar();
DECLARE_REGISTRY_RESOURCEID(IDR_BAR)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CBar)
COM_INTERFACE_ENTRY(IBar)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(ISupportErrorInfo)
END_COM_MAP()
// ...
};
- ДОБАВЛЕНИЕ ПОЗЖЕ -
Декомпилировать *, через .NET Reflector:
[ComImport, CoClass(typeof(BarClass)), Guid("...")]
public interface Bar : IBar
{
}
* Мне все равно, что интерфейс Reflector UI вызывает это разборку - если он выводит HLL, он декомпилируется.