Files
esiur-dotnet/Libraries/Esiur/README.md
T
2026-07-17 02:19:05 +03:00

6.8 KiB
Raw Blame History

Esiur

Esiur is a distributed object and resource library that facilitates real-time property modification, asynchronous function invocation, and event handling across different languages, primarily in C#, JavaScript, and Dart. It's designed for flexible, scalable, and efficient communication between client and server, suitable for applications that need rapid, bidirectional data updates and complex data handling.

Key Features

Real-Time Property Modification:

Allows resources to update properties in real-time across distributed environments, ensuring that changes on one side are immediately reflected on the other.

Asynchronous Function Invocation:

Supports async instance and static functions that are triggered across distributed nodes, allowing non-blocking operations and efficient resource management.

Event Handling:

Built-in event system enables objects to raise events and propagate them across the network, making it easy to subscribe to or respond to specific events as they happen.

Wide Range of Data Types:

Esiur supports extensive data types for transmission and representation, including primitive types, lists, maps, enums, tuples and nullable types.

The library allows complex data structures to be transferred seamlessly, ensuring consistency and compatibility across different systems.

Inheritance and Generic Types:

Enables inheritance, so you can define base types and extend them, enhancing code reuse and flexibility.

Supports generics, allowing for strong type definitions and collections, ensuring data integrity and reducing errors.

Self-Describing API:

Esiur provides a self-describing API that allows the client to introspect services and resources, discovering properties, methods, and events at runtime. This feature enables dynamic and versatile usage patterns, as the client can adjust based on available functionalities without precompiled knowledge of them.

Multi-Language Support

Esiur has implementations in C#, JavaScript, and Dart, making it highly versatile for different platforms, including desktop, web, and mobile environments. This cross-platform compatibility enables developers to use it in various client-server and P2P distributed systems where real-time data handling is essential.

Example Use Cases

  • IoT Networks: Seamlessly update and control device properties across a network, with real-time monitoring and updates.
  • Game Development: Enable multiplayer synchronization of game states and events, ensuring real-time feedback for interactive experiences.
  • Financial Services: Support real-time, distributed data sharing for trading platforms or monitoring systems where latency is critical.

Esiurs robust, feature-rich approach allows developers to focus on building applications without worrying about the complexities of distributed systems, while its self-describing API and broad data type support enable flexible and scalable application design.

Installation

  • Nuget Install-Package Esiur
  • Command-line dotnet add package Esiur

Getting Started

Esiur for C# uses source generator feature of .Net framework to implement the necessary calls for property modification, which means a class must be marked as "partial" so the library automatically creates setters and getters for every property exported to the public.

MyResource.cs

[Resource]
public partial class HelloResource {
   // Esiur will generate a property with name `Counts` 
   [Export] int counts; 
   [Export] public string SayHi(string msg) {
       Counts++;
       GreetingReceived?.Invoke(msg);
       return $"Welcome, current time {DateTime.Now}";
   }
   [Export] public ResourceEventHandler<string> GreetingReceived;
}

Setting up the server

Esiur resources are arranged into stores (IStore) and accessed using paths similar to a Unix file system. Each store is responsible for keeping its resources in memory, files, or a database.

This example creates a Warehouse and uses the built-in MemoryStore, which keeps its resources in RAM.

var warehouse = new Warehouse();
await warehouse.Put("sys", new MemoryStore());

Now we can add our resource to the memory store using warehouse.Put.

await warehouse.Put("sys/hello", new HelloResource());

Add an EpServer to expose the resource through the Esiur EP protocol. Anonymous access is enabled here only to make the development example easy to run; production applications should configure an authentication provider.

await warehouse.Put("sys/server", new EpServer
{
    AllowUnauthorizedAccess = true, // Development only.
});

Finally, open the Warehouse to initialize the system.

await warehouse.Open();

To sum up

Program.cs

using Esiur.Protocol;
using Esiur.Resource;
using Esiur.Stores;

var warehouse = new Warehouse();
await warehouse.Put("sys", new MemoryStore());
await warehouse.Put("sys/hello", new HelloResource());
await warehouse.Put("sys/server", new EpServer
{
   AllowUnauthorizedAccess = true, // Development only.
});
await warehouse.Open();

Setting up the client

To access our resource remotely, we need to use it's full path including the protocol, host and instance link.

var warehouse = new Warehouse();
dynamic res = await warehouse.Get<IResource>("ep://localhost/sys/hello");

Now we can invoke the exported functions and read/write properties;

    var reply = await res.SayHi("Hi, I'm calling you from dotnet");
    Console.WriteLine(reply);
    Console.WriteLine($"Number of people said hi {res.Counts}");

Summing up

Program.cs

using Esiur.Resource;

var warehouse = new Warehouse();
dynamic res = await warehouse.Get<IResource>("ep://localhost/sys/hello");

var reply = await res.SayHi("Hi, I'm calling you from dotnet");

Console.WriteLine(reply);
Console.WriteLine($"Number of people said hi {res.Counts}");

Getting Types

In the above client example, we relied on Esiur support for dynamic objects, but this way the developer would need to know the functions, properties and events available given to them as API docs or inspect it in debugging mode.

Esiur has a self describing feature which comes with every language it supports, allowing the developer to fetch and generate classes that match the ones on the other side (i.e. server).

After installing the Esiur NuGet package, a new command named Get-Types is added to the Visual Studio Package Manager Console. It generates client-side classes for robust static typing.

Get-Types ep://localhost/sys/hello

This will generate and add wrappers for all types needed by our resource.

Allowing us to use

var warehouse = new Warehouse();
var res = await warehouse.Get<MyResource>("ep://localhost/sys/hello");
var reply = await res.SayHi("Static typing is better");
Console.WriteLine(reply);