{"id":13430576,"url":"https://github.com/RxDave/Qactive","last_synced_at":"2025-03-16T06:30:32.497Z","repository":{"id":83510820,"uuid":"53762529","full_name":"RxDave/Qactive","owner":"RxDave","description":"Reactive queryable observable framework.","archived":false,"fork":false,"pushed_at":"2017-10-13T02:46:54.000Z","size":630,"stargazers_count":157,"open_issues_count":23,"forks_count":20,"subscribers_count":18,"default_branch":"master","last_synced_at":"2024-05-29T14:39:23.394Z","etag":null,"topics":["expression-tree","observable","qbservable","reactive","rx","service"],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RxDave.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2016-03-13T01:49:21.000Z","updated_at":"2024-04-10T01:34:55.000Z","dependencies_parsed_at":"2023-06-16T14:00:15.851Z","dependency_job_id":null,"html_url":"https://github.com/RxDave/Qactive","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RxDave%2FQactive","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RxDave%2FQactive/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RxDave%2FQactive/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RxDave%2FQactive/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RxDave","download_url":"https://codeload.github.com/RxDave/Qactive/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221656309,"owners_count":16858737,"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":["expression-tree","observable","qbservable","reactive","rx","service"],"created_at":"2024-07-31T02:00:55.316Z","updated_at":"2024-10-27T09:30:21.700Z","avatar_url":"https://github.com/RxDave.png","language":"C#","readme":"# Qactive\nA reactive queryable observable framework.\n\u003cimg align=\"right\" src=\"https://raw.githubusercontent.com/RxDave/Qactive/master/Artifacts/Logo2.png\" /\u003e\n\n* **Runtime:** .NET Framework 4.6.1; 4.5.2 (portable); 4.0\n* **Development:** Visual Studio 2017 and C# 7\n* **Dependencies:** [Reactive Extensions (Rx.NET)](https://github.com/Reactive-Extensions/Rx.NET)\n\n## Download from NuGet\n\u003e [Qactive.Providers.Tcp](https://www.nuget.org/packages/qactive.providers.tcp)  \n\u003e Depends on Rx, Qactive.Providers.Streaming, Qactive.Expressions and Qactive  \n\u003e Runtimes: .NET Framework 4.6.1; 4.5.2; 4.0\n\n\u003e [Qactive.Providers.Streaming](https://www.nuget.org/packages/qactive.providers.streaming)  \n\u003e Depends on Rx, Qactive.Expressions and Qactive  \n\u003e Runtimes: .NET Framework 4.6.1; 4.5.2; 4.0\n\n\u003e [Qactive](https://www.nuget.org/packages/qactive)  \n\u003e Depends on Rx  \n\u003e Runtimes: .NET Framework 4.6.1; 4.5.2; 4.0, ASP.NET Core 1.0, Windows 8, Windows Phone 8.1, Xamarin.Android, Xamarin.iOS\n\n\u003e [Qactive.Expressions](https://www.nuget.org/packages/qactive.expressions)  \n\u003e No dependencies  \n\u003e Runtimes: .NET Framework 4.6.1; 4.5.2; 4.0\n\n## Overview\nQactive builds on Reactive Extension's queryable observable providers, enabling you to write elegant reactive queries in LINQ that execute server-side, even though they are written on the client.\nQactive makes the extremely powerful act of querying a reactive service as easy as writing a typical Rx query.\n\nMore specifically, Qactive enables you to easily expose `IQbservable\u003cT\u003e` services for clients to query. When a client defines a query and subscribes, a connection is made to the server and the \nserialized query is transmitted to the server as an expression tree. The server deserializes the expression tree and executes it as a standing query. Any output from the query is marshaled back \nto the client over a persistent, full-duplex connection. Members on closures and static members that are local to the client are invoked from within the service automatically via full-duplex \nmessaging. Anonymous types are automatically serialized as well.\n\nFor more information, see [this series of blog posts](http://davesexton.com/blog/page/TCP-Qbservable-Provider-Series.aspx).\n\n\u003e **Warning:** Qactive allows clients to execute arbitrary code on your server.\n\u003e There are security mechanisms in place by default to prevent malicious clients but only to a point, \n\u003e it hasn't been fully considered yet. Do not expose a Qbservable service on a public server without \n\u003e taking the necessary precautions to secure it first.\n\n\u003e See [Security Guidelines](Artifacts/Security%20Guidelines.md) for more information.\n\n## Features\n\nPlease refer to the [list of features](../../wiki/Features) in the wiki.\n\n## Getting Started\nQactive is a set of .NET class libraries that you can reference in your projects. NuGet is recommended.\n\nAdd a reference to the **Qactive.Providers.Tcp** package in your Visual Studio project. That package references the other packages as dependencies, so NuGet will automatically download all of them for you.\n\n\u003e **Note:** Currently, the TCP provider is the only provider available.\n\nThe source code's [Examples](Examples/) folder contains projects that show various usages of Qactive, from a simple query over a timer to a real-time chat application.\n\n### To run the examples:\n1. Run _QbservableServer.exe_.\n  1. The server will start hosting example Qbservable services as soon as the console application begins.\n  1. Pressing a key at any time will stop the server.\n1. Run _QbservableClient.exe_.\n  1. You can run several client console applications at the same time.\n1. When the client console application starts, press any key to connect to the server.  The client will begin running the first example.\n1. Press any key to stop the current example and start the following example.\n\n### To build the source code:\n1. Set the *QbservableServer* project as the startup project.\n1. Build and run. The server will start as soon as the console application begins.\n1. Set the *QbservableClient* project as the startup project.\n1. Build and run. You can run several client console applications at the same time.\n1. When the client console application starts, press any key to connect to the server.\n\n\u003e **Tip:** To see the original and rewritten expression trees, run the client application with the debugger attached and look at the **Output** window.\n\n## Simple Example\nThe following example creates a _cold_ observable sequence that generates a new notification every second and exposes it as an `IQbservable\u003clong\u003e` service over TCP port 3205 on the local computer.\n\n### Server\n```c#\nIObservable\u003clong\u003e source = Observable.Interval(TimeSpan.FromSeconds(1));\n\nvar service = source.ServeQbservableTcp(new IPEndPoint(IPAddress.Loopback, 3205));\n\nusing (service.Subscribe(\n  client =\u003e Console.WriteLine(\"Client shutdown.\"),\n  ex =\u003e Console.WriteLine(\"Fatal error: {0}\", ex.Message),\n  () =\u003e Console.WriteLine(\"This will never be printed because a service host never completes.\")))\n{\n  Console.ReadKey();\n}\n```\nThe following example creates a LINQ query over the `IQbservable\u003clong\u003e` service that is created by the previous example.  Subscribing to the query on the client causes the query to be serialized to the server and executed there.  In other words, the `where` clause is actually executed on the server so that the client only receives the data that it requested without having to do any filtering itself.  The client will receive the first six values, one per second.  The server then filters out the next 2 values - it does not send them to the client.  Finally, the remaining values are sent to the client until either the client or the server disposes of the subscription.\n\n### Client\n```c#\nvar client = new TcpQbservableClient\u003clong\u003e(new IPEndPoint(IPAddress.Loopback, 3205));\n\nIQbservable\u003clong\u003e query =\n  from value in client.Query()\n  where value \u003c= 5 || value \u003e= 8\n  select value;\n\nusing (query.Subscribe(\n  value =\u003e Console.WriteLine(\"Client observed: \" + value),\n  ex =\u003e Console.WriteLine(\"Error: {0}\", ex.Message),\n  () =\u003e Console.WriteLine(\"Completed\")))\n{\n  Console.ReadKey();\n}\n```\n","funding_links":[],"categories":["Frameworks, Libraries and Tools","框架, 库和工具","Functional Programming"],"sub_categories":["Functional Programming","响应式编程"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRxDave%2FQactive","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FRxDave%2FQactive","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRxDave%2FQactive/lists"}