关于 Activator.CreateInstance的一个问题

时间:2021-01-22 00:59:19
  object comObj = Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024")));
                object obj = comObj.GetType().InvokeMember(_methodName, System.Reflection.BindingFlags.InvokeMethod, null, comObj, param);

在实例化的这个对象以后,我应该怎么判断这个Guid("30FB1E22-B498-4B62-8B26-98BA61176024"))类里面到底有没有_methodName这个方法啊?

32 个解决方案

#1


comObj.GetType().GetMember(_methodName)

#2


反射呗
var type = Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"));
var method = type.GetMethod(_methodName, 是否区分大小写);
if(method != null)
{
         method.Invoke(XXX)
}

#3


引用 2 楼 dongxinxi 的回复:
反射呗
var type = Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"));
var method = type.GetMethod(_methodName, 是否区分大小写);
if(method != null)
{
         method.Invoke(XXX)
}

method值一直为空额,哪怕里面有那个方法也是

#4



引用 1 楼 feiyun0112 的回复:
comObj.GetType().GetMember(_methodName)

不行啊,判断不出来啊,是否有这个方法

#5


引用 2 楼 dongxinxi 的回复:
反射呗
var type = Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"));
var method = type.GetMethod(_methodName, 是否区分大小写);
if(method != null)
{
         method.Invoke(XXX)
}

   //通过GUID获取到DVBusiUtilCalClass类
             var type=Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"));
                //查看是否有—_methodName这个方法
                var method = type.GetMethod(_methodName);
                如果在DVBusiUtilCalClass没有找到这个方法,那么去创建DVBusiUtilPreClass的实例
                if (method == null)
                {
                   type = Type.GetTypeFromCLSID(new Guid("592703AB-CF61-425D-9ACD-A0938E451AEA"));
                }

#6


引用 3 楼 u013063561 的回复:
Quote: 引用 2 楼 dongxinxi 的回复:

反射呗
var type = Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"));
var method = type.GetMethod(_methodName, 是否区分大小写);
if(method != null)
{
         method.Invoke(XXX)
}

method值一直为空额,哪怕里面有那个方法也是

 type有值没?

#7


引用 5 楼 u013063561 的回复:
Quote: 引用 2 楼 dongxinxi 的回复:

反射呗
var type = Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"));
var method = type.GetMethod(_methodName, 是否区分大小写);
if(method != null)
{
         method.Invoke(XXX)
}

   //通过GUID获取到DVBusiUtilCalClass类
             var type=Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"));
                //查看是否有—_methodName这个方法
                var method = type.GetMethod(_methodName);
                如果在DVBusiUtilCalClass没有找到这个方法,那么去创建DVBusiUtilPreClass的实例
                if (method == null)
                {
                   type = Type.GetTypeFromCLSID(new Guid("592703AB-CF61-425D-9ACD-A0938E451AEA"));
                }

type有值,但是method每值,一直是空

#8


引用 6 楼 lovelj2012 的回复:
Quote: 引用 3 楼 u013063561 的回复:

Quote: 引用 2 楼 dongxinxi 的回复:

反射呗
var type = Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"));
var method = type.GetMethod(_methodName, 是否区分大小写);
if(method != null)
{
         method.Invoke(XXX)
}

method值一直为空额,哪怕里面有那个方法也是

 type有值没?

type一直没值!~~

#9


comObj.GetType().GetMembers()
看有哪些MemberName

#10


引用 6 楼 lovelj2012 的回复:
Quote: 引用 3 楼 u013063561 的回复:

Quote: 引用 2 楼 dongxinxi 的回复:

反射呗
var type = Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"));
var method = type.GetMethod(_methodName, 是否区分大小写);
if(method != null)
{
         method.Invoke(XXX)
}

method值一直为空额,哪怕里面有那个方法也是

 type有值没?

type有值 但是method一直为空。。

#11


引用 8 楼 u013063561 的回复:
Quote: 引用 6 楼 lovelj2012 的回复:

Quote: 引用 3 楼 u013063561 的回复:

Quote: 引用 2 楼 dongxinxi 的回复:

反射呗
var type = Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"));
var method = type.GetMethod(_methodName, 是否区分大小写);
if(method != null)
{
         method.Invoke(XXX)
}

method值一直为空额,哪怕里面有那个方法也是

 type有值没?

type一直没值!~~

type一直没值,那执行GetMethod肯定反射不来东东啊
是不是你的GUID搞错了

#12


引用 9 楼 feiyun0112 的回复:
comObj.GetType().GetMembers()
看有哪些MemberName

{System.String ToString()}
System.Object GetLifetimeService
System.Runtime.Remoting.ObjRef CreateObjRef(System.Type)
等等一共6个值!~

#13


引用 11 楼 lovelj2012 的回复:
Quote: 引用 8 楼 u013063561 的回复:

Quote: 引用 6 楼 lovelj2012 的回复:

Quote: 引用 3 楼 u013063561 的回复:

Quote: 引用 2 楼 dongxinxi 的回复:

反射呗
var type = Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"));
var method = type.GetMethod(_methodName, 是否区分大小写);
if(method != null)
{
         method.Invoke(XXX)
}

method值一直为空额,哪怕里面有那个方法也是

 type有值没?

type一直没值!~~

type一直没值,那执行GetMethod肯定反射不来东东啊
是不是你的GUID搞错了

type有值,method没值!~一直是空

#14


GetMethod用法,是不是2#搞错了。
照着msdn的例子用
http://msdn.microsoft.com/zh-cn/library/6hy0h0z1(v=vs.100).aspx

#15


引用 14 楼 lovelj2012 的回复:
GetMethod用法,是不是2#搞错了。
照着msdn的例子用
http://msdn.microsoft.com/zh-cn/library/6hy0h0z1(v=vs.100).aspx

 额,这个getMethod是调用方法啊?我要的只查询出这个方法是否存在于这个类中!· = = 

#16



  args[0] = "DVC_CutImgmethod";
                args[1] = @"11";
                args[2] = "1";
                args[3] = "2";
                //如果没有数据的话,直接return
                if (args.Length == 0)
                {
                    return;
                }
                //获取方法名
                string _methodName = args[0];
                //创建list集合用于保存参数
                List<object> list = new List<object>();

                for (int i = 1; i < args.Length; i++)
                {
                    list.Add(args[i]);
                }
                //转换成object数组
                object[] param = list.ToArray();
            
                //通过GUID获取到DVBusiUtilCalClass类
                var type=Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"));
                //查看是否有—_methodName这个方法
                var method = type.GetMethod(_methodName);
               MethodInfo[] sss=  type.GetMethods();
                //如果在DVBusiUtilCalClass没有找到这个方法,那么去创建DVBusiUtilPreClass的实例
                if (method == null)
                {
                    type = Type.GetTypeFromCLSID(new Guid("592703AB-CF61-425D-9ACD-A0938E451AEA"));
                }
                object comObj = Activator.CreateInstance(type);
                //创建类型实例
                //object comObj = Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024")));
                //MemberInfo[] vvv = comObj.GetType().GetMembers();
                //int ddd = vvv.Length;
                //if (comObj.GetType().GetMember(_methodName)==null)
                //{
                //    comObj = Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("592703AB-CF61-425D-9ACD-A0938E451AEA")));
                //}
                //获取返回值
                object result = comObj.GetType().InvokeMember(_methodName, System.Reflection.BindingFlags.InvokeMethod, null, comObj, param);
               
                Console.WriteLine(Convert.ToInt32(result));

整体代码。。

#17


引用 9 楼 feiyun0112 的回复:
comObj.GetType().GetMembers()
看有哪些MemberName

没用啊版主,找不到那个guid类当中的那些方法!~~~

#18


引用 15 楼 u013063561 的回复:
Quote: 引用 14 楼 lovelj2012 的回复:

GetMethod用法,是不是2#搞错了。
照着msdn的例子用
http://msdn.microsoft.com/zh-cn/library/6hy0h0z1(v=vs.100).aspx

 额,这个getMethod是调用方法啊?我要的只查询出这个方法是否存在于这个类中!· = = 

无语了~~~

