There are two things that make the R type provider tricky:
When you use R provider via NuGet and the F# compiler references the R provider, it attempts to load it from the location where NuGet puts it. This is typically
packages/RProvider.1.0.8/lib. This directory does not contain
RDotNet.dll(which is installed in
packages/R.NET.1.3.5/lib/net40) and so the loading could fail.
To avoid this, we need to make sure that the assembly that is loaded by the F# compiler (and Visual Studio) does not trigger loading of R.NET immediately - that way, we can setup
AssemblyResolveevent handler and load R.NET assembly from another directory.
Connecting to R is not entirely stable and so we do not want to crash the F# compiler (or Visual Studio) when something goes wrong with R. For this reason, we run the type discovery in a separate process and communicate with it via .NET remoting.
To solve the two issues outlined above, the project structure looks like this:
Things to keep in mind
Here is what you need to know about individual assemblies in the solution:
RProvider.Runtime.dll- this is the assembly that contains most of the interesting runtime functionality (such as initialization of R, interop with R and converters that convert values between F# and R). It also contains helpers (logging, etc.).
This assembly references R.NET in its public assemblies and so when it is loaded, .NET needs to be able to load R.NET (i.e. the
AssemblyResolveevent handler needs to be set up).
RProvider.dll- this is the assembly that the user of R provider will reference. It does not contain any useful code - it only contains
TypeProviderAssemblyattribute pointing to the assembly with the actual type provider code.
Note that we cannot put the functionality from
RProvider.Runtime.dllhere, because the code needs to be referenced by the other two assemblies (that are compiled before the type provider can be loaded).
RProvider.DesignTime.dll- this is where the type provider code lives. This sets up
AssemblyResolveevent handler and then it generates types (by calling the
RProvider.Server.exeto do the type discovery).
RProvider.Server.exe- this is started as a stand-alone process that performs type and package discovery in R. It is called by the DesignTime component and restarted automatically. This also needs to setup the