Adding code for RInterop v2.0 (#2)

* Adding code for RInterop v2.0

* Updates

* Configuration updates

* Readme update.

* Readme update.

* Update README.md

* Update README.md
This commit is contained in:
rohit-joy 2017-03-23 14:07:44 -07:00 коммит произвёл GitHub
Родитель adb5e1f5a5
Коммит a893431e1c
26 изменённых файлов: 626 добавлений и 331 удалений

9
Logging/ILogger.cs Normal file
Просмотреть файл

@ -0,0 +1,9 @@
namespace Logging
{
public interface ILogger
{
void LogInformation(string message);
void LogError(string message);
void Close();
}
}

58
Logging/Logging.csproj Normal file
Просмотреть файл

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{DA0E6A71-5A37-4EE6-87A4-C82C93EF908D}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Logging</RootNamespace>
<AssemblyName>Logging</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\RInterop\GlobalAssemblyInfo.cs">
<Link>GlobalAssemblyInfo.cs</Link>
</Compile>
<Compile Include="ILogger.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TraceLogger.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

Просмотреть файл

@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Logging")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Logging")]
//[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("da0e6a71-5a37-4ee6-87a4-c82c93ef908d")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
//[assembly: AssemblyVersion("1.0.0.0")]
//[assembly: AssemblyFileVersion("1.0.0.0")]

Просмотреть файл

@ -6,12 +6,10 @@ using System.IO;
using System.Security.AccessControl;
using System.Security.Principal;
namespace RInterop
namespace Logging
{
public class TraceLogger : ILogger
{
private TraceSource TraceSource { get; }
public TraceLogger(string rootFolder, string prefix)
{
TraceSource = new TraceSource(prefix, SourceLevels.All);
@ -21,8 +19,8 @@ namespace RInterop
string logFilePath = Path.Combine(rootFolder,
string.Format(CultureInfo.InvariantCulture, "{0}_{1}.log",
prefix,
DateTime.UtcNow.Ticks));
prefix,
DateTime.UtcNow.Ticks));
Trace.AutoFlush = true;
@ -65,7 +63,9 @@ namespace RInterop
newLogFilename = f.FullName;
break;
}
catch { } // This log file is in use -- try next
catch
{
} // This log file is in use -- try next
}
// If we didn't find a reusable log file, we'll create a new using the next available log file number
@ -77,17 +77,20 @@ namespace RInterop
Path.GetDirectoryName(Path.Combine(Environment.CurrentDirectory, logFilePath)),
Path.GetFileNameWithoutExtension(logFilePath),
maxLogFileNumber.ToString("000", CultureInfo.InvariantCulture),
Path.GetExtension(logFilePath)); // e.g. "logFilename.001.log"
Path.GetExtension(logFilePath)); // e.g. "logFilename.001.log"
}
if (File.Exists(newLogFilename)) { File.Delete(newLogFilename); }
if (File.Exists(newLogFilename))
{
File.Delete(newLogFilename);
}
// Hook up the log file as a trace listener
FileStream fstream = new FileStream(newLogFilename,
FileMode.Create,
FileSystemRights.WriteData,
FileShare.Read,
(int)Math.Pow(2, 10),
(int) Math.Pow(2, 10),
FileOptions.None,
GetFileSecurity());
@ -96,6 +99,26 @@ namespace RInterop
TraceSource.Listeners.Add(traceListener);
}
private TraceSource TraceSource { get; }
public void LogInformation(string message)
{
TraceSource.TraceEvent(TraceEventType.Information, 0, string.Format(CultureInfo.InvariantCulture, "{0:O} {1}", DateTime.UtcNow,
message));
}
public void LogError(string message)
{
TraceSource.TraceEvent(TraceEventType.Error, 0, string.Format(CultureInfo.InvariantCulture, "{0:O} {1}", DateTime.UtcNow,
message));
}
public void Close()
{
TraceSource.Flush();
TraceSource.Close();
}
public static FileSecurity GetFileSecurity()
{
var fss = new FileSecurity();
@ -154,41 +177,18 @@ namespace RInterop
return fss;
}
public void LogInformation(string message, params object[] parameters)
{
TraceSource.TraceInformation(string.Format(CultureInfo.InvariantCulture, "{0:O} {1}", DateTime.UtcNow, message, parameters));
}
public void Close()
{
TraceSource.Flush();
TraceSource.Close();
}
private string GetCallingFunction()
{
StackFrame frame = new StackTrace().GetFrame(3);
var declaringType = frame.GetMethod().DeclaringType;
if (declaringType != null)
{
string callingFunction = string.Format(CultureInfo.InvariantCulture, "{0}.{1}", declaringType.FullName, frame.GetMethod().Name);
return callingFunction;
}
return string.Empty;
}
}
/// <summary>
/// Used to sort an array of FileInfo objects by filename.
/// </summary>
class CompareFileInfoNames : IComparer
internal class CompareFileInfoNames : IComparer
{
public int Compare(object x, object y)
{
FileInfo firstFile = (FileInfo)x;
FileInfo secondFile = (FileInfo)y;
FileInfo firstFile = (FileInfo) x;
FileInfo secondFile = (FileInfo) y;
return string.CompareOrdinal(firstFile.FullName, secondFile.FullName);
}
}
}
}

Просмотреть файл

