AdvancedRpcLib 1.0.0
See the version list below for details.
dotnet add package AdvancedRpcLib --version 1.0.0
NuGet\Install-Package AdvancedRpcLib -Version 1.0.0
<PackageReference Include="AdvancedRpcLib" Version="1.0.0" />
paket add AdvancedRpcLib --version 1.0.0
#r "nuget: AdvancedRpcLib, 1.0.0"
// Install AdvancedRpcLib as a Cake Addin #addin nuget:?package=AdvancedRpcLib&version=1.0.0 // Install AdvancedRpcLib as a Cake Tool #tool nuget:?package=AdvancedRpcLib&version=1.0.0
AdvancedRPC
AdvancedRPC is a remote procedure call library for .NET. It differs from common solutions like REST, GRPC or WebSockets in that it supports an object hierarchy similar to .NET Remoting. I wrote the library mainly as a replacement for .NET Remoting to make our corporate application ready for .NET Core. It relies heavily on the ability to make remote procedure calls on objects.
Features
- Communication via TCP and Named Pipes
- Support for impersonation with Named Pipes
- Deep object hierarchies
- Events and callbacks
- No need for serialization annotations, just publish an interface
- Support for multiple clients with notification on connection and disconnection
- .NET 4.8, .NET Standard 2.0 and .NET Standard 2.1
- Very easy to setup: No need to start a web service or define proto files. Just define an interface that is shared between applications and you are ready.
Example
Common interface definition
public interface IRpcServer
{
IRpcObject CreateObject(string name);
}
public interface IRpcObject
{
string Name { get; }
void ChangeName(string name);
event NameChanged;
}
Server implementation
class RpcServer : IRpcServer
{
IRpcObject CreateObject(string name)
{
return RpcObjectImpl(name);
}
}
class RpcObjectImpl : IRpcObject
{
public RpcObjectImpl(string name)
{
Name = name;
}
string Name { get; private set; }
void ChangeName(string name)
{
Name = name;
NameChanged?.Invoke(this, EventArgs.Empty);
}
event NameChanged;
}
class Program
{
static async Task Main(string[] args)
{
var server = new NamedPipeRpcServerChannel(new BinaryRpcSerializer(),
new RpcMessageFactory(), "myipcchannelname");
server.ObjectRepository.RegisterSingleton<RpcServer>();
await server.ListenAsync();
Console.WriteLine("Press key to quit");
Console.ReadKey();
}
}
Client implementation
class Program
{
static async Task Main(string[] args)
{
var client = new NamedPipeRpcClientChannel(new BinaryRpcSerializer(),
new RpcMessageFactory(), "myipcchannelname");
await client.ConnectAsync(TimeSpan.FromSeconds(5));
var rpcServerObj = await client.GetServerObjectAsync<IRpcServer>();
var nameObj = rpcServerObj.CreateObject("Jon Doe")
nameObj.NameChanged += (sender, e) => Console.WriteLine(((IRpcObject)sender).Name);
// This calls the method on the server and invokes
// the event NameChanged on the client.
nameObj.ChangeName("Jane Doe");
Console.WriteLine("Press key to quit");
Console.ReadKey();
}
}
See unit tests for more advanced scenarios.
Some Notes
- If you return a plain static object that doesn't need to know about server changes, use the
Serializable
attribute on the implementation. In that case the object will be serialized and copied to the client or server without creating a proxy object. This can be more efficient for data objects if you have a lot of properties and deep hierarchies. This behaves like a REST call. - Do not return or pass IEnumerable, as this will result in a remote call for every
MoveNext
when iterating over it. Instead, use an array in those cases. - Watch out for memory leaks. AdvancedRPC handles a lot of scenarios for you but take care to remove your event listeners.
- CAREFUL! Every remote call can throw an exception if the server goes down.
Restrictions
- Method overloads with same parameter count are not supported (yet). Overloads with different parameter count are possible though.
- Named Pipe impersonation limitations:
- doesn't work with .NET Standard 2.0 (for now)
- only works on Windows
IEnumerable
doesn't work for .NET Core (the interfaces use ByRef Values). There might be a workaround to support this.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 is compatible. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 is compatible. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETFramework 4.8
- Microsoft.Extensions.Logging.Abstractions (>= 3.1.5)
-
.NETStandard 2.0
- Microsoft.Extensions.Logging.Abstractions (>= 3.1.5)
- System.IO.Pipes.AccessControl (>= 4.5.1)
- System.Reflection.Emit (>= 4.7.0)
-
.NETStandard 2.1
- Microsoft.Extensions.Logging.Abstractions (>= 3.1.5)
- System.IO.Pipes.AccessControl (>= 4.5.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
1.0.0 Initial release