C# コードの一部を、COM を介してあらゆる種類の実装と対話させる必要があります。
この統合をユーザーが簡単に行えるようにするために、相互作用するインターフェイスを IDL に (関連する既存の DLL の一部として、ただしコクラスや実装は含めずに) 含め、Tlbimp を実行して型定義を作成することで C# コードに組み込みました。
C# を実装し、Windows レジストリ情報に基づいて COM オブジェクトを作成し、そのオブジェクトを必要なインターフェイスにキャストしました。
次に、別のプロジェクトでインターフェイスの C# 実装を作成し、登録しました。メイン プログラムはテスト COM オブジェクトを正しく作成しますが、インターフェイスへのキャストに失敗します (C# 'as' を使用すると null オブジェクトを取得し、明示的なキャストの InvalidCastException を取得します)。
インターフェイスがテストオブジェクトによって実装されていると識別されない理由を誰かが示唆できますか?
これは IDL のインターフェイス定義です (VS 2005 で C++ でコンパイル):
[
object,
uuid(B60C546F-EE91-48a2-A352-CFC36E613CB7),
dual,
nonextensible,
helpstring("IScriptGenerator Interface"),
pointer_default(unique)
]
interface IScriptGenerator : IDispatch{
[helpstring("Init the Script generator")]
HRESULT Init();
[helpstring("General purpose error reporting")]
HRESULT GetLastError([out] BSTR *Error);
};
これは、Tlbimp によって C# 用に作成されたスタブです。
[TypeLibType(4288)]
[Guid("B60C546F-EE91-48A2-A352-CFC36E613CB7")]
public interface IScriptGenerator
{
[DispId(1610743813)]
void GetLastError(out string Error);
[DispId(1610743808)]
void Init();
}
これはメインの C# コードの一部であり、その ProgID によって COM オブジェクトを作成し、それを IScriptGenerator インターフェイスにキャストします。
public ScriptGenerator(string GUID)
{
Type comType = Type.GetTypeFromProgID(GUID);
object comObj = null;
if (comType != null)
{
try
{
comObj = Activator.CreateInstance(comType);
}
catch (Exception ex)
{
Debug.Fail("Cannot create the script generator COM object due to the following exception: " + ex, ex.Message + "\n" + ex.StackTrace);
throw ex;
}
}
else
throw new ArgumentException("The GUID does not match a registetred COM object", "GUID");
m_internalGenerator = comObj as IScriptGenerator;
if (m_internalGenerator == null)
{
Debug.Fail("The script generator doesn't support the required interface - IScriptGenerator");
throw new InvalidCastException("The script generator with the GUID " + GUID + " doesn't support the required interface - IScriptGenerator");
}
}
これは C# コードの実装で、機能していることをテストします (実際には機能していません)。
[Guid("EB46E31F-0961-4179-8A56-3895DDF2884E"),
ProgId("ScriptGeneratorExample.ScriptGenerator"),
ClassInterface(ClassInterfaceType.None),
ComSourceInterfaces(typeof(SOAAPIOLELib.IScriptGeneratorCallback))]
public class ScriptGenerator : IScriptGenerator
{
public void GetLastError(out string Error)
{
throw new NotImplementedException();
}
public void Init()
{
// nothing to do
}
}