GetMethod从类型里面反射出某个方法是否存在
类型.GetMethod返回结果不是null,就证明这个类型中存在这个方法了

#19


引用 18 楼 lovelj2012 的回复:
Quote: 引用 15 楼 u013063561 的回复:

Quote: 引用 14 楼 lovelj2012 的回复:

GetMethod用法,是不是2#搞错了。
照着msdn的例子用
http://msdn.microsoft.com/zh-cn/library/6hy0h0z1(v=vs.100).aspx

 额,这个getMethod是调用方法啊?我要的只查询出这个方法是否存在于这个类中!· = = 

无语了~~~

GetMethod从类型里面反射出某个方法是否存在
类型.GetMethod返回结果不是null,就证明这个类型中存在这个方法了

不是吧?我看csdn里面是写的方法名加参数,得到的是返回结果额?
但是我那个类中确实存在那个方法。method还是为空!~

#20


如果那个方法没有重载过,是不需要指定参数及类型的,你确定总共就6个成员吗?

那样就不是GetMethod的问题了,反射出来的都是托管类型的成员,不是COM接口的成员
当COM类实现了IDispatch意味着将延迟绑定类型
IDispatch::GetIDsOfNames 方法,Visual C# 可以询问对象支持哪些方法和属性
IDispatch::Invoke 方法允许 Visual C# 调用这些方法和属性。

不过NET封装了现成的

try
{
          var type = Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"));
          type.InvokeMember(_methodName, BindingFlags.InvokeMethod, null, comObj, 参数列表);
}
catch(System.MissingMethodException exp)
{
          方法未找到
}


找到了一篇C++通过IDispatch查询并调用的文章,你可以看看,
http://blog.csdn.net/csfreebird/article/details/463031

#21


Com对象在.net这边的类型其实是System.__ComObject,所以通过GetMethods这样反射是取不到信息的。
必须使用Com的IDispatch接口上面的GetIDsOfNames才能判断

#22


引用 20 楼 dongxinxi 的回复:
如果那个方法没有重载过,是不需要指定参数及类型的,你确定总共就6个成员吗?

那样就不是GetMethod的问题了,反射出来的都是托管类型的成员,不是COM接口的成员
当COM类实现了IDispatch意味着将延迟绑定类型
IDispatch::GetIDsOfNames 方法,Visual C# 可以询问对象支持哪些方法和属性
IDispatch::Invoke 方法允许 Visual C# 调用这些方法和属性。

不过NET封装了现成的

try
{
          var type = Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"));
          type.InvokeMember(_methodName, BindingFlags.InvokeMethod, null, comObj, 参数列表);
}
catch(System.MissingMethodException exp)
{
          方法未找到
}


找到了一篇C++通过IDispatch查询并调用的文章,你可以看看,
http://blog.csdn.net/csfreebird/article/details/463031

那我应该怎么办呢???

#24


引用 23 楼 github_22161131 的回复:
可以使用这里面提供的代码: http://www.codeproject.com/Articles/523417/Reflection-with-IDispatch-based-COM-objects

不该DLL文件能实现吗?只要能判断出这个方法到底存在不存在就ok

#25


引用 23 楼 github_22161131 的回复:
可以使用这里面提供的代码: http://www.codeproject.com/Articles/523417/Reflection-with-IDispatch-based-COM-objects

你给的这个打不开!~~网站

#26


其实思路也不复杂
1. 定义一个IDispatch
2. 获取IDispatch指针对象
3.利用IDispatch.GetIDsOfNames来判断成员是否存在(当然先要用GetTypeInfoCount(out count)判断是否具有类型信息)

HRESULT STDMETHODCALLTYPE GetIDsOfNames(
            /* [in] */ REFIID riid,
            /* [size_is][in] */ LPOLESTR *rgszNames,
            /* [in] */ UINT cNames,
            /* [in] */ LCID lcid,
/* [size_is][out] */ DISPID *rgDispId)
 
IDispatch接口的属性实质上是方法,方法也就是成员函数,IDispatch接口把所有成员函数的入口地址放入到一个数组中,并且内部组织了一个Map,将数组索引和方法名称一一映射。我们常见的DISPID就是这些方法在数组中的索引。如果我们想调用某一个方法,我们就需要DISPID来让我们找到该方法的地址。
    
     参数riid必须为NULL。
     参数rgszNames为字符串数组,第一个字符串为方法或者属性的名称,后续的字符串为参数名称,IDispatch接口的参数也可以有名字。
     参数cNames指定rgszNames数组中字符串的个数。
     参数lcid传递地域标志,同GetTypeInfo方法中的参数。
     参数rgDispId输出一个数组,每个数组成员对应rgszNames中的一个字符串名称。
 
     关于DISPID的进一步说明:
         typedef LONG DISPID;
typedef DISPID MEMBERID;
    
     DISPID小于等于0的值都是有特殊意义的,如下面介绍的----
         /* DISPID reserved to indicate an "unknown" name */
/* only reserved for data members (properties); reused as a method dispid below */
//如果GetIDsOfNames函数找不到与名称相对应的DISPID,返回该值
#define  DISPID_UNKNOWN     ( -1 )

所以当输出参数rgDispId == -1即表示不存在了,上面那个代码里有现成的接口声明,贴给你吧

#27



