如何从PARAMDESC获取默认值

时间:2013-12-16 11:06:38

标签: c# com interop

我正在使用ITypeInfo接口来获取有关COM对象及其成员的信息(以便构建某种反射API)。读取类型和成员(及其参数)工作正常,但我不知道如何访问参数的默认值。这就是我的......

...

PARAMDESC paramDesc = elemDesc.desc.paramdesc;

object defaultValue = null;
PARAMFLAG paramFlags = paramDesc.wParamFlags;
bool hasDefaultValue = (paramFlags & PARAMFLAG.PARAMFLAG_FHASDEFAULT) == PARAMFLAG.PARAMFLAG_FHASDEFAULT;
if (hasDefaultValue && paramDesc.lpVarValue != IntPtr.Zero)
{
    defaultValue = null; // TODO: get value from paramDesc.lpVarValue
}

...

我检查wParamFlags字段;如果参数具有默认值且lpVarValue字段具有有效指针,我想读取该值。我假设lpVarValue指向本机COM变体,所以我尝试使用Marshal.GetObjectForNativeVariant获取一个表示默认值的对象,但这会因致命错误而失败...

2 个答案:

答案 0 :(得分:2)

他们在PARAMDESC.lpVarValue上使用了一个快捷方式,因为指针类型很难在托管代码中声明。它实际上是一个指向PARAMDESCEX的指针,在oaidl.idl中声明如下:

typedef struct tagPARAMDESCEX {
    ULONG cBytes;               /* size of this structure */
    VARIANTARG varDefaultValue; /* default value of this parameter */
} PARAMDESCEX, * LPPARAMDESCEX;

所以,是的,使用Marshal.GetObjectForNativeVariant()是获取 varDefaultValue 字段的好方法。但是,您必须添加以跳过 cBytes 字段。这需要添加4来跳过ULONG,再加上4来跳过字段之间的填充。所以使用类似的东西:

PARAMDESC pd = ...;
object defValue = null;
if ((pd.wParamFlags & 0x20) != 0) {
    IntPtr defptr = new IntPtr((long)pd.lpVarValue + 8);
    defValue = Marshal.GetObjectForNativeVariant(defptr);
}

答案 1 :(得分:0)

PARAMFLAG_FHASDEFAULT的{​​{3}}说:

  

参数已定义默认行为。如果设置了wParamFlags的PARAMFLAG_FOPT和PARAMFLAG_FHASDEFAULT位,则pPARAMDescEx字段包含指向VARIANT的指针,该指针描述此参数的默认值。

因此,只要设置了PARAMFLAG_FOPTPARAMFLAG_FHASDEFAULT,就可以从paramDesc.pPARAMDescEx中读取信息。


但是根据@Hans的答案,这实际上是PARAMDESCEX而不是PARAMDESC,因此我感到困惑。

相关问题