@ -2,50 +2,63 @@
.NET managed abstraction layer for communicating with R
## Installation
#### [x86]: <https://github.com/Microsoft/R-Interop/releases/download/v1.1.41577.1/RInteropSetup-x86.msi>
#### [x64]: <https://github.com/Microsoft/R-Interop/releases/download/v1.1.41577.1/RInteropSetup-x64.msi>
Please note that there are breaking changes in terms of how RInterop works as well as command line arguments it takes in to start up.
#### <https://github.com/Microsoft/R-Interop/releases/download/v2.0/RInteropSetup.msi>
## Command-line arguments
```sh
```
--schema Path to schema binary file containing types to serialize and deserialize input data and output data sent to and received from the R package, respectively
--s Same as -schema
--rpackage Path to R package file containing statistical functions (optional if packages are already installed)
--r Same as --rpackage
--typemap Mapping from R function to input and output type schema.
--t Same as --typemap
```
## Example
```sh
RInterop.exe --r C:\RPackages\MyStatsPackage_0.1.zip --s C:\RPackages\Schemas.dll
```
RInterop.exe --r C:\RPackages\MyStatsPackage_0.1.zip --s C:\RPackages\Schemas.dll --t C:\RPackages\TypeMap.json
```
## Overview
R Interop starts a WCF service with named-pipe endpoints for inter process communication. Your application talks to R Interop through the named pipe. The following are the steps involved:
1. Client application sends request to R Interop as an Input object
2. R Interop serializes the input object and sends the request to R package loaded in R
3. R function evaluates the input object and returns the output
4. R Interop deserializes the output and returns to client application
1. Client application sends request to R Interop as an Input object.
2. R Interop serializes the input object and sends the request to R package loaded in R.
3. R function evaluates the input object and returns the output.
4. R Interop deserializes the output and returns it to client application.
Note that both the client application and RInterop utilize the same Schemas library so that they can understand each other.
## Named pipe endpoints
R Interop makes available 3 endpoints.
R Interop makes available 2 endpoints.
#### net.pipe://RInterop/
Metadata endpoint for generating a service reference
#### net.pipe://RInterop/Initialize
R Interop communicates with R through a simple JSON serialization/deserialization contract. The contract with R package expects an input type, an output type and the R function name, at minimum. There are two dictionaries - one for Input and one for Output - that enable this contract to be successfully created between the client application and R Interop. The key for the dictionary is the R function name. The value is the type provided in the class library passed as the --schema parameter.
For example, use the following code to initialize the type mapping for the R function.
```sh
Dictionary<string, string> inputMap["DistributionTest"] = "Schemas.TTest.Input";
Dictionary<string, string> outputMap["DistributionTest"] = "Schemas.TTest.Output";
RClient client = new RClient("NetNamedPipeBinding_IR1");
client.Initialize(inputMap, outputMap);
client.Close();
```
Call the Initialize endpoint to pass the input and output type Dictionary mapping for each of your R functions.
Metadata exchange (MEX) endpoint for generating a service reference within the client or caller application.
#### net.pipe://RInterop/Execute
Executes the R function provided in the Input object with members describing the parameters. Returns the result as the Output type. The types are as described in the dictionaries initialized when calling the endpoint net.pipe://RInterop/Initialize
Executes the R function provided in the Input object with members describing the parameters. Returns the result as the corresponding Output type. The types are as described in the dictionaries provided in TypeMap.json that map to the types in the Schemas assembly.
The format of TypeMap.json is as follows:
```
{
"Mapping": [
{
"Function": "TTest",
"InputType": "Schemas.TTest.Input",
"OutputType": "Schemas.TTest.Output"
},
{
"Function": "ChiSquareTest",
"InputType": "Schemas.ChiSquareTest.Input",
"OutputType": "Schemas.ChiSquareTest.Output"
}
]
}
```
## Windows events for developers
When RInterop starts up successfully, it will fire an event named ```Global\RInteropStarted```.
When RInterop is unable to start up successfully, it will fire an event named ```Global\RInteropStartupError``` and exit. The logs located in the ```%temp%\RInterop``` folder will help diagnose and/or resolve issues. Feel free to post questions on Github.

Просмотреть файл