public static class DispatchUtility
{
#region Private Constants

private const int S_OK = 0; //From WinError.h
private const int LOCALE_SYSTEM_DEFAULT = 2 << 10; //From WinNT.h == 2048 == 0x800

#endregion

#region Public Methods

/// <summary>
/// Gets whether the specified object implements IDispatch.
/// </summary>
/// <param name="obj">An object to check.</param>
/// <returns>True if the object implements IDispatch.  False otherwise.</returns>
public static bool ImplementsIDispatch(object obj)
{
bool result = obj is IDispatchInfo;
return result;
}

/// <summary>
/// Gets a Type that can be used with reflection.
/// </summary>
/// <param name="obj">An object that implements IDispatch.</param>
/// <param name="throwIfNotFound">Whether an exception should be thrown if a Type can't be obtained.</param>
/// <returns>A .NET Type that can be used with reflection.</returns>
/// <exception cref="InvalidCastException">If <paramref name="obj"/> doesn't implement IDispatch.</exception>
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public static Type GetType(object obj, bool throwIfNotFound)
{
RequireReference(obj, "obj");
Type result = GetType((IDispatchInfo)obj, throwIfNotFound);
return result;
}

/// <summary>
/// Tries to get the DISPID for the requested member name.
/// </summary>
/// <param name="obj">An object that implements IDispatch.</param>
/// <param name="name">The name of a member to lookup.</param>
/// <param name="dispId">If the method returns true, this holds the DISPID on output.
/// If the method returns false, this value should be ignored.</param>
/// <returns>True if the member was found and resolved to a DISPID.  False otherwise.</returns>
/// <exception cref="InvalidCastException">If <paramref name="obj"/> doesn't implement IDispatch.</exception>
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public static bool TryGetDispId(object obj, string name, out int dispId)
{
RequireReference(obj, "obj");
bool result = TryGetDispId((IDispatchInfo)obj, name, out dispId);
return result;
}

#region Private Methods

/// <summary>
/// Requires that the value is non-null.
/// </summary>
/// <typeparam name="T">The type of the value.</typeparam>
/// <param name="value">The value to check.</param>
/// <param name="name">The name of the value.</param>
private static void RequireReference<T>(T value, string name) where T : class
{
if (value == null)
{
throw new ArgumentNullException(name);
}
}

/// <summary>
/// Gets a Type that can be used with reflection.
/// </summary>
/// <param name="dispatch">An object that implements IDispatch.</param>
/// <param name="throwIfNotFound">Whether an exception should be thrown if a Type can't be obtained.</param>
/// <returns>A .NET Type that can be used with reflection.</returns>
private static Type GetType(IDispatchInfo dispatch, bool throwIfNotFound)
{
RequireReference(dispatch, "dispatch");

Type result = null;
int typeInfoCount;
int hr = dispatch.GetTypeInfoCount(out typeInfoCount);
if (hr == S_OK && typeInfoCount > 0)
{
// Type info isn't usually culture-aware for IDispatch, so we might as well pass
// the default locale instead of looking up the current thread's LCID each time
// (via CultureInfo.CurrentCulture.LCID).
dispatch.GetTypeInfo(0, LOCALE_SYSTEM_DEFAULT, out result);
}

if (result == null && throwIfNotFound)
{
// If the GetTypeInfoCount called failed, throw an exception for that.
Marshal.ThrowExceptionForHR(hr);

// Otherwise, throw the same exception that Type.GetType would throw.
throw new TypeLoadException();
}

return result;
}

/// <summary>
/// Tries to get the DISPID for the requested member name.
/// </summary>
/// <param name="dispatch">An object that implements IDispatch.</param>
/// <param name="name">The name of a member to lookup.</param>
/// <param name="dispId">If the method returns true, this holds the DISPID on output.
/// If the method returns false, this value should be ignored.</param>
/// <returns>True if the member was found and resolved to a DISPID.  False otherwise.</returns>
private static bool TryGetDispId(IDispatchInfo dispatch, string name, out int dispId)
{
RequireReference(dispatch, "dispatch");
RequireReference(name, "name");

bool result = false;

// Members names aren't usually culture-aware for IDispatch, so we might as well
// pass the default locale instead of looking up the current thread's LCID each time
// (via CultureInfo.CurrentCulture.LCID).
Guid iidNull = Guid.Empty;
int hr = dispatch.GetDispId(ref iidNull, ref name, 1, LOCALE_SYSTEM_DEFAULT, out dispId);

const int DISP_E_UNKNOWNNAME = unchecked((int)0x80020006); //From WinError.h
const int DISPID_UNKNOWN = -1; //From OAIdl.idl
if (hr == S_OK)
{
result = true;
}
else if (hr == DISP_E_UNKNOWNNAME && dispId == DISPID_UNKNOWN)
{
// This is the only supported "error" case because it means IDispatch
// is saying it doesn't know the member we asked about.
result = false;
}
else
{
// The other documented result codes are all errors.
Marshal.ThrowExceptionForHR(hr);
}

return result;
}

#endregion

#region Private Interfaces

/// <summary>
/// A partial declaration of IDispatch used to lookup Type information and DISPIDs.
/// </summary>
/// <remarks>
/// This interface only declares the first three methods of IDispatch.  It omits the
/// fourth method (Invoke) because there are already plenty of ways to do dynamic
/// invocation in .NET.  But the first three methods provide dynamic type metadata
/// discovery, which .NET doesn't provide normally if you have a System.__ComObject
/// RCW instead of a strongly-typed RCW.
/// <para/>
/// Note: The original declaration of IDispatch is in OAIdl.idl.
/// </remarks>
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("00020400-0000-0000-C000-000000000046")]
private interface IDispatchInfo
{
/// <summary>
/// Gets the number of Types that the object provides (0 or 1).
/// </summary>
/// <param name="typeInfoCount">Returns 0 or 1 for the number of Types provided by <see cref="GetTypeInfo"/>.</param>
/// <remarks>
/// http://msdn.microsoft.com/en-us/library/da876d53-cb8a-465c-a43e-c0eb272e2a12(VS.85)
/// </remarks>
[PreserveSig]
int GetTypeInfoCount(out int typeInfoCount);

/// <summary>
/// Gets the Type information for an object if <see cref="GetTypeInfoCount"/> returned 1.
/// </summary>
/// <param name="typeInfoIndex">Must be 0.</param>
/// <param name="lcid">Typically, LOCALE_SYSTEM_DEFAULT (2048).</param>
/// <param name="typeInfo">Returns the object's Type information.</param>
/// <remarks>
/// http://msdn.microsoft.com/en-us/library/cc1ec9aa-6c40-4e70-819c-a7c6dd6b8c99(VS.85)
/// </remarks>
void GetTypeInfo(int typeInfoIndex, int lcid, [MarshalAs(UnmanagedType.CustomMarshaler,
MarshalTypeRef = typeof(System.Runtime.InteropServices.CustomMarshalers.TypeToTypeInfoMarshaler))] out Type typeInfo);

/// <summary>
/// Gets the DISPID of the specified member name.
/// </summary>
/// <param name="riid">Must be IID_NULL.  Pass a copy of Guid.Empty.</param>
/// <param name="name">The name of the member to look up.</param>
/// <param name="nameCount">Must be 1.</param>
/// <param name="lcid">Typically, LOCALE_SYSTEM_DEFAULT (2048).</param>
/// <param name="dispId">If a member with the requested <paramref name="name"/>
/// is found, this returns its DISPID and the method's return value is 0.
/// If the method returns a non-zero value, then this parameter's output value is
/// undefined.</param>
/// <returns>Zero for success. Non-zero for failure.</returns>
/// <remarks>
/// http://msdn.microsoft.com/en-us/library/6f6cf233-3481-436e-8d6a-51f93bf91619(VS.85)
/// </remarks>
[PreserveSig]
int GetDispId(ref Guid riid, ref string name, int nameCount, int lcid, out int dispId);

// NOTE: The real IDispatch also has an Invoke method next, but we don't need it.
// We can invoke methods using .NET's Type.InvokeMember method with the special
// [DISPID=n] syntax for member "names", or we can get a .NET Type using GetTypeInfo
// and invoke methods on that through reflection.
// Type.InvokeMember: http://msdn.microsoft.com/en-us/library/de3dhzwy.aspx
}
                #endregion
}



if (!DispatchUtility.ImplementsIDispatch(obj))
{
         throw new ArgumentException("The object created for " + progId + " doesn't implement IDispatch.");
}

// See if we can get Type info and then do some reflection.
Type dispatchType = DispatchUtility.GetType(obj, false);
if (dispatchType != null)
{
        var hr = DispatchUtility.TryGetDispId(obj, _methodName, out dispId);
        return hr== hr_OK && dispId != -1;
}

#28


引用 27 楼 dongxinxi 的回复:

public static class DispatchUtility
{
#region Private Constants

private const int S_OK = 0; //From WinError.h
private const int LOCALE_SYSTEM_DEFAULT = 2 << 10; //From WinNT.h == 2048 == 0x800

#endregion

#region Public Methods

/// <summary>
/// Gets whether the specified object implements IDispatch.
/// </summary>
/// <param name="obj">An object to check.</param>
/// <returns>True if the object implements IDispatch.  False otherwise.</returns>
public static bool ImplementsIDispatch(object obj)
{
bool result = obj is IDispatchInfo;
return result;
}

/// <summary>
/// Gets a Type that can be used with reflection.
/// </summary>
/// <param name="obj">An object that implements IDispatch.</param>
/// <param name="throwIfNotFound">Whether an exception should be thrown if a Type can't be obtained.</param>
/// <returns>A .NET Type that can be used with reflection.</returns>
/// <exception cref="InvalidCastException">If <paramref name="obj"/> doesn't implement IDispatch.</exception>
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public static Type GetType(object obj, bool throwIfNotFound)
{
RequireReference(obj, "obj");
Type result = GetType((IDispatchInfo)obj, throwIfNotFound);
return result;
}

/// <summary>
/// Tries to get the DISPID for the requested member name.
/// </summary>
/// <param name="obj">An object that implements IDispatch.</param>
/// <param name="name">The name of a member to lookup.</param>
/// <param name="dispId">If the method returns true, this holds the DISPID on output.
/// If the method returns false, this value should be ignored.</param>
/// <returns>True if the member was found and resolved to a DISPID.  False otherwise.</returns>
/// <exception cref="InvalidCastException">If <paramref name="obj"/> doesn't implement IDispatch.</exception>
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public static bool TryGetDispId(object obj, string name, out int dispId)
{
RequireReference(obj, "obj");
bool result = TryGetDispId((IDispatchInfo)obj, name, out dispId);
return result;
}

#region Private Methods

/// <summary>
/// Requires that the value is non-null.
/// </summary>
/// <typeparam name="T">The type of the value.</typeparam>
/// <param name="value">The value to check.</param>
/// <param name="name">The name of the value.</param>
private static void RequireReference<T>(T value, string name) where T : class
{
if (value == null)
{
throw new ArgumentNullException(name);
}
}

/// <summary>
/// Gets a Type that can be used with reflection.
/// </summary>
/// <param name="dispatch">An object that implements IDispatch.</param>
/// <param name="throwIfNotFound">Whether an exception should be thrown if a Type can't be obtained.</param>
/// <returns>A .NET Type that can be used with reflection.</returns>
private static Type GetType(IDispatchInfo dispatch, bool throwIfNotFound)
{
RequireReference(dispatch, "dispatch");

Type result = null;
int typeInfoCount;
int hr = dispatch.GetTypeInfoCount(out typeInfoCount);
if (hr == S_OK && typeInfoCount > 0)
{
// Type info isn't usually culture-aware for IDispatch, so we might as well pass
// the default locale instead of looking up the current thread's LCID each time
// (via CultureInfo.CurrentCulture.LCID).
dispatch.GetTypeInfo(0, LOCALE_SYSTEM_DEFAULT, out result);
}

if (result == null && throwIfNotFound)
{
// If the GetTypeInfoCount called failed, throw an exception for that.
Marshal.ThrowExceptionForHR(hr);

// Otherwise, throw the same exception that Type.GetType would throw.
throw new TypeLoadException();
}

return result;
}

/// <summary>
/// Tries to get the DISPID for the requested member name.
/// </summary>
/// <param name="dispatch">An object that implements IDispatch.</param>
/// <param name="name">The name of a member to lookup.</param>
/// <param name="dispId">If the method returns true, this holds the DISPID on output.
/// If the method returns false, this value should be ignored.</param>
/// <returns>True if the member was found and resolved to a DISPID.  False otherwise.</returns>
private static bool TryGetDispId(IDispatchInfo dispatch, string name, out int dispId)
{
RequireReference(dispatch, "dispatch");
RequireReference(name, "name");

bool result = false;

// Members names aren't usually culture-aware for IDispatch, so we might as well
// pass the default locale instead of looking up the current thread's LCID each time
// (via CultureInfo.CurrentCulture.LCID).
Guid iidNull = Guid.Empty;
int hr = dispatch.GetDispId(ref iidNull, ref name, 1, LOCALE_SYSTEM_DEFAULT, out dispId);

const int DISP_E_UNKNOWNNAME = unchecked((int)0x80020006); //From WinError.h
const int DISPID_UNKNOWN = -1; //From OAIdl.idl
if (hr == S_OK)
{
result = true;
}
else if (hr == DISP_E_UNKNOWNNAME && dispId == DISPID_UNKNOWN)
{
// This is the only supported "error" case because it means IDispatch
// is saying it doesn't know the member we asked about.
result = false;
}
else
{
// The other documented result codes are all errors.
Marshal.ThrowExceptionForHR(hr);
}

return result;
}

#endregion

#region Private Interfaces

/// <summary>
/// A partial declaration of IDispatch used to lookup Type information and DISPIDs.
/// </summary>
/// <remarks>
/// This interface only declares the first three methods of IDispatch.  It omits the
/// fourth method (Invoke) because there are already plenty of ways to do dynamic
/// invocation in .NET.  But the first three methods provide dynamic type metadata
/// discovery, which .NET doesn't provide normally if you have a System.__ComObject
/// RCW instead of a strongly-typed RCW.
/// <para/>
/// Note: The original declaration of IDispatch is in OAIdl.idl.
/// </remarks>
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("00020400-0000-0000-C000-000000000046")]
private interface IDispatchInfo
{
/// <summary>
/// Gets the number of Types that the object provides (0 or 1).
/// </summary>
/// <param name="typeInfoCount">Returns 0 or 1 for the number of Types provided by <see cref="GetTypeInfo"/>.</param>
/// <remarks>
/// http://msdn.microsoft.com/en-us/library/da876d53-cb8a-465c-a43e-c0eb272e2a12(VS.85)
/// </remarks>
[PreserveSig]
int GetTypeInfoCount(out int typeInfoCount);

/// <summary>
/// Gets the Type information for an object if <see cref="GetTypeInfoCount"/> returned 1.
/// </summary>
/// <param name="typeInfoIndex">Must be 0.</param>
/// <param name="lcid">Typically, LOCALE_SYSTEM_DEFAULT (2048).</param>
/// <param name="typeInfo">Returns the object's Type information.</param>
/// <remarks>
/// http://msdn.microsoft.com/en-us/library/cc1ec9aa-6c40-4e70-819c-a7c6dd6b8c99(VS.85)
/// </remarks>
void GetTypeInfo(int typeInfoIndex, int lcid, [MarshalAs(UnmanagedType.CustomMarshaler,
MarshalTypeRef = typeof(System.Runtime.InteropServices.CustomMarshalers.TypeToTypeInfoMarshaler))] out Type typeInfo);

/// <summary>
/// Gets the DISPID of the specified member name.
/// </summary>
/// <param name="riid">Must be IID_NULL.  Pass a copy of Guid.Empty.</param>
/// <param name="name">The name of the member to look up.</param>
/// <param name="nameCount">Must be 1.</param>
/// <param name="lcid">Typically, LOCALE_SYSTEM_DEFAULT (2048).</param>
/// <param name="dispId">If a member with the requested <paramref name="name"/>
/// is found, this returns its DISPID and the method's return value is 0.
/// If the method returns a non-zero value, then this parameter's output value is
/// undefined.</param>
/// <returns>Zero for success. Non-zero for failure.</returns>
/// <remarks>
/// http://msdn.microsoft.com/en-us/library/6f6cf233-3481-436e-8d6a-51f93bf91619(VS.85)
/// </remarks>
[PreserveSig]
int GetDispId(ref Guid riid, ref string name, int nameCount, int lcid, out int dispId);

// NOTE: The real IDispatch also has an Invoke method next, but we don't need it.
// We can invoke methods using .NET's Type.InvokeMember method with the special
// [DISPID=n] syntax for member "names", or we can get a .NET Type using GetTypeInfo
// and invoke methods on that through reflection.
// Type.InvokeMember: http://msdn.microsoft.com/en-us/library/de3dhzwy.aspx
}
                #endregion
}



if (!DispatchUtility.ImplementsIDispatch(obj))
{
         throw new ArgumentException("The object created for " + progId + " doesn't implement IDispatch.");
}

// See if we can get Type info and then do some reflection.
Type dispatchType = DispatchUtility.GetType(obj, false);
if (dispatchType != null)
{
        var hr = DispatchUtility.TryGetDispId(obj, _methodName, out dispId);
        return hr== hr_OK && dispId != -1;
}

哥们,这个是改的C++端的程序吗? 有点晕。- -有没有其他什么方式能判断呢。只要是能查询出这个方法是否存在于这个dll当中就可以。!

#29


该回复于2014-11-21 16:55:29被管理员删除

#30


不是C++端的,就是C#中判断COM组件是否包含某个成员的方法

#31


你把DispatchUtility这个类复制到你的项目中,然后用
if (!DispatchUtility.ImplementsIDispatch(obj))
{
         throw new ArgumentException("The object created for " + progId + " doesn't implement IDispatch.");
}
// See if we can get Type info and then do some reflection.
Type dispatchType = DispatchUtility.GetType(obj, false);
int dispId;
if (dispatchType != null)
{
        var hr = DispatchUtility.TryGetDispId(obj, _methodName, out dispId);
        return hr== 0 && dispId != -1;
}

obj就是com对象,其实是不需要obj的,有var type = Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"))就行了

如果这都看不懂,那你只好去补一下基础了

#32


引用 31 楼 dongxinxi 的回复:
你把DispatchUtility这个类复制到你的项目中,然后用
if (!DispatchUtility.ImplementsIDispatch(obj))
{
         throw new ArgumentException("The object created for " + progId + " doesn't implement IDispatch.");
}
// See if we can get Type info and then do some reflection.
Type dispatchType = DispatchUtility.GetType(obj, false);
int dispId;
if (dispatchType != null)
{
        var hr = DispatchUtility.TryGetDispId(obj, _methodName, out dispId);
        return hr== 0 && dispId != -1;
}

