我正在使用Invoke对支持IDispatch的旧COM对象进行后期绑定。这似乎是必要的,因为.NET的Type.GetMethod Type.InvokeMember似乎不适用于这些对象。
以下代码适用于从对象获取属性,调用者将属性名称作为字符串传递,以获取具有后期绑定的属性值。该类在其构造函数中获取一个对象,并将this.idisp(和this.lcid)设置为该对象的接口指针(Critiques welcome!)
public object InvokeGet(string propertyName)
{
int id = GetDispID(propertyName);
IntPtr[] pArgErr = default(IntPtr[]);
object pVarResult;
System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams = default(System.Runtime.InteropServices.ComTypes.DISPPARAMS);
System.Runtime.InteropServices.ComTypes.EXCEPINFO pExcepInfo = default(System.Runtime.InteropServices.ComTypes.EXCEPINFO);
Guid guid = new Guid();
int result = this.idisp.Invoke(id, ref guid, (uint)this.lcid,
(ushort)System.Runtime.InteropServices.ComTypes.INVOKEKIND.INVOKE_PROPERTYGET,
ref pDispParams, out pVarResult, ref pExcepInfo, pArgErr);
if (result != 0)
{
throw new ArgumentException(string.Format("Error invoking property: {0}. COM error code is {1}", propertyName, result));
}
return pVarResult;
}
我现在正在尝试编写等效的setter,即
public void InvokeSet(string propertyName, object newValue)
但是我不知道如何用C#打包Dispatch参数。
即。如何设置结构:
System.Runtime.InteropServices.ComTypes.DISPPARAMS
我知道我需要从托管对象创建一个非托管变体来编组。有什么建议怎么做?
答案 0 :(得分:1)
我知道晚会很晚,但是我找到了答案。
// Create the DISPPARAMS struct
var pDispParams= default(System.Runtime.InteropServices.ComTypes.DISPPARAMS);
// Set the number of unnamed parameters
pDispParams.cArgs = 1;
// Marshal a value to a variant
int value = 10;
IntPtr pVariant = Marshal.AllocCoTaskMem(16); // Default VARIANT size
Marshal.GetNativeVariantForObject(value, pVariant);
// Set the unnamed parameter arguments
pDispParams.rgvarg = pVariant;
// Call the IDispatch.Invoke
int result = this.idisp.Invoke(id, ref guid, (uint)this.lcid,
(ushort)System.Runtime.InteropServices.ComTypes.INVOKEKIND.INVOKE_PROPERTYGET,
ref pDispParams, out pVarResult, ref pExcepInfo, pArgErr);
我很难弄清楚如何在C#中编组变体。我发现this article本质上回答了我所有的悬而未决的问题,也回答了你的问题。
希望这仍然可以对某人有所帮助。