@ -5,6 +5,8 @@ VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RInterop", "RInterop\RInterop.csproj", "{EC24722E-AEC0-42D9-B5ED-300137236355}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Logging", "Logging\Logging.csproj", "{DA0E6A71-5A37-4EE6-87A4-C82C93EF908D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -15,6 +17,10 @@ Global
{EC24722E-AEC0-42D9-B5ED-300137236355}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EC24722E-AEC0-42D9-B5ED-300137236355}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EC24722E-AEC0-42D9-B5ED-300137236355}.Release|Any CPU.Build.0 = Release|Any CPU
{DA0E6A71-5A37-4EE6-87A4-C82C93EF908D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DA0E6A71-5A37-4EE6-87A4-C82C93EF908D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DA0E6A71-5A37-4EE6-87A4-C82C93EF908D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DA0E6A71-5A37-4EE6-87A4-C82C93EF908D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

105
RInterop/Bootstrapper.cs Normal file
Просмотреть файл

@ -0,0 +1,105 @@
using System;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using Logging;
using Newtonsoft.Json;
namespace RInterop
{
public class Bootstrapper : IBootstrapper
{
private readonly ILogger _logger = DependencyFactory.Resolve<ILogger>();
public void Start(string[] args)
{
if (args == null) throw new ArgumentNullException(nameof(args));
_logger.LogInformation(string.Format(CultureInfo.InvariantCulture, "Working directory: {0}",
Environment.CurrentDirectory));
_logger.LogInformation(string.Format(CultureInfo.InvariantCulture, "Arguments: {0}", string.Join(" ", args)));
var options = new CommandLineOptions();
if (!CommandLineOptions.ParseArguments(args, options))
{
_logger.LogError(string.Format(CultureInfo.InvariantCulture, "Invalid arguments {0}",
string.Join(" ", args)));
LogUsage();
return;
}
Config.SchemaBinaryPath = options.SchemaBinaryPath;
Assembly assembly = Assembly.LoadFrom(Config.SchemaBinaryPath);
if (!string.IsNullOrEmpty(options.RPackagePath))
{
try
{
var filename = Path.GetFileName(options.RPackagePath);
if (!string.IsNullOrEmpty(filename))
Config.RPackageName = filename.Substring(0, filename.IndexOf("_", StringComparison.Ordinal));
}
catch (Exception exception)
{
_logger.LogError(string.Format(CultureInfo.InvariantCulture,
"Exiting. Exception while extracting R package name: {0}", exception));
LogUsage();
return;
}
try
{
REngineWrapper.InstallPackages(options.RPackagePath);
}
catch (Exception exception)
{
EventWaitHandle startupErrorEvent = new EventWaitHandle(false, EventResetMode.ManualReset,
@"Global\RInteropStartupError");
startupErrorEvent.Set();
_logger.LogError(string.Format(CultureInfo.InvariantCulture,
"Exiting. Exception while installing packages: {0}", exception));
return;
}
}
if (!string.IsNullOrEmpty(options.TypeMapJsonPath))
{
Config.SerializationTypeMap = new SerializationTypeMap();
if (!string.IsNullOrEmpty(options.TypeMapJsonPath))
{
TypeMap o =
JsonConvert.DeserializeObject<TypeMap>(new StreamReader(options.TypeMapJsonPath).ReadToEnd());
foreach (Map i in o.Mapping)
{
DependencyFactory.Resolve<ILogger>()
.LogInformation(string.Format(CultureInfo.InvariantCulture,
"Got input type mapping: {0} > {1} > {2}", i.Function, i.InputType, i.OutputType));
Config.SerializationTypeMap.InputTypeMap[i.Function] = assembly
.GetTypes()
.First(a => a.FullName.Equals(i.InputType));
Config.SerializationTypeMap.OutputTypeMap[i.Function] = assembly
.GetTypes()
.First(a => a.FullName.Equals(i.OutputType));
}
}
}
using (var service = new Service())
{
service.Start();
service.StartedEvent.WaitOne();
}
}
private void LogUsage()
{
_logger.LogInformation(
@"Usage: RInterop.exe --s ""<path to schema.dll>"" --r ""<path to R package file>""");
_logger.LogInformation(
@"Example: RInterop.exe --s ""C:\Temp\Schemas.dll"" --r ""C:\Temp\RPackage.zip"" --t ""C:\Temp\TypeMap.json""");
}
}
}

Просмотреть файл

@ -1,44 +1,65 @@
using CommandLine;
using System;
using System.Globalization;
using System.IO;
using CommandLine;
using Logging;
namespace RInterop
{
public class CommandLineOptions
{
[Option('s', "schema", Required = true,
HelpText = "Path to schema binary file containing types to serialize and deserialize input data and output data sent to and received from the R package, respectively")]
HelpText =
"Path to schema binary file containing types to serialize and deserialize input data and output data sent to and received from the R package, respectively"
)]
public string SchemaBinaryPath { get; set; }
[Option('r', "rpackage", Required = true,
HelpText = "Path to R package file containing statistical functions (optional if packages are already installed)")]
[Option('r', "rpackage", Required = false,
HelpText =
"Path to R package file containing statistical functions (optional if packages are already installed)")]
public string RPackagePath { get; set; }
[Option('t', "typemap", Required = false,
HelpText = "Path to JSON file with type map (optional)")]
public string TypeMapJsonPath { get; set; }
// Omitting long name, default --verbose
[Option(HelpText = "Prints all messages to standard output.")]
public bool Verbose { get; set; }
public static bool ParseArguments(string[] args, CommandLineOptions options)
{
if (args == null) throw new ArgumentNullException(nameof(args));
if (options == null) throw new ArgumentNullException(nameof(options));
var logger = DependencyFactory.Resolve<ILogger>();
if (!Parser.Default.ParseArguments(args, options))
{
return false;
}
if (!File.Exists(options.RPackagePath))
{
logger.LogInformation(string.Format(CultureInfo.InvariantCulture, "RPackage {0} not found", options.RPackagePath));
return false;
}
if (!File.Exists(options.SchemaBinaryPath))
{
logger.LogInformation(string.Format(CultureInfo.InvariantCulture, "Schema binary {0} not found", options.SchemaBinaryPath));
logger.LogInformation(string.Format(CultureInfo.InvariantCulture, "Schema binary {0} not found",
options.SchemaBinaryPath));
return false;
}
if (!string.IsNullOrEmpty(options.RPackagePath) && !File.Exists(options.RPackagePath))
{
logger.LogInformation(string.Format(CultureInfo.InvariantCulture, "R Package {0} not found",
options.RPackagePath));
return false;
}
if (!string.IsNullOrEmpty(options.TypeMapJsonPath) && !File.Exists(options.TypeMapJsonPath))
{
logger.LogInformation(string.Format(CultureInfo.InvariantCulture, "Type Map JSON file {0} not found",
options.TypeMapJsonPath));
return false;
}
return true;
}
}
}
}