obj就是com对象,其实是不需要obj的,有var type = Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"))就行了

如果这都看不懂,那你只好去补一下基础了

结贴,谢谢了。

#1


comObj.GetType().GetMember(_methodName)

#2


反射呗
var type = Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"));
var method = type.GetMethod(_methodName, 是否区分大小写);
if(method != null)
{
         method.Invoke(XXX)
}

#3


引用 2 楼 dongxinxi 的回复:
反射呗
var type = Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"));
var method = type.GetMethod(_methodName, 是否区分大小写);
if(method != null)
{
         method.Invoke(XXX)
}

method值一直为空额,哪怕里面有那个方法也是

#4



引用 1 楼 feiyun0112 的回复:
comObj.GetType().GetMember(_methodName)

不行啊,判断不出来啊,是否有这个方法

#5


引用 2 楼 dongxinxi 的回复:
反射呗
var type = Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"));
var method = type.GetMethod(_methodName, 是否区分大小写);
if(method != null)
{
         method.Invoke(XXX)
}

   //通过GUID获取到DVBusiUtilCalClass类
             var type=Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"));
                //查看是否有—_methodName这个方法
                var method = type.GetMethod(_methodName);
                如果在DVBusiUtilCalClass没有找到这个方法,那么去创建DVBusiUtilPreClass的实例
                if (method == null)
                {
                   type = Type.GetTypeFromCLSID(new Guid("592703AB-CF61-425D-9ACD-A0938E451AEA"));
                }

#6


引用 3 楼 u013063561 的回复:
Quote: 引用 2 楼 dongxinxi 的回复:

反射呗
var type = Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"));
var method = type.GetMethod(_methodName, 是否区分大小写);
if(method != null)
{
         method.Invoke(XXX)
}

method值一直为空额,哪怕里面有那个方法也是

 type有值没?

#7


引用 5 楼 u013063561 的回复:
Quote: 引用 2 楼 dongxinxi 的回复:

反射呗
var type = Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"));
var method = type.GetMethod(_methodName, 是否区分大小写);
if(method != null)
{
         method.Invoke(XXX)
}

   //通过GUID获取到DVBusiUtilCalClass类
             var type=Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"));
                //查看是否有—_methodName这个方法
                var method = type.GetMethod(_methodName);
                如果在DVBusiUtilCalClass没有找到这个方法,那么去创建DVBusiUtilPreClass的实例
                if (method == null)
                {
                   type = Type.GetTypeFromCLSID(new Guid("592703AB-CF61-425D-9ACD-A0938E451AEA"));
                }

type有值,但是method每值,一直是空

#8


引用 6 楼 lovelj2012 的回复:
Quote: 引用 3 楼 u013063561 的回复:

Quote: 引用 2 楼 dongxinxi 的回复:

反射呗
var type = Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"));
var method = type.GetMethod(_methodName, 是否区分大小写);
if(method != null)
{
         method.Invoke(XXX)
}

method值一直为空额,哪怕里面有那个方法也是

 type有值没?

type一直没值!~~

#9


comObj.GetType().GetMembers()
看有哪些MemberName

#10


引用 6 楼 lovelj2012 的回复:
Quote: 引用 3 楼 u013063561 的回复:

Quote: 引用 2 楼 dongxinxi 的回复:

反射呗
var type = Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"));
var method = type.GetMethod(_methodName, 是否区分大小写);
if(method != null)
{
         method.Invoke(XXX)
}

method值一直为空额,哪怕里面有那个方法也是

 type有值没?

type有值 但是method一直为空。。

#11


引用 8 楼 u013063561 的回复:
Quote: 引用 6 楼 lovelj2012 的回复:

Quote: 引用 3 楼 u013063561 的回复:

Quote: 引用 2 楼 dongxinxi 的回复:

反射呗
var type = Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"));
var method = type.GetMethod(_methodName, 是否区分大小写);
if(method != null)
{
         method.Invoke(XXX)
}

method值一直为空额,哪怕里面有那个方法也是

 type有值没?

type一直没值!~~

type一直没值,那执行GetMethod肯定反射不来东东啊
是不是你的GUID搞错了

#12


引用 9 楼 feiyun0112 的回复:
comObj.GetType().GetMembers()
看有哪些MemberName

{System.String ToString()}
System.Object GetLifetimeService
System.Runtime.Remoting.ObjRef CreateObjRef(System.Type)
等等一共6个值!~

#13


引用 11 楼 lovelj2012 的回复:
Quote: 引用 8 楼 u013063561 的回复:

Quote: 引用 6 楼 lovelj2012 的回复:

Quote: 引用 3 楼 u013063561 的回复:

Quote: 引用 2 楼 dongxinxi 的回复:

反射呗
var type = Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"));
var method = type.GetMethod(_methodName, 是否区分大小写);
if(method != null)
{
         method.Invoke(XXX)
}

method值一直为空额,哪怕里面有那个方法也是

 type有值没?

type一直没值!~~

type一直没值,那执行GetMethod肯定反射不来东东啊
是不是你的GUID搞错了

type有值,method没值!~一直是空

#14


GetMethod用法,是不是2#搞错了。
照着msdn的例子用
http://msdn.microsoft.com/zh-cn/library/6hy0h0z1(v=vs.100).aspx

#15


引用 14 楼 lovelj2012 的回复:
GetMethod用法,是不是2#搞错了。
照着msdn的例子用
http://msdn.microsoft.com/zh-cn/library/6hy0h0z1(v=vs.100).aspx

 额,这个getMethod是调用方法啊?我要的只查询出这个方法是否存在于这个类中!· = = 

#16



  args[0] = "DVC_CutImgmethod";
                args[1] = @"11";
                args[2] = "1";
                args[3] = "2";
                //如果没有数据的话,直接return
                if (args.Length == 0)
                {
                    return;
                }
                //获取方法名
                string _methodName = args[0];
                //创建list集合用于保存参数
                List<object> list = new List<object>();

                for (int i = 1; i < args.Length; i++)
                {
                    list.Add(args[i]);
                }
                //转换成object数组
                object[] param = list.ToArray();
            
                //通过GUID获取到DVBusiUtilCalClass类
                var type=Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"));
                //查看是否有—_methodName这个方法
                var method = type.GetMethod(_methodName);
               MethodInfo[] sss=  type.GetMethods();
                //如果在DVBusiUtilCalClass没有找到这个方法,那么去创建DVBusiUtilPreClass的实例
                if (method == null)
                {
                    type = Type.GetTypeFromCLSID(new Guid("592703AB-CF61-425D-9ACD-A0938E451AEA"));
                }
                object comObj = Activator.CreateInstance(type);
                //创建类型实例
                //object comObj = Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024")));
                //MemberInfo[] vvv = comObj.GetType().GetMembers();
                //int ddd = vvv.Length;
                //if (comObj.GetType().GetMember(_methodName)==null)
                //{
                //    comObj = Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("592703AB-CF61-425D-9ACD-A0938E451AEA")));
                //}
                //获取返回值
                object result = comObj.GetType().InvokeMember(_methodName, System.Reflection.BindingFlags.InvokeMethod, null, comObj, param);
               
                Console.WriteLine(Convert.ToInt32(result));

整体代码。。

#17


引用 9 楼 feiyun0112 的回复:
comObj.GetType().GetMembers()
看有哪些MemberName

没用啊版主,找不到那个guid类当中的那些方法!~~~

#18


引用 15 楼 u013063561 的回复:
Quote: 引用 14 楼 lovelj2012 的回复:

GetMethod用法,是不是2#搞错了。
照着msdn的例子用
http://msdn.microsoft.com/zh-cn/library/6hy0h0z1(v=vs.100).aspx

 额,这个getMethod是调用方法啊?我要的只查询出这个方法是否存在于这个类中!· = = 

无语了~~~

GetMethod从类型里面反射出某个方法是否存在
类型.GetMethod返回结果不是null,就证明这个类型中存在这个方法了

#19


引用 18 楼 lovelj2012 的回复:
Quote: 引用 15 楼 u013063561 的回复:

Quote: 引用 14 楼 lovelj2012 的回复:

