See the question and my original answer on StackOverflow

Here is some C# sample code that allows you to do that (it's much easier from C/C++ because IDispatch is very special in .NET):

// get the object type from progid (or use other means)
var type = Type.GetTypeFromProgID("ClassLibrary.MyClass");
var obj = Activator.CreateInstance(type);

// sadly, we can't cast to a redefined p/invoke IDispatch of ours because its a .NET COM object
// and IDispatch has a very special treatment
// so we use the vtable directly
var dispPtr = Marshal.GetIDispatchForObject(obj);
var vtablePtr = Marshal.ReadIntPtr(dispPtr);
var methodPtr = Marshal.ReadIntPtr(vtablePtr + 5 * IntPtr.Size); // GetIDsOfNames is 5 methods away from IUnknown first method)
var getIDsOfNames = Marshal.GetDelegateForFunctionPointer<GetIDsOfNames>(methodPtr);

// ask for the dispid of "MyMethod" member
var dispid = new int[1];
var hr = getIDsOfNames(dispPtr, Guid.Empty, new string[] { "MyMethod" }, 1, 0, dispid);
Marshal.ThrowExceptionForHR(hr); // throw if not found

...

public delegate int GetIDsOfNames(
    IntPtr pThis,
    [MarshalAs(UnmanagedType.LPStruct)] Guid riid,
    [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)] string[] rgszNames,
    int cNames,
    int lcid,
    int[] rgDispId);