C#支持指针,尤其是与COM交互的接口指针。Marshal类可以帮你完成任何事。
如果只是简单的使用IDispatch,用MarshalAsAttribute就可以了:In COM/IDL:
HRESULT FunctionNeedIDispatch([in] IDispatch* disp);
HRESULT FunctionRetIDispatch([out, retval] IDispatch** pdisp);In C#:
void FunctionNeedIDispatch([MarshalAs(UnmanagedType.IDispatch)] Object o);
[MarshalAs(UnmanagedType.IDispatch)] 
Object FunctionRetIDispatch();
...
当然,这也要看你具体使用IDispatch的场合,总的来说,你cast成某个CoClass或者其它的Interface (用tlbimp声明的)。

解决方案 »

  1.   

    谢谢你的回复。
    你提供的方法,只是把IDispatch压进一个对象中。
    并且该对象提供获取IDispatch指针的方法而已。
    ----------
    我希望的不是C#代码作为IDispatch传递的媒介。
    而是想直接用C#调用IDispatch::Invoke
    例如我希望用C#来实现下面代码:STDMETHODIMP CTest::LoadXMLDocument(/*[in]*/BSTR szURL,/*[out,retval]*/LPDISPATCH *lplpDisp)
    {
    // TODO: Add your implementation code here
    HRESULT hres;
    CLSID clsidXMLDOM; hres=CLSIDFromProgID(L"Microsoft.XMLDOM",&clsidXMLDOM);
    if(FAILED(hres))
    return hres; LPDISPATCH lpDisp;
    hres=CoCreateInstance(clsidXMLDOM,NULL,CLSCTX_INPROC_SERVER,IID_IDispatch,(LPVOID*)&lpDisp);
    if(FAILED(hres))
    return hres;

    BSTR rgszNames[]={L"async",L"load"};
    DISPID Dispid;
    DISPPARAMS dps;
    VARIANT params[1];
    dps.cArgs=1;
    dps.cNamedArgs=0;
    dps.rgdispidNamedArgs=NULL;
    dps.rgvarg=params;
    VARIANT vres;
    EXCEPINFO ei;
    UINT rgui[2]; //xmldom.async=false;
    hres=lpDisp->GetIDsOfNames(IID_NULL,&rgszNames[0],1,GetSystemDefaultLCID(),&Dispid);
    if(FAILED(hres))
    {
    lpDisp->Release();
    return hres;
    }
    params[0].vt=VT_BOOL;
    params[0].boolVal=FALSE;
    hres=lpDisp->Invoke(Dispid,IID_NULL,GetSystemDefaultLCID(),DISPATCH_PROPERTYPUT,&dps,&vres,&ei,rgui);
    if(FAILED(hres))
    {
    lpDisp->Release();
    return hres;
    } //xmldom.load(szURL);
    hres=lpDisp->GetIDsOfNames(IID_NULL,&rgszNames[1],1,GetSystemDefaultLCID(),&Dispid);
    if(FAILED(hres))
    {
    lpDisp->Release();
    return hres;
    }
    params[0].vt=VT_BSTR|VT_BYREF;
    params[0].pbstrVal=&szURL;
    hres=lpDisp->Invoke(Dispid,IID_NULL,GetSystemDefaultLCID(),DISPATCH_METHOD,&dps,&vres,&ei,rgui);
    if(FAILED(hres))
    {
    lpDisp->Release();
    return hres;
    } *lplpDisp=lpDisp;
    return S_OK;
    }
      

  2.   

    如果你确信需要使用的是XMLDOM组件的话,TlbImp.exe已经足够了。
    tlbimp c:\winnt\system32\msxml3.dll然后你的目录下会有一个MSXML2.dll,用ildasm查以下,还用Idispatch吗?:)XMLDocument doc = new XMLDocument();
    doc.async = ...;
      

  3.   

    不是啊。。
    我的意思是,
    如过我有一个XML脚本如下:
    <var name="url" type="string">
    <set-value><value type="string">http://www.host.com/thexml.xml</value></set-value>
    </var>
    <var name="test" type="object">
    <set-value><active-x-object>Microsoft.XMLDOM</active-x-object></set-value>
    </var>
    <set-property>
    <caller><getvar name="test" /></caller>
    <property name="async"></property>
    <value type="boolean">false</value>
    </set-property>
    <call-method>
    <caller>
    <get-var name="test" />
    </caller>
    <method name="load">
    </method>
    <arguments>
    <param type="string"><get-var name="url" /></param>
    </arguments>
    </call-method>
    我要用这个脚本来处理一些事务(就象游戏脚本一样)
    而且我要调用哪个Automation的东西都不知道。
    所以我只能用IDispatch
      

  4.   

    原来是要用late binding,那就没办法了:p,这可是C#的大弱项。
    当然,理论上说reflection可以办到,但是... #@$@#不过在.NET的范围内还是可以解决的,VB.NET比C#的优点之一就是late binding,所以只要用vb.net就好了,不用C++介入,编程也方便许多。
    可以用VB.NET编译个独立的DLL,吧这部分功能封装起来...
    VB.NET我也不是很熟,这是MSDN上的一个例子:
    Dim xlApp As Object
    xlApp = CreateObject("Excel.Application")
    MsgBox(xlApp.Version)
    ...
      

  5.   

    我尝试了一下,并不麻烦,而且VB.NET编译的Assembly DLL与C#的互操作性更好些,我想。
    VB.NET支持LateBinding是由于它的Runtime (Microsft.VisualBasic)中实现了很多附加的功能,这里是一个完整的程序:Option Explicit On 
    Option Strict OffImports System
    Imports Microsoft.VisualBasicModule Hello
       Sub Main()
          Dim obj As Object
          obj = CreateObject("Word.Application")
          Console.WriteLine(obj.Version)
       End Sub
    End Module我不确定是否可以在C#里面using Microsoft.VisualBasic,然后用Late Binding。