处理丢失的引用COM接口(MATLAB)很好



我有一个引用MATLAB COM接口的VS2013 c#项目。该应用程序所做的90%与MATLAB无关,我希望能够在MATLAB不可用的环境中编译和运行。期望的行为是:

  • 构建,不管引用是否存在(抛出警告)。
  • 如果MATLAB不可用,如果用户试图执行MATLAB特定功能,则打印消息,但不应该是致命的。

我的第一反应是使用不同构建配置的预处理器指令,但我想避免这样做,因为它会在设置持续集成和测试等时变得混乱。

所以我试着反思一下:

try
{
  var matlab = Activator.CreateComInstanceFrom("appname.exe", "MLApp.MLApp").Unwrap();
}
catch
{
  //message
}

抛出MissingMethodException(即无法找到构造函数)。当MATLAB存在时,这工作得很好:

     var matlab = new MLApp.MLApp();

欢迎有新想法,提前感谢!

编辑:

请参阅下面的详细答案,但对于那些寻找快速测试代码的人来说,这里是对我有用的。

        var Matlab_t = Type.GetTypeFromProgID("Matlab.Autoserver");
        if (Matlab_t != null)
            matlab = Activator.CreateInstance(Matlab_t);
        else
            MessageBox.Show("Matlab installation not found.n");

在我的COM相关单元测试/检测器中,我只是分多个步骤进行:

  1. 查找COM类型
  2. 从类型创建COM对象
  3. 调用方法。
  4. 释放所有COM对象。

在你的情况下,我建议写一个映射器类,把所有这些COM的丑陋隐藏在抽象层下。(我只需要那些帮助来测试我写的COM库,所以它是相反的)

类型。当没有找到type时,GetTypeFromProgID不会抛出异常,而是简单地返回null

    public static object GetComObject(string typeName)
    {
        Type ComType;
        ComType = Type.GetTypeFromProgID(typeName);
        if (ComType == null)
        {
            //COM type not found
        }
        // Create an instance of your COM Registered Object.
        return Activator.CreateInstance(ComType);
    }

当对象创建(或不创建)时,我使用dynamic或手写反射(做与动态相同的事情,但具有更高的控制程度,并且也适用于较旧的。net版本)。

    public static object CallFunction(string method, string typeName, params object[] args)
    {
        Type ComType;
        object ComObject;
        ComType = Type.GetTypeFromProgID(typeName);
        if (ComType == null)
        {
            //COM type not found
        }
        // Create an instance of your COM Registered Object.
        ComObject = Activator.CreateInstance(ComType);
        // Call the Method and cast return to whatever it should be.
        return ComType.InvokeMember(method, BindingFlags.InvokeMethod, null, ComObject, args);
    }

工作结束后,你应该释放他们,所有的人。在根COM对象中包含由方法返回(由方法创建)的对象。(释放父引擎,但不释放子引擎,除了memleaks,还会导致Unit Test引擎冻结,真讨厌)

    public static void DisposeCOM(dynamic obj)
    {
        if (obj != null)
        {
            Marshal.ReleaseComObject(obj);
        }
    }

相关内容

最新更新