【发布时间】:2017-11-27 08:52:12
【问题描述】:
我有一个用于一些简单数学实用程序的 COM 对象。其中,它导出 2 个接口 - IDL 如下:
interface IUnivariateFunction : IDispatch
{
HRESULT evaluate([in] double a, [out, retval] double* b);
};
interface IOneDimSolver : IDispatch
{
HRESULT Solve([in] double min, [in] double max, [in] double targetAccuracy, [in] LONG maxIterations, [in] IUnivariateFunction* function, [out, retval] double* result);
};
然后IOneDimSolver的实现是:
coclass Brent
{
[default] interface IOneDimSolver;
};
如果我想在 C# 中使用这个对象并且我有可用的 TypeLibrary,那么使用这个功能非常容易——我可以实现一些函数来解决:
public class CalculatePi : IUnivariateFunction
{
public double evaluate(double x)
{
return x - Math.PI;
}
}
然后使用它:
var brent = new Brent();
var result = brent.Solve(-10.0, 10.0, 1E-10, 100, new CalculatePi());
这很好用,所以没有问题。但是,我还想证明我可以将它与后期绑定一起使用(此时几乎纯粹用于学术目的)。
var brent = Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")));
var result = brent.GetType().InvokeMember("Solve", BindingFlags.InvokeMethod, null, brent, new object[] { -10.0, 10.0, 1E-10, 100, new CalculatePi() });
看起来brent 对象创建成功,但对InvokeMember 的调用失败并显示消息{"Specified cast is not valid."}
我猜CalculatePi 的类型与 COM IDispatch 机器所期望的不兼容,但我只是不确定如何使其工作。任何帮助都会很棒!
【问题讨论】:
-
首先,您可以使用
dynamic关键字与COM 后期绑定,它更容易,如dynamic brent = /*create instance*/; var result brent.Solve(-10.0, 10.0, 1E-10, 100, new CalculatePi());。如果这仍然不起作用,IDispatch 是如何实现的? IOneDimSolver 接口可能没用,后期绑定只会使用 IDispatch。 -
您说得对,将其创建为
dynamic会更好!不幸的是,我得到了完全相同的错误 - 我会考虑 IDispatch,我不完全确定接下来要尝试什么。 -
你这个绝对的巫师@HansPassant,这正是问题所在!非常感谢!如果您想将其发布为答案,我很乐意接受:)
标签: c# com com-interop idispatch