Когда вы связываете COM-объект из кода .NET, VS создает DLL взаимодействия с классами взаимодействия.
Пример:
У вас есть foo.dll, который реализует COM-библиотеку Foo, которая включает реализацию COM-интерфейса "IBar". Вы добавляете ссылку на foo.dll в проект .NET. в / bin вы увидите Interop.FooLib.dll. В обозревателе объектов вы увидите Interop.FooLib, под ним вы увидите FooLib, под ним вы увидите BarClass, под которым вы увидите базовые типы, под этим Bar и 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 () иногда работает?
Может ли кто-нибудь предоставить метод, обеспечивающий, чтобы никто не ошибочно вызывал неправильные конструкторы, не читая каждую строку кода?
- ДОБАВЛЕНО -
Было высказано предположение, что проблема была в нашей реализации 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 называет это дизассемблированием - если он выводит HLL, это декомпиляция.