我正在使用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
获取一个表示默认值的对象,但这会因致命错误而失败...
答案 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_FOPT
和PARAMFLAG_FHASDEFAULT
,就可以从paramDesc.pPARAMDescEx
中读取信息。
但是根据@Hans的答案,这实际上是PARAMDESCEX
而不是PARAMDESC
,因此我感到困惑。