如何在不生成异常的情况下检查COM属性或方法是否存在?

4
我正在处理一些遗留代码,它创建了一个字符串列表,其中包含属性和/或方法名称,并尝试将这些属性或方法应用于COM对象。不能保证COM对象的属性或方法存在,而且我不知道它是属性还是方法。
目前,如果属性或方法不存在,它会被捕获为COM异常。这会导致性能下降。我正在尝试找到一种方法,在尝试应用属性或方法之前检查COM对象中是否存在属性或方法,而不生成异常。
使用GetType返回类型System.com_object。在System.com_object上使用GetProperty无效,因为这是确切的运行时类型,而不是它派生自的类型。相反,我必须使用InvokeMember,如果成员不存在,则会创建异常。有没有更好的方法来解决这个问题?
我目前在.NET 3.5中工作。迁移到.NET 4目前不是一个选项,但如果新的语言特性提供了更好的解决方案,我仍然对.NET 4中的解决方案感兴趣。
public static bool CheckIfComPropertyOrMethodExists<T1>(T1 objectToCheck, string propertyOrMethodName)
{
    if (CheckIfComPropertyExists(objectToCheck, propertyOrMethodName) == false & CheckIfComMethodExists(objectToCheck, propertyOrMethodName) == false) {
        return false;
    }
    {
        return true;
    }
}

public static bool CheckIfComPropertyExists<T1>(T1 objectToCheck, string propertyName)
{
    return objectToCheck.GetType().InvokeMember(propertyName, BindingFlags.GetProperty, null, objectToCheck, null) != null;
}

public static bool CheckIfComMethodExists<T1>(T1 objectToCheck, string methodName)
{
    return objectToCheck.GetType().GetMethod(methodName, BindingFlags.Public | BindingFlags.Instance) != null;
}

迄今为止有用的文章

如何检查对象是否具有某个方法/属性?

从C#调用IDispatch COM接口的成员

http://msdn.microsoft.com/en-us/library/aa909091.aspx

在C#中实现IDispatch

http://msdn.microsoft.com/en-us/magazine/dd347981.aspx

关于COM对象的反射


2
不要忘记过滤掉“FormatDrive”方法。 - Hans Passant
1个回答

1

很可能COM类也实现了IDispatch接口。然后,您可以使用它的GetIDsOfNames来检查类中是否存在成员。

这里有人从C#中调用它:

从C#调用IDispatch COM接口的成员


谢谢你的回答。我认为GetIDsOfNames会解决这个问题。我很快就会接受你的答案。我想知道你是否介意用一个例子来扩展你的答案,因为我很难理解https://dev59.com/w13Ua4cB1Zd3GeqP9BBF。我正在尝试访问Microsoft.Office.Interop.Excel的成员。如果我不知道应用GetIDsOfNames的类的基础类型,我该如何为一个类获取GetIDsOfNames?我只有一个System.com_object。那可能是Microsoft.Office.Interop.Excel namspce中的任何类型。 - dior001
1
你只需要将COM对象转换为IDispatch类型,无论对象是什么类型,它都一定实现了IDispatch接口。 - Wiktor Zychla
如果成员不存在,GetIDsofNames会抛出DISP_E_UNKNOWNNAME COM异常。这意味着我仍然面临着同样的性能问题。有没有什么办法可以避免抛出异常呢?我尝试了以下方法http://stackoverflow.com/questions/11665813/object-of-type-system-int32-cannot-be-converted-to-type-system-uint32,但没有成功。 - dior001
2
(六年后...)您可以使用[PreserveSig]属性标记GetIdsOfNames,让它直接返回HRESULT而不是为错误情况引发异常。 - Govert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接