C# 很好地处理COM接口(MATLAB)缺少的引用
我有一个参考MATLAB COM接口的VS2013 C#项目。应用程序90%的功能与MATLAB无关,我希望能够在MATLAB不可用的环境中编译和运行。期望的行为是:C# 很好地处理COM接口(MATLAB)缺少的引用,c#,matlab,C#,Matlab,我有一个参考MATLAB COM接口的VS2013 C#项目。应用程序90%的功能与MATLAB无关,我希望能够在MATLAB不可用的环境中编译和运行。期望的行为是: 构建,而不管引用是否存在(抛出警告) 如果MATLAB不可用,如果用户试图执行MATLAB特定的功能,请打印一条消息,但这不应该是致命的 我的第一个直觉是对不同的构建配置使用预处理器指令,但我希望避免这种情况,因为在设置连续集成和测试等时,它会变得混乱 所以我试着思考一下: try { var matlab = Activ
- 构建,而不管引用是否存在(抛出警告)
- 如果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相关单元测试/检测器中,我只需分多个步骤进行:
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
或手写反射(做与dynamic相同的事情,但控制程度更高,在较旧的.NET版本中也能工作)
工作完成后,你应该释放它们,所有的。在根COM对象中包括由方法返回(创建)的对象。(除了memleaks之外,释放父代而非其子代会导致单元测试引擎冻结,令人讨厌)
谢谢还有很好的建议。现在,我也将丑陋封装在mapper类中。修复的关键是使用Type.GetTypeFromProgID和泛型CreateInstance方法,而不是CreateComInstanceFrom。@user102569只是不要忘记处理对象。我认为使用mapper with将非常适合这里(COM对象毕竟是本机资源)。
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);
}
public static void DisposeCOM(dynamic obj)
{
if (obj != null)
{
Marshal.ReleaseComObject(obj);
}
}