Kevin, this is possible, but I would also agree with Kirill, it is very difficult.
The primary issue is that the .idl language is C/C++ specific as is the generated code from the midl compiler. I've done it before by compiling the .idl to the appropriate C/C++ client/server stubs and then translating the code into C# PInvoke. This translation is Painful (with a capital "P"). The structures involved have circular references which makes it rather difficult, but not impossible, in C#.
Instead of fighting with loads of interface methods we chose the easier approach, a single entry-point. To that end our IDL looks like the following:
[ uuid (546B0CE0-C70B-1067-B317-00DD010662DA),
version(1.0),
pointer_default(unique)
]
interface IRpcExec
{
error_status_t Exec(
[in] handle_t Binding,
[in] long lDataSize,
[size_is(lDataSize)] byte arData[*],
[out] long *plReturnSize,
[out, size_is(,*plReturnSize)] byte **arReturn
);
}
The ACF then simply declares this to return errors:
interface IRpcExec
{
[comm_status, fault_status]
Exec();
}
Effectively this allows us to receive a byte[], and return a byte[], thereby turning RPC into a simple transport layer rather than a full-blown protocol. The full project and source are available from:
http://csharptest.net/browse/src/RpcLibrary/
Layered on top of this simple transport is a library to add support for a full-featured RPC mechanism via Google protocol buffers (using Skeet's protobuf-csharp-port):