GetMethod用法,是不是2#搞错了。
照着msdn的例子用
http://msdn.microsoft.com/zh-cn/library/6hy0h0z1(v=vs.100).aspx

 额,这个getMethod是调用方法啊?我要的只查询出这个方法是否存在于这个类中!· = = 

无语了~~~

GetMethod从类型里面反射出某个方法是否存在
类型.GetMethod返回结果不是null,就证明这个类型中存在这个方法了

不是吧?我看csdn里面是写的方法名加参数,得到的是返回结果额?
但是我那个类中确实存在那个方法。method还是为空!~

#20


如果那个方法没有重载过,是不需要指定参数及类型的,你确定总共就6个成员吗?

那样就不是GetMethod的问题了,反射出来的都是托管类型的成员,不是COM接口的成员
当COM类实现了IDispatch意味着将延迟绑定类型
IDispatch::GetIDsOfNames 方法,Visual C# 可以询问对象支持哪些方法和属性
IDispatch::Invoke 方法允许 Visual C# 调用这些方法和属性。

不过NET封装了现成的

try
{
          var type = Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"));
          type.InvokeMember(_methodName, BindingFlags.InvokeMethod, null, comObj, 参数列表);
}
catch(System.MissingMethodException exp)
{
          方法未找到
}


找到了一篇C++通过IDispatch查询并调用的文章,你可以看看,
http://blog.csdn.net/csfreebird/article/details/463031

#21


Com对象在.net这边的类型其实是System.__ComObject,所以通过GetMethods这样反射是取不到信息的。
必须使用Com的IDispatch接口上面的GetIDsOfNames才能判断

#22


引用 20 楼 dongxinxi 的回复:
如果那个方法没有重载过,是不需要指定参数及类型的,你确定总共就6个成员吗?

那样就不是GetMethod的问题了,反射出来的都是托管类型的成员,不是COM接口的成员
当COM类实现了IDispatch意味着将延迟绑定类型
IDispatch::GetIDsOfNames 方法,Visual C# 可以询问对象支持哪些方法和属性
IDispatch::Invoke 方法允许 Visual C# 调用这些方法和属性。

不过NET封装了现成的

try
{
          var type = Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"));
          type.InvokeMember(_methodName, BindingFlags.InvokeMethod, null, comObj, 参数列表);
}
catch(System.MissingMethodException exp)
{
          方法未找到
}


找到了一篇C++通过IDispatch查询并调用的文章,你可以看看,
http://blog.csdn.net/csfreebird/article/details/463031

那我应该怎么办呢???

#23


#24


引用 23 楼 github_22161131 的回复:
可以使用这里面提供的代码: http://www.codeproject.com/Articles/523417/Reflection-with-IDispatch-based-COM-objects

不该DLL文件能实现吗?只要能判断出这个方法到底存在不存在就ok

#25


引用 23 楼 github_22161131 的回复:
可以使用这里面提供的代码: http://www.codeproject.com/Articles/523417/Reflection-with-IDispatch-based-COM-objects

你给的这个打不开!~~网站

#26


其实思路也不复杂
1. 定义一个IDispatch
2. 获取IDispatch指针对象
3.利用IDispatch.GetIDsOfNames来判断成员是否存在(当然先要用GetTypeInfoCount(out count)判断是否具有类型信息)

HRESULT STDMETHODCALLTYPE GetIDsOfNames(
            /* [in] */ REFIID riid,
            /* [size_is][in] */ LPOLESTR *rgszNames,
            /* [in] */ UINT cNames,
            /* [in] */ LCID lcid,
/* [size_is][out] */ DISPID *rgDispId)
 
IDispatch接口的属性实质上是方法,方法也就是成员函数,IDispatch接口把所有成员函数的入口地址放入到一个数组中,并且内部组织了一个Map,将数组索引和方法名称一一映射。我们常见的DISPID就是这些方法在数组中的索引。如果我们想调用某一个方法,我们就需要DISPID来让我们找到该方法的地址。
    
     参数riid必须为NULL。
     参数rgszNames为字符串数组,第一个字符串为方法或者属性的名称,后续的字符串为参数名称,IDispatch接口的参数也可以有名字。
     参数cNames指定rgszNames数组中字符串的个数。
     参数lcid传递地域标志,同GetTypeInfo方法中的参数。
     参数rgDispId输出一个数组,每个数组成员对应rgszNames中的一个字符串名称。
 
     关于DISPID的进一步说明:
         typedef LONG DISPID;
typedef DISPID MEMBERID;
    
     DISPID小于等于0的值都是有特殊意义的,如下面介绍的----
         /* DISPID reserved to indicate an "unknown" name */
/* only reserved for data members (properties); reused as a method dispid below */
//如果GetIDsOfNames函数找不到与名称相对应的DISPID,返回该值
#define  DISPID_UNKNOWN     ( -1 )

所以当输出参数rgDispId == -1即表示不存在了,上面那个代码里有现成的接口声明,贴给你吧

#27



