问题
I am using .NET 4.0 and dynamic to invoke members on a System.__ComObject at runtime. I instanciate the object in the following way:
dynamic DrApi;
DrApi = Activator.CreateInstance(SprImportedTypes.DrApi);
The types are declared in a static class like this:
internal static Type DrApi = Type.GetTypeFromProgID("DrApi.DrApi.1");
Since the object is dynamic, I can invoke methods without any difficulty:
string vers = string.Empty;
DrApi.Version(ref vers);
For consolidation and localized error handling, I'm trying to have a single routine that can be used for invoking methods on that object. Most of the methods require ref/out parameters, so I'm currently returning an object array of values that gets returned from reflection:
public object[] Run(string method, params object[] args)
{
var p = new ParameterModifier(args.Length);
for (int i = 0; i < args.Length; i++)
p[i] = true;
ParameterModifier[] mods = { p };
SprImportedTypes.DrApi.InvokeMember(method, BindingFlags.InvokeMethod,
null, DrApi, args, mods, null, null));
return args;
}
While this works, I'm not getting any information on the method I'm invoking, and am therefore not 100% comfortable setting all of the parameters by reference.
Here's what I tried that isn't working:
MethodInfo mInfo = SprImportedTypes.DrApi.GetMethod(methodName, BindingFlags.Instance |
BindingFlags.NonPublic | BindingFlags.Static);
Here is the method from OLE TypeLib Viewer:
[id(0x00000009), helpstring("method Version")]
HRESULT Version(
[in, out] BSTR* VersionString,
[out, retval] long* pReturnValue);
The class implements an interface which itself implements IDispatch, and the method is HRESULT, so I can't figure out why it never returns anything.
回答1:
This cannot work, COM does not support Reflection. So you cannot expect Type.GetMethod() to return anything. Late binding in COM is one-way, you can ask the server to execute a method by name but it won't tell you what methods it supports and what arguments they take. You are supposed to know this from the documentation.
You actually have a type library so technically you can inspect it at runtime to see what it is inside. This is far beyond painful and utterly impractical. Far simpler is to just add a reference to the type library. And you'll get auto-generated .NET wrapper types that you can use directly in your code. Check the MSDN article about Tlbimp.exe for details. This turns on lots of goodies, like IntelliSense and compile-time error checking. The code runs a lot faster as well. No need for dynamic anymore. The only disadvantage is that you'll bind your code to a specific version of the COM server, the one you have the type library for. But you'll of course still crash when your late-bound call is not compatible with an update, there is no magic cure for that.
来源:https://stackoverflow.com/questions/21709626/invoking-getmethod-on-a-system-comobject-always-returns-null