Why does dynamic method invoke fail when reflection still works?
c#, com, dynamic, reflection
Solution
Interestingly, none of `NameTranslate` methods are callable via `dynamic`. I have only a theoretical explanation of this, below.
AFAIK, when .NET DLR deals with COM objects for `dynamic` invocation, it tries to make use of a COM type library, if available, and then resorts to `IDispatch`. That's how it is different from Reflection, which calls `IDispatch` right away when used with COM objects.
The ActiveDS type library (`C:\Windows\System32\activeds.tlb`), as viewed with OleView, appears to be somewhat ill-formed. It includes a lot of non-automation compatible declarations, including interfaces:
interface IPrivateDispatch;
interface ITypeInfo;
interface ITypeComp;
interface ITypeLib;
interface IPrivateUnknown;
The class definition for `NameTranslate` itself looks like this:
[
uuid(274FAE1F-3626-11D1-A3A4-00C04FB950DC)
]
coclass NameTranslate {
[default] interface IADsNameTranslate;
interface IDispatch;
};
It's unusual (although not prohibited) to declare `IDispatch` inside `coclass`.
So, I'd assume such type library and/or `coclass` definition might be confusing the DLR in this case.
As a workaround, you can import it with `TlbImp.exe activeds.tlb` (that would produce a bunch of warnings), add the output interop assembly to your project and call the API directly. This works:
Type ntt = Type.GetTypeFromProgID("NameTranslate");
var nto = Activator.CreateInstance(ntt) as ActiveDs.IADsNameTranslate;
nto.Init(3, null);
Problem
Why can't a `dynamic` object invoke these methods on the NameTranslate COM object when reflection can? Failing example using dynamic: ``` Type ntt = Type.GetTypeFromProgID("NameTranslate"); dynamic nto = Activator.CreateInstance(ntt); nto.Init(3,null) ``` The third line fails with a NotImplementedException and the message The method or operation is not implemented. A similar attempt that works using a different COM object (WScript.Shell and SendKeys): ``` Type shellType = Type.GetTypeFromProgID("WScript.Shell"); dynamic shell = Activator.CreateInstance(shellType); shell.SendKeys("abc"); ``` Getting back to the first sample. If I use reflection and invoke the methods using the InvokeMethod method things work fine. Working example using reflection: ``` Type ntt = Type.GetTypeFromProgID("NameTranslate"); object nto = Activator.CreateInstance(ntt); object[] initParams = new object[]{3,null}; ntt.InvokeMember("Init", BindingFlags.InvokeMethod, null, nto, initParams); ``` I believe this must have something to do with how the COM object is created or marked - but for the life of me I can't see anything in the docs, object browser or registry that indicates these COM objects and their subs/functions are marked private or something else that would normally throw off the `dynamic` keyword. NameTranslate documentation on MSDN: http://msdn.microsoft.com/en-us/library/windows/desktop/aa706046.aspx