Просмотреть файл

@ -6,6 +6,6 @@
public static string RPackageName { get; set; }
public static SerializationTypeMaps SerializationTypeMaps { get; set; }
public static SerializationTypeMap SerializationTypeMap { get; set; }
}
}

Просмотреть файл

@ -1,36 +1,25 @@
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
using System.Configuration;
using Logging;
using Microsoft.Practices.Unity;
namespace RInterop
{
public class DependencyFactory
{
public static IUnityContainer Container { get; private set; }
static DependencyFactory()
public static void Initialize()
{
var container = new UnityContainer();
var section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section?.Configure(container);
Container = container;
Container.RegisterType<ILoggerFactory>("TraceLoggerFactory",
new InjectionFactory(c => new TraceLoggerFactory()));
Container.RegisterInstance<ILogger>(
Container
.Resolve<ILoggerFactory>("TraceLoggerFactory")
.Create("RInterop"));
Container.RegisterInstance<ILogger>(new TraceLogger("%temp%", "RInterop"));
Resolve<ILogger>().LogInformation("Completed registering dependencies");
}
public static IUnityContainer Container { get; private set; }
public static T Resolve<T>()
{
T ret = default(T);
if (Container.IsRegistered(typeof(T)))
if (Container.IsRegistered(typeof (T)))
{
ret = Container.Resolve<T>();
}
@ -38,4 +27,4 @@ namespace RInterop
return ret;
}
}
}
}

Просмотреть файл

@ -10,7 +10,7 @@
[assembly: System.Reflection.AssemblyCopyright("Copyright (c) Microsoft Corporation 2016")]
[assembly: System.CLSCompliant(false)]
[assembly: System.Reflection.AssemblyVersion("1.1.41577.4")]
[assembly: System.Reflection.AssemblyFileVersion("1.1.41577.4")]
[assembly: System.Reflection.AssemblyVersion("1.2.3.4")]
[assembly: System.Reflection.AssemblyFileVersion("1.2.3.4")]

Просмотреть файл

@ -0,0 +1,7 @@
namespace RInterop
{
public interface IBootstrapper
{
void Start(string[] args);
}
}

Просмотреть файл

@ -1,9 +0,0 @@
namespace RInterop
{
public interface ILogger
{
void LogInformation(string message, params object[] parameters);
void Close();
}
}

Просмотреть файл

@ -1,9 +0,0 @@
namespace RInterop
{
public interface ILoggerFactory
{
ILogger Create(string prefix);
ILogger Create(string rootFolder, string prefix);
}
}

Просмотреть файл

@ -1,16 +1,12 @@
using System.Collections.Generic;
using System.ServiceModel;
using System.ServiceModel;
namespace RInterop
{
[ServiceContract]
[ServiceKnownType("GetKnownTypes", typeof(KnownTypesProvider))]
[ServiceKnownType("GetKnownTypes", typeof (KnownTypesProvider))]
public interface IR
{
[OperationContract]
object Execute(dynamic input);
[OperationContract]
void Initialize(Dictionary<string, string> inputTypeMap, Dictionary<string, string> outputTypeMap);
}
}
}

21
RInterop/Models.bond Normal file
Просмотреть файл

@ -0,0 +1,21 @@
namespace RInterop
using Type = int64;
struct SerializationTypeMap
{
0: map<string, Type> InputTypeMap;
1: map<string, Type> OutputTypeMap;
}
struct Map
{
0: string Function;
1: string InputType;
2: string OutputType;
}
struct TypeMap
{
0: vector<Map> Mapping;
}

Просмотреть файл

@ -1,96 +1,13 @@
using System;
using System.Globalization;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Threading;
namespace RInterop
namespace RInterop
{
class Program
public class Program
{
public static void Main(string[] args)
{
ILogger logger = DependencyFactory.Resolve<ILogger>();
DependencyFactory.Initialize();
logger.LogInformation(string.Format(CultureInfo.InvariantCulture, "Working directory: {0}", Environment.CurrentDirectory));
logger.LogInformation(string.Format(CultureInfo.InvariantCulture, "Arguments: {0}", string.Join(" ", args)));
var options = new CommandLineOptions();
if (!CommandLineOptions.ParseArguments(args, options))
{
DependencyFactory.Resolve<ILogger>().LogInformation(string.Format(CultureInfo.InvariantCulture, "Invalid arguments {0}", string.Join(" ", args)));
logger.LogInformation(@"Usage: RInterop.exe --s ""<path to schema.dll>"" --r ""<path to R package file>""");
logger.LogInformation(@"Example: RInterop.exe --s ""C:\Temp\Schemas.dll"" --r ""C:\Temp\RPackage.zip""");
logger.LogInformation("Press any key to continue...");
Console.ReadLine();
return;
}
try
{
var filename = Path.GetFileName(options.RPackagePath);
Config.RPackageName = filename.Substring(0, filename.IndexOf("_", StringComparison.Ordinal));
}
catch (Exception exception)
{
logger.LogInformation("Exception while extracting R package name: {0}", exception);
return;
}
Config.SchemaBinaryPath = options.SchemaBinaryPath;
REngineWrapper.InstallPackages(options.RPackagePath, options.SchemaBinaryPath);
StartService();
}
private static void StartService()
{
EventWaitHandle startedEvent = new EventWaitHandle(false, EventResetMode.ManualReset, @"Global\RInteropStarted");
using (ServiceHost host = new ServiceHost(typeof(R), new Uri("net.pipe://RInterop")))
{
NetNamedPipeBinding binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
binding.MaxReceivedMessageSize = Int32.MaxValue;
binding.MaxBufferSize = Int32.MaxValue;
host.AddServiceEndpoint(typeof(IR),
binding,
"Execute");
host.AddServiceEndpoint(typeof(IR),
binding,
"Initialize");
// Check to see if the service host already has a ServiceMetadataBehavior
ServiceMetadataBehavior smb = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
// If not, add one
if (smb == null)
smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = false;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(smb);
// Add MEX endpoint
host.AddServiceEndpoint(
ServiceMetadataBehavior.MexContractName,
MetadataExchangeBindings.CreateMexNamedPipeBinding(),
"mex");
// Add application endpoint
host.AddServiceEndpoint(typeof(IR), new NetNamedPipeBinding(), "");
host.Open();
startedEvent.Set();
DependencyFactory.Resolve<ILogger>().LogInformation("Service is available. Press <ENTER> to exit.");
Console.ReadLine();
host.Close();
}
var bootstrapper = new Bootstrapper();
bootstrapper.Start(args);
}
}
}
}