public static class DispatchUtility
{
#region Private Constants

private const int S_OK = 0; //From WinError.h
private const int LOCALE_SYSTEM_DEFAULT = 2 << 10; //From WinNT.h == 2048 == 0x800

#endregion

#region Public Methods

/// <summary>
/// Gets whether the specified object implements IDispatch.
/// </summary>
/// <param name="obj">An object to check.</param>
/// <returns>True if the object implements IDispatch.  False otherwise.</returns>
public static bool ImplementsIDispatch(object obj)
{
bool result = obj is IDispatchInfo;
return result;
}

/// <summary>
/// Gets a Type that can be used with reflection.
/// </summary>
/// <param name="obj">An object that implements IDispatch.</param>
/// <param name="throwIfNotFound">Whether an exception should be thrown if a Type can't be obtained.</param>
/// <returns>A .NET Type that can be used with reflection.</returns>
/// <exception cref="InvalidCastException">If <paramref name="obj"/> doesn't implement IDispatch.</exception>
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public static Type GetType(object obj, bool throwIfNotFound)
{
RequireReference(obj, "obj");
Type result = GetType((IDispatchInfo)obj, throwIfNotFound);
return result;
}

/// <summary>
/// Tries to get the DISPID for the requested member name.
/// </summary>
/// <param name="obj">An object that implements IDispatch.</param>
/// <param name="name">The name of a member to lookup.</param>
/// <param name="dispId">If the method returns true, this holds the DISPID on output.
/// If the method returns false, this value should be ignored.</param>
/// <returns>True if the member was found and resolved to a DISPID.  False otherwise.</returns>
/// <exception cref="InvalidCastException">If <paramref name="obj"/> doesn't implement IDispatch.</exception>
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public static bool TryGetDispId(object obj, string name, out int dispId)
{
RequireReference(obj, "obj");
bool result = TryGetDispId((IDispatchInfo)obj, name, out dispId);
return result;
}

#region Private Methods

/// <summary>
/// Requires that the value is non-null.
/// </summary>
/// <typeparam name="T">The type of the value.</typeparam>
/// <param name="value">The value to check.</param>
/// <param name="name">The name of the value.</param>
private static void RequireReference<T>(T value, string name) where T : class
{
if (value == null)
{
throw new ArgumentNullException(name);
}
}

/// <summary>
/// Gets a Type that can be used with reflection.
/// </summary>
/// <param name="dispatch">An object that implements IDispatch.</param>
/// <param name="throwIfNotFound">Whether an exception should be thrown if a Type can't be obtained.</param>
/// <returns>A .NET Type that can be used with reflection.</returns>
private static Type GetType(IDispatchInfo dispatch, bool throwIfNotFound)
{
RequireReference(dispatch, "dispatch");

Type result = null;
int typeInfoCount;
int hr = dispatch.GetTypeInfoCount(out typeInfoCount);
if (hr == S_OK && typeInfoCount > 0)
{
// Type info isn't usually culture-aware for IDispatch, so we might as well pass
// the default locale instead of looking up the current thread's LCID each time
// (via CultureInfo.CurrentCulture.LCID).
dispatch.GetTypeInfo(0, LOCALE_SYSTEM_DEFAULT, out result);
}

if (result == null && throwIfNotFound)
{
// If the GetTypeInfoCount called failed, throw an exception for that.
Marshal.ThrowExceptionForHR(hr);

// Otherwise, throw the same exception that Type.GetType would throw.
throw new TypeLoadException();
}

return result;
}

/// <summary>
/// Tries to get the DISPID for the requested member name.
/// </summary>
/// <param name="dispatch">An object that implements IDispatch.</param>
/// <param name="name">The name of a member to lookup.</param>
/// <param name="dispId">If the method returns true, this holds the DISPID on output.
/// If the method returns false, this value should be ignored.</param>
/// <returns>True if the member was found and resolved to a DISPID.  False otherwise.</returns>
private static bool TryGetDispId(IDispatchInfo dispatch, string name, out int dispId)
{
RequireReference(dispatch, "dispatch");
RequireReference(name, "name");

bool result = false;

// Members names aren't usually culture-aware for IDispatch, so we might as well
// pass the default locale instead of looking up the current thread's LCID each time
// (via CultureInfo.CurrentCulture.LCID).
Guid iidNull = Guid.Empty;
int hr = dispatch.GetDispId(ref iidNull, ref name, 1, LOCALE_SYSTEM_DEFAULT, out dispId);

const int DISP_E_UNKNOWNNAME = unchecked((int)0x80020006); //From WinError.h
const int DISPID_UNKNOWN = -1; //From OAIdl.idl
if (hr == S_OK)
{
result = true;
}
else if (hr == DISP_E_UNKNOWNNAME && dispId == DISPID_UNKNOWN)
{
// This is the only supported "error" case because it means IDispatch
// is saying it doesn't know the member we asked about.
result = false;
}
else
{
// The other documented result codes are all errors.
Marshal.ThrowExceptionForHR(hr);
}

return result;
}

#endregion

#region Private Interfaces

/// <summary>
/// A partial declaration of IDispatch used to lookup Type information and DISPIDs.
/// </summary>
/// <remarks>
/// This interface only declares the first three methods of IDispatch.  It omits the
/// fourth method (Invoke) because there are already plenty of ways to do dynamic
/// invocation in .NET.  But the first three methods provide dynamic type metadata
/// discovery, which .NET doesn't provide normally if you have a System.__ComObject
/// RCW instead of a strongly-typed RCW.
/// <para/>
/// Note: The original declaration of IDispatch is in OAIdl.idl.
/// </remarks>
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("00020400-0000-0000-C000-000000000046")]
private interface IDispatchInfo
{
/// <summary>
/// Gets the number of Types that the object provides (0 or 1).
/// </summary>
/// <param name="typeInfoCount">Returns 0 or 1 for the number of Types provided by <see cref="GetTypeInfo"/>.</param>
/// <remarks>
/// http://msdn.microsoft.com/en-us/library/da876d53-cb8a-465c-a43e-c0eb272e2a12(VS.85)
/// </remarks>
[PreserveSig]
int GetTypeInfoCount(out int typeInfoCount);

/// <summary>
/// Gets the Type information for an object if <see cref="GetTypeInfoCount"/> returned 1.
/// </summary>
/// <param name="typeInfoIndex">Must be 0.</param>
/// <param name="lcid">Typically, LOCALE_SYSTEM_DEFAULT (2048).</param>
/// <param name="typeInfo">Returns the object's Type information.</param>
/// <remarks>
/// http://msdn.microsoft.com/en-us/library/cc1ec9aa-6c40-4e70-819c-a7c6dd6b8c99(VS.85)
/// </remarks>
void GetTypeInfo(int typeInfoIndex, int lcid, [MarshalAs(UnmanagedType.CustomMarshaler,
MarshalTypeRef = typeof(System.Runtime.InteropServices.CustomMarshalers.TypeToTypeInfoMarshaler))] out Type typeInfo);

/// <summary>
/// Gets the DISPID of the specified member name.
/// </summary>
/// <param name="riid">Must be IID_NULL.  Pass a copy of Guid.Empty.</param>
/// <param name="name">The name of the member to look up.</param>
/// <param name="nameCount">Must be 1.</param>
/// <param name="lcid">Typically, LOCALE_SYSTEM_DEFAULT (2048).</param>
/// <param name="dispId">If a member with the requested <paramref name="name"/>
/// is found, this returns its DISPID and the method's return value is 0.
/// If the method returns a non-zero value, then this parameter's output value is
/// undefined.</param>
/// <returns>Zero for success. Non-zero for failure.</returns>
/// <remarks>
/// http://msdn.microsoft.com/en-us/library/6f6cf233-3481-436e-8d6a-51f93bf91619(VS.85)
/// </remarks>
[PreserveSig]
int GetDispId(ref Guid riid, ref string name, int nameCount, int lcid, out int dispId);

// NOTE: The real IDispatch also has an Invoke method next, but we don't need it.
// We can invoke methods using .NET's Type.InvokeMember method with the special
// [DISPID=n] syntax for member "names", or we can get a .NET Type using GetTypeInfo
// and invoke methods on that through reflection.
// Type.InvokeMember: http://msdn.microsoft.com/en-us/library/de3dhzwy.aspx
}
                #endregion
}



if (!DispatchUtility.ImplementsIDispatch(obj))
{
         throw new ArgumentException("The object created for " + progId + " doesn't implement IDispatch.");
}

// See if we can get Type info and then do some reflection.
Type dispatchType = DispatchUtility.GetType(obj, false);
if (dispatchType != null)
{
        var hr = DispatchUtility.TryGetDispId(obj, _methodName, out dispId);
        return hr== hr_OK && dispId != -1;
}

#28


引用 27 楼 dongxinxi 的回复:

