tylerjensen/ServiceWire

Avoid dynamic code generation by providing a custom Proxy implementation

RendijsSmukulis opened this issue · 5 comments

This idea stems from me using ServiceWire in .Net 5 with CoreRT compiler, attempting to do ahead-of-time compilation to an unmanaged library.

CoreRT currently does not allow dynamic code generation:

Unhandled Exception: System.PlatformNotSupportedException: Dynamic code generation is not supported on this platform.
   at LightspaceCompositorServiceClientNative!<BaseAddress>+0x15e5f5
   at ServiceWire.ProxyFactory.CreateProxyBuilder(String, Type, Type, Type) + 0x3b
   at ServiceWire.PooledDictionary`2.Request(TKey, Func`1) + 0xce
   at ServiceWire.ProxyFactory.CreateProxy[TInterface](Type, Type, Object, ISerializer) + 0x10d
   at ServiceWire.NamedPipes.NpProxy.CreateProxy[TInterface](NpEndPoint, ISerializer) + 0x47
   at LightspaceCompositorServiceClientNative!<BaseAddress>+0x1823a7

As such, I am looking to implement a mechanism to avoid calls to CreateProxy, and instead provide an existing Proxy implementation.

A couple questions:

  1. If I succeed, would you be interested in a pull request on the feature?
  2. Any tips on what to consider while implementing this - any underwater stones I might hit, and not see right now?

I would be happy to look at a pull request. At first blush, this seems like the user of the library would have to build the proxy based on known types in advance. I'm also not certain that supporting WinRT is going to be all that important to most users of the library.

Perhaps you can share with me why you want to use ServiceWire with WinRT?

We'll be using this to create a plugin for an unmanaged Windows app to communicate with a managed process, so it's not related to WinRT. I've tested a few RPC options, and ServiceWire with named pipes seems to be the one with lowest latency. To avoid writing a wrapper in C++/CLI, we're using AOT compilation to create a native dll.

From what I've seen, I can save the types generated in the Proxy builder with something like:

AssemblyBuilder asm = dom.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave);
[..]
            Type finished = asmType.CreateType();
            asm.Save(asmName.Name + ".dll");

As far as I can tell, this can be automated, so that the Proxy builder produces the auto-generated assembly dll during compile time, I'd just need to extend the interface a bit to provide the pre-compiled proxy object during runtime.

Honestly it's not a primary use case for the library. The dynamic assembly created when the client in created is part of it's charm. Generating the physical assembly may have merit for your use case, but I would want to review it carefully and make it optional rather than the default behavior. I look forward to seeing the PR.

Closing this as an edge case that will not be resolved in the library.