Просмотреть файл

@ -9,7 +9,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("RInterop")]
//[assembly: AssemblyCopyright("Copyright © 2016")] // Added in generated GlobalAssemblyInfo.cs file
//[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
//[assembly: AssemblyVersion("0.4.7.0")] // Added in generated GlobalAssemblyInfo.cs file
//[assembly: AssemblyFileVersion("0.4.7.0")] // Added in generated GlobalAssemblyInfo.cs file
//[assembly: AssemblyVersion("0.4.7.0")]
//[assembly: AssemblyFileVersion("0.4.7.0")]

Просмотреть файл

@ -1,16 +1,17 @@
using Newtonsoft.Json;
using RDotNet;
using System;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.ServiceModel;
using Logging;
using Newtonsoft.Json;
using RDotNet;
namespace RInterop
{
[ServiceBehavior(
ConcurrencyMode = ConcurrencyMode.Multiple,
ConcurrencyMode = ConcurrencyMode.Multiple,
IncludeExceptionDetailInFaults = true,
InstanceContextMode = InstanceContextMode.PerCall)]
public class R : IR
@ -21,72 +22,65 @@ namespace RInterop
private readonly ILogger _logger;
private readonly bool _shouldLogCommand;
private readonly bool _shouldLogResult;
public R() : this(DependencyFactory.Resolve<ILogger>())
{
_engine = REngineWrapper.REngine;
}
public R(ILogger logger)
{
_logger = logger;
_shouldLogCommand = Convert.ToBoolean(ConfigurationManager.AppSettings["LogCommand"]);
_shouldLogResult = Convert.ToBoolean(ConfigurationManager.AppSettings["LogResult"]);
}
public object Execute(dynamic input)
{
// R.Net's REngine cannot perform parallel evaluation of R scripts
lock(LockObject)
lock (LockObject)
{
try
{
Type inputType = Config.SerializationTypeMaps.InputTypeMap[input.config.fn];
Type outputType = Config.SerializationTypeMaps.OutputTypeMap[input.config.fn];
Type inputType = Config.SerializationTypeMap.InputTypeMap[input.config.fn];
Type outputType = Config.SerializationTypeMap.OutputTypeMap[input.config.fn];
object deserializedInput = Convert.ChangeType(input, inputType);
var command = string.Format(CultureInfo.InvariantCulture,
"{0}::run(\"{1}\")",
@"{0}::run(""{1}"")",
Config.RPackageName,
JsonConvert.SerializeObject(deserializedInput).Replace("\"", "\\\""));
if (_shouldLogCommand) _logger.LogInformation(string.Format(CultureInfo.InvariantCulture, "Command: {0}", command));
_logger.LogInformation(string.Format(CultureInfo.InvariantCulture, "Evaluating: {0}", command));
var result = _engine
.Evaluate(command)
var result = _engine.Evaluate(command)
.AsList()
.First()
.AsCharacter()
.First();
_logger.LogInformation(string.Format(CultureInfo.InvariantCulture, "Result: {0}", result));
if (_shouldLogResult) _logger.LogInformation(string.Format(CultureInfo.InvariantCulture, "Result: {0}", result));
return JsonConvert.DeserializeObject(result, outputType);
}
catch (KeyNotFoundException e)
{
string reason = string.Format(CultureInfo.InvariantCulture,
@"Could not find function ""{0}"" in the TypeMap.json configuration. Exception: {1}",
input.config.fn, e);
_logger.LogError(reason);
throw new FaultException(new FaultReason(reason));
}
catch (Exception e)
{
_logger.LogInformation(string.Format(CultureInfo.InvariantCulture, "Exception during evaluation {0}", e));
return null;
string reason = string.Format(CultureInfo.InvariantCulture,
"Evaluation failed. Exception: {0}", e);
_logger.LogError(reason);
throw new FaultException(new FaultReason(reason));
}
}
}
public void Initialize(Dictionary<string, string> inputTypeMap, Dictionary<string, string> outputTypeMap)
{
Assembly assembly = Assembly.LoadFrom(Config.SchemaBinaryPath);
Config.SerializationTypeMaps = new SerializationTypeMaps();
foreach (string key in inputTypeMap.Keys)
{
Config.SerializationTypeMaps.InputTypeMap[key] = assembly
.GetTypes()
.First(a => a.FullName.Equals(inputTypeMap[key]));
_logger.LogInformation(string.Format(CultureInfo.InvariantCulture, "Got input type mapping: {0} > {1}", key, inputTypeMap[key]));
}
foreach (string key in outputTypeMap.Keys)
{
Config.SerializationTypeMaps.OutputTypeMap[key] = assembly
.GetTypes()
.First(a => a.FullName.Equals(outputTypeMap[key]));
_logger.LogInformation(string.Format(CultureInfo.InvariantCulture, "Got output type mapping: {0} > {1}", key, outputTypeMap[key]));
}
}
}
}
}