public static class DispatchUtility
{
#region Private Constants

private const int S_OK = 0; //From WinError.h
private const int LOCALE_SYSTEM_DEFAULT = 2 << 10; //From WinNT.h == 2048 == 0x800

#endregion

#region Public Methods

/// <summary>
/// Gets whether the specified object implements IDispatch.
/// </summary>
/// <param name="obj">An object to check.</param>
/// <returns>True if the object implements IDispatch.  False otherwise.</returns>
public static bool ImplementsIDispatch(object obj)
{
bool result = obj is IDispatchInfo;
return result;
}

/// <summary>
/// Gets a Type that can be used with reflection.
/// </summary>
/// <param name="obj">An object that implements IDispatch.</param>
/// <param name="throwIfNotFound">Whether an exception should be thrown if a Type can't be obtained.</param>
/// <returns>A .NET Type that can be used with reflection.</returns>
/// <exception cref="InvalidCastException">If <paramref name="obj"/> doesn't implement IDispatch.</exception>
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public static Type GetType(object obj, bool throwIfNotFound)
{
RequireReference(obj, "obj");
Type result = GetType((IDispatchInfo)obj, throwIfNotFound);
return result;
}

/// <summary>
/// Tries to get the DISPID for the requested member name.
/// </summary>
/// <param name="obj">An object that implements IDispatch.</param>
/// <param name="name">The name of a member to lookup.</param>
/// <param name="dispId">If the method returns true, this holds the DISPID on output.
/// If the method returns false, this value should be ignored.</param>
/// <returns>True if the member was found and resolved to a DISPID.  False otherwise.</returns>
/// <exception cref="InvalidCastException">If <paramref name="obj"/> doesn't implement IDispatch.</exception>
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public static bool TryGetDispId(object obj, string name, out int dispId)
{
RequireReference(obj, "obj");
bool result = TryGetDispId((IDispatchInfo)obj, name, out dispId);
return result;
}

#region Private Methods

/// <summary>
/// Requires that the value is non-null.
/// </summary>
/// <typeparam name="T">The type of the value.</typeparam>
/// <param name="value">The value to check.</param>
/// <param name="name">The name of the value.</param>
private static void RequireReference<T>(T value, string name) where T : class
{
if (value == null)
{
throw new ArgumentNullException(name);
}
}

/// <summary>
/// Gets a Type that can be used with reflection.
/// </summary>
/// <param name="dispatch">An object that implements IDispatch.</param>
/// <param name="throwIfNotFound">Whether an exception should be thrown if a Type can't be obtained.</param>
/// <returns>A .NET Type that can be used with reflection.</returns>
private static Type GetType(IDispatchInfo dispatch, bool throwIfNotFound)
{
RequireReference(dispatch, "dispatch");

Type result = null;
int typeInfoCount;
int hr = dispatch.GetTypeInfoCount(out typeInfoCount);
if (hr == S_OK && typeInfoCount > 0)
{
// Type info isn't usually culture-aware for IDispatch, so we might as well pass
// the default locale instead of looking up the current thread's LCID each time
// (via CultureInfo.CurrentCulture.LCID).
dispatch.GetTypeInfo(0, LOCALE_SYSTEM_DEFAULT, out result);
}

if (result == null && throwIfNotFound)
{
// If the GetTypeInfoCount called failed, throw an exception for that.
Marshal.ThrowExceptionForHR(hr);

// Otherwise, throw the same exception that Type.GetType would throw.
throw new TypeLoadException();
}

return result;
}

/// <summary>
/// Tries to get the DISPID for the requested member name.
/// </summary>
/// <param name="dispatch">An object that implements IDispatch.</param>
/// <param name="name">The name of a member to lookup.</param>
/// <param name="dispId">If the method returns true, this holds the DISPID on output.
/// If the method returns false, this value should be ignored.</param>
/// <returns>True if the member was found and resolved to a DISPID.  False otherwise.</returns>
private static bool TryGetDispId(IDispatchInfo dispatch, string name, out int dispId)
{
RequireReference(dispatch, "dispatch");
RequireReference(name, "name");

bool result = false;

// Members names aren't usually culture-aware for IDispatch, so we might as well
// pass the default locale instead of looking up the current thread's LCID each time
// (via CultureInfo.CurrentCulture.LCID).
Guid iidNull = Guid.Empty;
int hr = dispatch.GetDispId(ref iidNull, ref name, 1, LOCALE_SYSTEM_DEFAULT, out dispId);

const int DISP_E_UNKNOWNNAME = unchecked((int)0x80020006); //From WinError.h
const int DISPID_UNKNOWN = -1; //From OAIdl.idl
if (hr == S_OK)
{
result = true;
}
else if (hr == DISP_E_UNKNOWNNAME && dispId == DISPID_UNKNOWN)
{
// This is the only supported "error" case because it means IDispatch
// is saying it doesn't know the member we asked about.
result = false;
}
else
{
// The other documented result codes are all errors.
Marshal.ThrowExceptionForHR(hr);
}

return result;
}

#endregion

#region Private Interfaces

/// <summary>
/// A partial declaration of IDispatch used to lookup Type information and DISPIDs.
/// </summary>
/// <remarks>
/// This interface only declares the first three methods of IDispatch.  It omits the
/// fourth method (Invoke) because there are already plenty of ways to do dynamic
/// invocation in .NET.  But the first three methods provide dynamic type metadata
/// discovery, which .NET doesn't provide normally if you have a System.__ComObject
/// RCW instead of a strongly-typed RCW.
/// <para/>
/// Note: The original declaration of IDispatch is in OAIdl.idl.
/// </remarks>
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("00020400-0000-0000-C000-000000000046")]
private interface IDispatchInfo
{
/// <summary>
/// Gets the number of Types that the object provides (0 or 1).
/// </summary>
/// <param name="typeInfoCount">Returns 0 or 1 for the number of Types provided by <see cref="GetTypeInfo"/>.</param>
/// <remarks>
/// http://msdn.microsoft.com/en-us/library/da876d53-cb8a-465c-a43e-c0eb272e2a12(VS.85)
/// </remarks>
[PreserveSig]
int GetTypeInfoCount(out int typeInfoCount);

/// <summary>
/// Gets the Type information for an object if <see cref="GetTypeInfoCount"/> returned 1.
/// </summary>
/// <param name="typeInfoIndex">Must be 0.</param>
/// <param name="lcid">Typically, LOCALE_SYSTEM_DEFAULT (2048).</param>
/// <param name="typeInfo">Returns the object's Type information.</param>
/// <remarks>
/// http://msdn.microsoft.com/en-us/library/cc1ec9aa-6c40-4e70-819c-a7c6dd6b8c99(VS.85)
/// </remarks>
void GetTypeInfo(int typeInfoIndex, int lcid, [MarshalAs(UnmanagedType.CustomMarshaler,
MarshalTypeRef = typeof(System.Runtime.InteropServices.CustomMarshalers.TypeToTypeInfoMarshaler))] out Type typeInfo);

/// <summary>
/// Gets the DISPID of the specified member name.
/// </summary>
/// <param name="riid">Must be IID_NULL.  Pass a copy of Guid.Empty.</param>
/// <param name="name">The name of the member to look up.</param>
/// <param name="nameCount">Must be 1.</param>
/// <param name="lcid">Typically, LOCALE_SYSTEM_DEFAULT (2048).</param>
/// <param name="dispId">If a member with the requested <paramref name="name"/>
/// is found, this returns its DISPID and the method's return value is 0.
/// If the method returns a non-zero value, then this parameter's output value is
/// undefined.</param>
/// <returns>Zero for success. Non-zero for failure.</returns>
/// <remarks>
/// http://msdn.microsoft.com/en-us/library/6f6cf233-3481-436e-8d6a-51f93bf91619(VS.85)
/// </remarks>
[PreserveSig]
int GetDispId(ref Guid riid, ref string name, int nameCount, int lcid, out int dispId);

// NOTE: The real IDispatch also has an Invoke method next, but we don't need it.
// We can invoke methods using .NET's Type.InvokeMember method with the special
// [DISPID=n] syntax for member "names", or we can get a .NET Type using GetTypeInfo
// and invoke methods on that through reflection.
// Type.InvokeMember: http://msdn.microsoft.com/en-us/library/de3dhzwy.aspx
}
                #endregion
}



if (!DispatchUtility.ImplementsIDispatch(obj))
{
         throw new ArgumentException("The object created for " + progId + " doesn't implement IDispatch.");
}

// See if we can get Type info and then do some reflection.
Type dispatchType = DispatchUtility.GetType(obj, false);
if (dispatchType != null)
{
        var hr = DispatchUtility.TryGetDispId(obj, _methodName, out dispId);
        return hr== hr_OK && dispId != -1;
}

哥们,这个是改的C++端的程序吗? 有点晕。- -有没有其他什么方式能判断呢。只要是能查询出这个方法是否存在于这个dll当中就可以。!

#29


该回复于2014-11-21 16:55:29被管理员删除

#30


不是C++端的,就是C#中判断COM组件是否包含某个成员的方法

#31


你把DispatchUtility这个类复制到你的项目中,然后用
if (!DispatchUtility.ImplementsIDispatch(obj))
{
         throw new ArgumentException("The object created for " + progId + " doesn't implement IDispatch.");
}
// See if we can get Type info and then do some reflection.
Type dispatchType = DispatchUtility.GetType(obj, false);
int dispId;
if (dispatchType != null)
{
        var hr = DispatchUtility.TryGetDispId(obj, _methodName, out dispId);
        return hr== 0 && dispId != -1;
}

obj就是com对象,其实是不需要obj的,有var type = Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"))就行了

如果这都看不懂,那你只好去补一下基础了

#32


引用 31 楼 dongxinxi 的回复:
你把DispatchUtility这个类复制到你的项目中,然后用
if (!DispatchUtility.ImplementsIDispatch(obj))
{
         throw new ArgumentException("The object created for " + progId + " doesn't implement IDispatch.");
}
// See if we can get Type info and then do some reflection.
Type dispatchType = DispatchUtility.GetType(obj, false);
int dispId;
if (dispatchType != null)
{
        var hr = DispatchUtility.TryGetDispId(obj, _methodName, out dispId);
        return hr== 0 && dispId != -1;
}

obj就是com对象,其实是不需要obj的,有var type = Type.GetTypeFromCLSID(new Guid("30FB1E22-B498-4B62-8B26-98BA61176024"))就行了

如果这都看不懂,那你只好去补一下基础了

结贴,谢谢了。