我有一个引用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相关单元测试/检测器中,我只是分多个步骤进行:
- 查找COM类型 从类型创建COM对象
- 调用方法。
- 释放所有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);
}
}