Просмотреть файл

@ -1,6 +1,9 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using Logging;
using RDotNet;
namespace RInterop
@ -10,7 +13,7 @@ namespace RInterop
private static REngine _engine;
private static readonly object LockObject = new object();
public static REngine REngine
{
get
@ -21,8 +24,6 @@ namespace RInterop
{
if (_engine == null)
{
var logger = DependencyFactory.Resolve<ILogger>();
_engine = REngine.GetInstance();
}
}
@ -32,34 +33,71 @@ namespace RInterop
}
}
public static void InstallPackages(string rPackagePath, string schemaBinaryPath)
public static void InstallPackages(string rPackagePath)
{
var engine = REngineWrapper.REngine;
var engine = REngine;
var logger = DependencyFactory.Resolve<ILogger>();
engine.Evaluate(string.Format(
CultureInfo.InvariantCulture,
var userDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "DEARPackages").Replace("\\", "/");
if (!Directory.Exists(userDirectory)) Directory.CreateDirectory(userDirectory);
engine.Evaluate($@".libPaths(""{userDirectory}"")");
engine.Evaluate(@".libPaths()");
engine.Evaluate(string.Format(CultureInfo.InvariantCulture,
@"install.packages(""{0}"", verbose = TRUE, dependencies = TRUE, type = ""win.binary"")",
rPackagePath.Replace(@"\", @"\\")));
logger.LogInformation(string.Format(CultureInfo.InvariantCulture, "Installed R package {0}", rPackagePath));
List<string> imports = engine
.Evaluate(@"packageDescription(""" + Config.RPackageName + @""")$Imports")
.AsCharacter()
.First()
.Replace(" ", string.Empty)
.Split(',')
.ToList();
logger.LogInformation(string.Format(CultureInfo.InvariantCulture, @"Installed R package ""{0}""", rPackagePath));
List<string> imports;
try
{
imports = engine
.Evaluate(string.Format(CultureInfo.InvariantCulture,
@"packageDescription(""{0}"")$Imports",
Config.RPackageName))
.AsCharacter()
.FirstOrDefault()?
.Replace(" ", string.Empty)
.Split(',')
.ToList();
}
catch (Exception e)
{
logger.LogInformation(string.Format(CultureInfo.InvariantCulture,
@"Could not get the dependent packages from provided package. Please manually install package using the ""install.packages"" command. Exception: {0}",
e));
throw;
}
if (imports == null) return;
foreach (string packageName in imports)
{
logger.LogInformation(string.Format(CultureInfo.InvariantCulture, "Installing dependent R package {0}", packageName));
engine.Evaluate(string.Format(CultureInfo.InvariantCulture,
@"if (!require(""{0}""))
install.packages(""{0}"", repo = ""https://cran.rstudio.com/"", dependencies = TRUE)",
logger.LogInformation(string.Format(CultureInfo.InvariantCulture,
@"Installing dependent R package ""{0}""",
packageName));
logger.LogInformation(string.Format(CultureInfo.InvariantCulture, "Installed R package {0}", packageName));
try
{
engine.Evaluate(string.Format(CultureInfo.InvariantCulture,
@"if (!require(""{0}""))
install.packages(""{0}"", repo = ""https://cran.rstudio.com/"", dependencies = TRUE)",
packageName));
engine.Evaluate(string.Format(CultureInfo.InvariantCulture,
@"if (!require(""{0}"")) stop(""Package {0} did not install correctly."")",
packageName));
}
catch (Exception e)
{
logger.LogInformation(string.Format(CultureInfo.InvariantCulture,
@"Could not automatically install dependent package ""{0}"". Please manually install R package using the following command: install.packages(""{0}"")
Exception: {1}",
packageName,
e));
throw;
}
logger.LogInformation(string.Format(CultureInfo.InvariantCulture, @"Installed dependent R package ""{0}""", packageName));
}
}
}
}
}

Просмотреть файл

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\Bond.CSharp.5.0.0\build\Bond.CSharp.props" Condition="Exists('..\packages\Bond.CSharp.5.0.0\build\Bond.CSharp.props')" />
<Import Project="..\packages\Bond.CSharp.5.2.0\build\Bond.CSharp.props" Condition="Exists('..\packages\Bond.CSharp.5.2.0\build\Bond.CSharp.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@ -27,6 +27,7 @@
<RunCodeAnalysis>true</RunCodeAnalysis>
<CodeAnalysisRuleSet>ManagedMinimumRules.ruleset</CodeAnalysisRuleSet>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<UseVSHostingProcess>false</UseVSHostingProcess>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@ -41,19 +42,23 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="Bond, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Bond.Core.CSharp.5.0.0\lib\net45\Bond.dll</HintPath>
<HintPath>..\packages\Bond.Core.CSharp.5.2.0\lib\net45\Bond.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Bond.Attributes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Bond.Core.CSharp.5.0.0\lib\net45\Bond.Attributes.dll</HintPath>
<HintPath>..\packages\Bond.Core.CSharp.5.2.0\lib\net45\Bond.Attributes.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Bond.IO, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Bond.Core.CSharp.5.0.0\lib\net45\Bond.IO.dll</HintPath>
<HintPath>..\packages\Bond.Core.CSharp.5.2.0\lib\net45\Bond.IO.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Bond.JSON, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Bond.Runtime.CSharp.5.0.0\lib\net45\Bond.JSON.dll</HintPath>
<HintPath>..\packages\Bond.Runtime.CSharp.5.2.0\lib\net45\Bond.JSON.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Bond.Reflection, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Bond.Core.CSharp.5.2.0\lib\net45\Bond.Reflection.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="CommandLine, Version=1.9.71.2, Culture=neutral, PublicKeyToken=de6f01bd326f8c32, processorArchitecture=MSIL">
@ -108,30 +113,34 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Bootstrapper.cs" />
<Compile Include="CommandLineOptions.cs" />
<Compile Include="Config.cs" />
<Compile Include="DependencyFactory.cs" />
<Compile Include="GlobalAssemblyInfo.cs" />
<Compile Include="ILogger.cs" />
<Compile Include="ILoggerFactory.cs" />
<Compile Include="IBootstrapper.cs" />
<Compile Include="IR.cs" />
<Compile Include="KnownTypesProvider.cs" />
<Compile Include="TraceLogger.cs" />
<Compile Include="TraceLoggerFactory.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="R.cs" />
<Compile Include="REngineWrapper.cs" />
<Compile Include="Service.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config">
<SubType>Designer</SubType>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="packages.config">
<SubType>Designer</SubType>
</None>
<BondCodegen Include="SerializationTypeMaps.bond" />
<BondCodegen Include="Models.bond" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Logging\Logging.csproj">
<Project>{da0e6a71-5a37-4ee6-87a4-c82c93ef908d}</Project>
<Name>Logging</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
@ -142,36 +151,35 @@
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Bond.CSharp.5.0.0\build\Bond.CSharp.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Bond.CSharp.5.0.0\build\Bond.CSharp.props'))" />
<Error Condition="!Exists('..\packages\Bond.CSharp.5.0.0\build\Bond.CSharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Bond.CSharp.5.0.0\build\Bond.CSharp.targets'))" />
<Error Condition="!Exists('..\packages\MSBuildTasks.1.5.0.214\build\MSBuildTasks.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSBuildTasks.1.5.0.214\build\MSBuildTasks.targets'))" />
<Error Condition="!Exists('..\packages\Bond.CSharp.5.2.0\build\Bond.CSharp.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Bond.CSharp.5.2.0\build\Bond.CSharp.props'))" />
<Error Condition="!Exists('..\packages\Bond.CSharp.5.2.0\build\Bond.CSharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Bond.CSharp.5.2.0\build\Bond.CSharp.targets'))" />
<Error Condition="!Exists('..\packages\MSBuildTasks.1.5.0.235\build\MSBuildTasks.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSBuildTasks.1.5.0.235\build\MSBuildTasks.targets'))" />
</Target>
<PropertyGroup>
<Major>1</Major>
<Minor>1</Minor>
</PropertyGroup>
<Choose>
<When Condition=" '$(BUILD_BUILDNUMBER)'=='' ">
<PropertyGroup>
<Build>$([MSBuild]::Modulo($([System.DateTime]::UtcNow.ToString("yyyyMMdd")), 65536))</Build>
<Revision>4</Revision>
<BUILD_BUILDNUMBER>$(Build).$(Revision)</BUILD_BUILDNUMBER>
</PropertyGroup>
</When>
<When Condition=" '$(BUILD_BUILDNUMBER)'!='' ">
<PropertyGroup>
<Major>2</Major>
<Minor>0</Minor>
<Build>$([MSBuild]::Modulo($([System.Math]::Floor($(BUILD_BUILDNUMBER))), 65536))</Build>
<Revision>$(BUILD_BUILDNUMBER.Substring($([MSBuild]::Add($(BUILD_BUILDNUMBER.IndexOf('.')), 1))))</Revision>
</PropertyGroup>
</When>
<When Condition=" '$(BUILD_BUILDNUMBER)'=='' ">
<PropertyGroup>
<Major>1</Major>
<Minor>2</Minor>
<Build>3</Build>
<Revision>4</Revision>
</PropertyGroup>
</When>
</Choose>
<Target Name="BeforeBuild">
<Message Text="AssemblyVersion: $(Major).$(Minor).$(Build).$(Revision)" />
<Message Text="AssemblyFileVersion: $(Major).$(Minor).$(BUILD_BUILDNUMBER)" />
<AssemblyInfo CodeLanguage="CS" OutputFile="GlobalAssemblyInfo.cs" AssemblyCopyright="Copyright (c) Microsoft Corporation 2016" AssemblyTrademark="" CLSCompliant="false" AssemblyVersion="$(Major).$(Minor).$(Build).$(Revision)" AssemblyFileVersion="$(Major).$(Minor).$(Build).$(Revision)" />
</Target>
<Import Project="..\packages\Bond.CSharp.5.0.0\build\Bond.CSharp.targets" Condition="Exists('..\packages\Bond.CSharp.5.0.0\build\Bond.CSharp.targets')" />
<Import Project="..\packages\MSBuildTasks.1.5.0.214\build\MSBuildTasks.targets" Condition="Exists('..\packages\MSBuildTasks.1.5.0.214\build\MSBuildTasks.targets')" />
<Import Project="..\packages\Bond.CSharp.5.2.0\build\Bond.CSharp.targets" Condition="Exists('..\packages\Bond.CSharp.5.2.0\build\Bond.CSharp.targets')" />
<Import Project="..\packages\MSBuildTasks.1.5.0.235\build\MSBuildTasks.targets" Condition="Exists('..\packages\MSBuildTasks.1.5.0.235\build\MSBuildTasks.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">

Просмотреть файл

@ -1,9 +0,0 @@
namespace RInterop
using Type = int64;
struct SerializationTypeMaps
{
0: map<string, Type> InputTypeMap;
1: map<string, Type> OutputTypeMap;
}

64
RInterop/Service.cs Normal file
Просмотреть файл

@ -0,0 +1,64 @@
using System;
using System.Globalization;
using System.ServiceModel;
using System.Threading;
using Logging;
namespace RInterop
{
public class Service : IDisposable
{
private readonly EventWaitHandle _startedEvent;
public Service()
{
_startedEvent = new EventWaitHandle(false, EventResetMode.ManualReset,
@"Global\RInteropStarted");
}
public EventWaitHandle StartedEvent => _startedEvent;
public void Start()
{
try
{
using (ServiceHost host = new ServiceHost(typeof (R)))
{
host.Closed += HostOnClosed;
host.Faulted += HostOnFaulted;
host.Opened += HostOnOpened;
host.Open();
Console.ReadLine();
host.Close();
}
}
catch (Exception e)
{
DependencyFactory.Resolve<ILogger>().LogInformation(string.Format(CultureInfo.InvariantCulture,
"RInterop hit an unexpected exception. Exception: {0}", e));
}
}
private void HostOnClosed(object sender, EventArgs eventArgs)
{
DependencyFactory.Resolve<ILogger>().LogInformation("RInterop has shutdown.");
}
private void HostOnFaulted(object sender, EventArgs eventArgs)
{
DependencyFactory.Resolve<ILogger>().LogInformation("RInterop is in faulted state.");
}
private void HostOnOpened(object sender, EventArgs eventArgs)
{
DependencyFactory.Resolve<ILogger>().LogInformation("Service is available. Press <ENTER> to exit.");
_startedEvent.Set();
}
public void Dispose()
{
_startedEvent.Dispose();
}
}
}

Просмотреть файл

@ -1,15 +0,0 @@
namespace RInterop
{
public class TraceLoggerFactory : ILoggerFactory
{
public ILogger Create(string prefix)
{
return Create("%temp%", prefix);
}
public ILogger Create(string rootFolder, string prefix)
{
return new TraceLogger(rootFolder, prefix);
}
}
}

Просмотреть файл

@ -1,5 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="LogCommand" value="false" />
<add key="LogResult" value="true" />
</appSettings>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
@ -12,4 +16,56 @@
</dependentAssembly>
</assemblyBinding>
</runtime>
<system.web>
<httpCookies requireSSL="true"/>
<httpRuntime enableVersionHeader="false"/>
</system.web>
<system.serviceModel>
<bindings>
<netNamedPipeBinding>
<binding name="NamedPipeBinding_IR"
closeTimeout="00:05:00"
openTimeout="00:20:00"
receiveTimeout="01:00:00"
sendTimeout="01:00:00"
hostNameComparisonMode="StrongWildcard"
maxConnections="1000"
maxBufferPoolSize="2147483647"
maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="32"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
<security mode="None" />
</binding>
</netNamedPipeBinding>
</bindings>
<services>
<service name="RInterop.R" behaviorConfiguration="MEX">
<endpoint address="net.pipe://RInterop"
binding="netNamedPipeBinding"
bindingConfiguration="NamedPipeBinding_IR"
contract="RInterop.IR" />
<endpoint address="net.pipe://RInterop/mex"
binding="mexNamedPipeBinding"
contract="IMetadataExchange" />
<endpoint address="net.pipe://RInterop/Execute"
binding="netNamedPipeBinding"
bindingConfiguration="NamedPipeBinding_IR"
contract="RInterop.IR" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MEX">
<serviceMetadata httpGetEnabled="False" />
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>

Просмотреть файл

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Bond.Core.CSharp" version="5.0.0" targetFramework="net452" />
<package id="Bond.CSharp" version="5.0.0" targetFramework="net452" />
<package id="Bond.Runtime.CSharp" version="5.0.0" targetFramework="net452" />
<package id="Bond.Core.CSharp" version="5.2.0" targetFramework="net452" />
<package id="Bond.CSharp" version="5.2.0" targetFramework="net452" />
<package id="Bond.Runtime.CSharp" version="5.2.0" targetFramework="net452" />
<package id="CommandLineParser" version="1.9.71" targetFramework="net452" />
<package id="CommonServiceLocator" version="1.3" targetFramework="net452" />
<package id="DynamicInterop" version="0.7.4" targetFramework="net452" />
<package id="MSBuildTasks" version="1.5.0.214" targetFramework="net452" developmentDependency="true" />
<package id="MSBuildTasks" version="1.5.0.235" targetFramework="net452" developmentDependency="true" />
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" />
<package id="R.NET.Community" version="1.6.5" targetFramework="net452" />
<package id="Unity" version="4.0.1" targetFramework="net452" />