{"id":15780918,"url":"https://github.com/menees/remoting","last_synced_at":"2026-01-24T04:33:39.594Z","repository":{"id":140488888,"uuid":"451552925","full_name":"menees/Remoting","owner":"menees","description":"Simple RMI and IPC library for modern .NET","archived":false,"fork":false,"pushed_at":"2024-10-16T23:39:51.000Z","size":255,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-10-18T22:14:00.059Z","etag":null,"topics":["inter-process-communication","ipc","remote-method-invocation","remote-procedure-call","rmi","rpc"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/menees.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-01-24T16:57:07.000Z","updated_at":"2024-10-16T23:39:54.000Z","dependencies_parsed_at":null,"dependency_job_id":"cd0b0bad-5291-4f37-8e12-a8dfd98a1fe3","html_url":"https://github.com/menees/Remoting","commit_stats":{"total_commits":89,"total_committers":2,"mean_commits":44.5,"dds":"0.011235955056179803","last_synced_commit":"e609180b81595c60798854087862f5b19e37ccdb"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/menees%2FRemoting","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/menees%2FRemoting/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/menees%2FRemoting/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/menees%2FRemoting/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/menees","download_url":"https://codeload.github.com/menees/Remoting/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243547642,"owners_count":20308747,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["inter-process-communication","ipc","remote-method-invocation","remote-procedure-call","rmi","rpc"],"created_at":"2024-10-04T19:00:37.614Z","updated_at":"2026-01-24T04:33:34.575Z","avatar_url":"https://github.com/menees.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"![windows build \u0026 test](https://github.com/menees/Remoting/workflows/windows%20build%20\u0026%20test/badge.svg) [![Nuget](https://img.shields.io/nuget/v/Menees.Remoting)](https://www.nuget.org/packages/Menees.Remoting/)\n\n# Remoting\nThis repo provides a simple [RMI](https://en.wikipedia.org/wiki/Remote_method_invocation) and [IPC](https://en.wikipedia.org/wiki/Inter-process_communication)\nlibrary for .NET 8.0+ applications. It's designed to help ease the migration from legacy [WCF](https://en.wikipedia.org/wiki/Windows_Communication_Foundation)\nand [.NET Remoting](https://en.wikipedia.org/wiki/.NET_Remoting) when porting code from .NET Framework to modern .NET. However, this library doesn't try to do\n[all the things](https://knowyourmeme.com/memes/all-the-things) like WCF and .NET Remoting.\n\nMenees.Remoting:\n* Prefers simplicity over performance.\n* Is designed for non-chatty communication.\n* Can't pass or return a .NET reference directly.\n* Requires values to be serialized going to and from the server.\n* Uses named pipes and a serializer of your choice (default is [System.Text.Json](https://docs.microsoft.com/en-us/dotnet/api/system.text.json)).\n* Doesn't use or care about MarshalByRefObject, OperationContract, ServiceContract, etc.\n\n## RMI\nMenees.Remoting provides [RmiClient](src/Menees.Remoting/RmiClient.cs) to invoke .NET interface methods in a remote [RmiServer](src/Menees.Remoting/RmiServer.cs).\nThe server process exposes a .NET interface for a given instance object. Then one or more client processes invoke .NET interface methods on the server's instance object.\n.NET's [DispatchProxy.Create](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.dispatchproxy.create) is used to generate the interface proxy, so clients can invoke \nthe interface methods as normal C# calls.\n\n``` C#\n[TestMethod]\npublic void HasherExample()\n{\n    const string ServerPath = \"Menees.Remoting.RmiClientTests.HasherExample\";\n\n    using RmiServer\u003cIHasher\u003e server = new(new Hasher(), ServerPath);\n    server.Start();\n\n    using RmiClient\u003cIHasher\u003e client = new(ServerPath);\n    IHasher proxy = client.CreateProxy();\n\n    proxy.Hash(new byte[] { 1, 2, 3, 4 }).Length.ShouldBe(20);\n    proxy.Hash(\"Testing\").ShouldBe(\"0820b32b206b7352858e8903a838ed14319acdfd\");\n}\n\ninternal interface IHasher\n{\n    byte[] Hash(byte[] data);\n    string Hash(string text);\n}\n\ninternal class Hasher : IHasher\n{\n    public byte[] Hash(byte[] data)\n    {\n        using HashAlgorithm hasher = SHA1.Create();\n        return hasher.ComputeHash(data);\n    }\n\n    public string Hash(string text)\n    {\n        byte[] hash = this.Hash(Encoding.UTF8.GetBytes(text));\n        return string.Concat(hash.Select(b =\u003e $\"{b:x2}\"));\n    }\n}\n```\n\nFor more usage examples see:\n* [RmiClientTests](tests/Menees.Remoting.Tests/RmiClientTests.cs)\n* [RmiServerTests](tests/Menees.Remoting.Tests/RmiServerTests.cs)\n\nDue to the synchronous API of the underlying\n[DispatchProxy.Invoke](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.dispatchproxy.invoke) method, all the client invocations are sent\nsynchronously to the server. The `RmiClient` can't do asynchronous calls to the `RmiServer` due to risks with\n[sync over async](https://devblogs.microsoft.com/pfxteam/should-i-expose-synchronous-wrappers-for-asynchronous-methods/).\nFor more on DispatchProxy's lack of InvokeAsync support see [#19349](https://github.com/dotnet/runtime/issues/19349)\nand the comments for [Migrating RealProxy Usage to DispatchProxy](https://devblogs.microsoft.com/dotnet/migrating-realproxy-usage-to-dispatchproxy/).\n\n## IPC\nMenees.Remoting provides [MessageClient](src/Menees.Remoting/MessageClient.cs) to send a `TIn`-typed request message to\na [MessageServer](src/Menees.Remoting/MessageServer.cs) and receive a `TOut`-typed response message. Message IPC only\nsupports asynchronous calls, and the server requires a lambda that takes a `TIn` and returns a `Task\u003cTOut\u003e`.\n\n``` C#\n[TestMethod]\npublic async Task Base64ExampleAsync()\n{\n    const string ServerPath = \"Menees.Remoting.MessageNodeTests.Base64ExampleAsync\";\n\n    using MessageServer\u003cbyte[], string\u003e server = new(data =\u003e Task.FromResult(Convert.ToBase64String(data)), ServerPath);\n    server.Start();\n\n    using MessageClient\u003cbyte[], string\u003e client = new(ServerPath);\n    string response = await client.SendAsync(new byte[] { 1, 2, 3, 4 }).ConfigureAwait(false);\n    response.ShouldBe(\"AQIDBA==\");\n}\n```\n\nFor more usage examples see:\n* [MessageNodeTests](tests/Menees.Remoting.Tests/MessageNodeTests.cs)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmenees%2Fremoting","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmenees%2Fremoting","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmenees%2Fremoting/lists"}