Skip to content

Commit 3f12d56

Browse files
committed
Readme and package readme files updated.
1 parent a235b1f commit 3f12d56

2 files changed

Lines changed: 76 additions & 145 deletions

File tree

README.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,18 +76,6 @@ public record MyEventData(string Message);
7676

7777
## API
7878

79-
### `WeakEvent<TEvent>`
80-
* `Subscribe(Action<TEvent> handler)`\
81-
`Subscribe(Func<TEvent, Task> handler)`\
82-
`Subscribe(Func<TEvent, CancellationToken, Task> handler)`\
83-
Subscribes the specified handler to the event. The handler will be invoked when the event is raised, provided that its target is still alive.
84-
* `Unsubscribe(Action<TEvent> handler)`\
85-
`Unsubscribe(Func<TEvent, Task> handler)`\
86-
`Unsubscribe(Func<TEvent, CancellationToken, Task> handler)`\
87-
Unsubscribes the specified handler from the event.
88-
* `PublishAsync(TEvent eventData, CancellationToken cancellationToken = default)`\
89-
Raises the event by invoking all live subscribers with the provided event data. Dead subscribers (whose targets have been garbage-collected) are removed.
90-
9179
### `WeakEvent`
9280
* `Subscribe(Action handler)`\
9381
`Subscribe(Func<Task> handler)`\
@@ -100,6 +88,18 @@ public record MyEventData(string Message);
10088
* `PublishAsync(CancellationToken cancellationToken = default)`\
10189
Raises the event by invoking all live subscribers. Dead subscribers (whose targets have been garbage-collected) are removed.
10290

91+
### `WeakEvent<TEvent>`
92+
* `Subscribe(Action<TEvent> handler)`\
93+
`Subscribe(Func<TEvent, Task> handler)`\
94+
`Subscribe(Func<TEvent, CancellationToken, Task> handler)`\
95+
Subscribes the specified handler to the event. The handler will be invoked when the event is raised, provided that its target is still alive.
96+
* `Unsubscribe(Action<TEvent> handler)`\
97+
`Unsubscribe(Func<TEvent, Task> handler)`\
98+
`Unsubscribe(Func<TEvent, CancellationToken, Task> handler)`\
99+
Unsubscribes the specified handler from the event.
100+
* `PublishAsync(TEvent eventData, CancellationToken cancellationToken = default)`\
101+
Raises the event by invoking all live subscribers with the provided event data. Dead subscribers (whose targets have been garbage-collected) are removed.
102+
103103
## Contributing
104104

105105
We welcome all contributions! You can:

src/WeakEvent/PACKAGE.md

Lines changed: 64 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -1,160 +1,91 @@
1-
# ByteAether ULID
1+
# WeakEvent
22

3-
A high-performance .NET implementation of ULIDs (Universally Unique Lexicographically Sortable Identifiers) that fully complies with the [official ULID specification](https://github.com/ulid/spec).
3+
[![License](https://img.shields.io/github/license/ByteAether/WeakEvent?logo=github&label=License)](https://github.com/ByteAether/WeakEvent/blob/main/LICENSE)
4+
[![NuGet Version](https://img.shields.io/nuget/v/ByteAether.WeakEvent?logo=nuget&label=Version)](https://www.nuget.org/packages/ByteAether.WeakEvent/)
5+
[![NuGet Downloads](https://img.shields.io/nuget/dt/ByteAether.WeakEvent?logo=nuget&label=Downloads)](https://www.nuget.org/packages/ByteAether.WeakEvent/)
6+
[![GitHub Build Status](https://img.shields.io/github/actions/workflow/status/ByteAether/WeakEvent/build-and-test.yml?logo=github&label=Build%20%26%20Test)](https://github.com/ByteAether/WeakEvent/actions/workflows/build-and-test.yml)
7+
[![GitHub Security](https://img.shields.io/github/actions/workflow/status/ByteAether/WeakEvent/codeql.yml?logo=github&label=Security%20Validation)](https://github.com/ByteAether/WeakEvent/actions/workflows/codeql.yml)
48

5-
For more detailed documentation, visit our [GitHub repository](https://github.com/ByteAether/Ulid).
9+
WeakEvent is a lightweight .NET library that implements the weak event pattern using weak references. It ensures that event subscribers don't prevent garbage collection, avoiding memory leaks.
610

7-
## Features
11+
## Key Features
812

9-
![.NET 9.0](https://img.shields.io/badge/.NET-9.0-brightgreen)
10-
![.NET 8.0](https://img.shields.io/badge/.NET-8.0-brightgreen)
11-
![.NET 7.0](https://img.shields.io/badge/.NET-7.0-green)
12-
![.NET 6.0](https://img.shields.io/badge/.NET-6.0-green)
13-
![.NET 5.0](https://img.shields.io/badge/.NET-5.0-yellow)
14-
![.NET Standard 2.1](https://img.shields.io/badge/.NET-Standard_2.1-yellow)
15-
![.NET Standard 2.0](https://img.shields.io/badge/.NET-Standard_2.0-green)
13+
![.NET Standard 2.0](https://img.shields.io/badge/.NET_Standard-2.0-brightgreen)
1614

17-
- **Universally Unique**: Ensures global uniqueness across systems.
18-
- **Sortable**: Lexicographically ordered for time-based sorting.
19-
- **Fast and Efficient**: Optimized for high performance and low memory usage.
20-
- **Specification-Compliant**: Fully adheres to the ULID specification.
21-
- **Interoperable**: Includes conversion methods to and from GUIDs, [Crockford's Base32](https://www.crockford.com/base32.html) strings, and byte arrays.
22-
- **Error-Free Generation**: Prevents overflow exceptions by incrementing timestamps during random part overflow.
15+
- **Weak References:** Subscribers are held weakly so they can be garbage-collected when no longer in use.
16+
- **Events With or Without Data:** Choose between `WeakEvent` for notifications without data and `WeakEvent<TEvent>` for events that pass data.
17+
- **Automatic Cleanup:** Dead subscribers are removed automatically during event publishing.
18+
- **Simple API:** Intuitive methods for subscribing, unsubscribing, and publishing events.
2319

2420
## Installation
2521

26-
Install the latest stable package via NuGet:
22+
Install via NuGet:
2723

2824
```sh
29-
dotnet add package ByteAether.Ulid
25+
dotnet add package ByteAether.WeakEvent
3026
```
3127

32-
Use the `--version` option to specify a [preview version](https://www.nuget.org/packages/ByteAether.Ulid/absoluteLatest) to install.
28+
Use the `--version` option to specify a [preview version](https://www.nuget.org/packages/ByteAether.WeakEvent/absoluteLatest) to install.
3329

3430
## Usage
3531

36-
Here is a basic example of how to use the ULID implementation:
32+
### Using the `WeakEvent`
3733

3834
```csharp
39-
using System;
40-
41-
class Program
42-
{
43-
static void Main()
44-
{
45-
// Create a new ULID
46-
var ulid = Ulid.New();
47-
48-
// Convert to byte array and back
49-
byte[] byteArray = ulid.ToByteArray();
50-
var ulidFromByteArray = Ulid.New(byteArray);
51-
52-
// Convert to GUID and back
53-
Guid guid = ulid.ToGuid();
54-
var ulidFromGuid = Ulid.New(guid);
55-
56-
// Convert to string and back
57-
string ulidString = ulid.ToString();
58-
var ulidFromString = Ulid.Parse(ulidString);
59-
60-
Console.WriteLine($"ULID: {ulid}, GUID: {guid}, String: {ulidString}");
61-
}
62-
}
63-
```
64-
65-
## API
66-
67-
The `Ulid` implementation provides the following properties and methods:
68-
69-
### Creation
70-
71-
- `Ulid.New(bool isMonotonic = true)`\
72-
Generates a new ULID. If `isMonotonic` is `true`, ensures monotonicity during timestamp collisions.
73-
- `Ulid.New(DateTimeOffset dateTimeOffset, bool isMonotonic = true)`\
74-
Generates a new ULID using the specified `DateTimeOffset`.
75-
- `Ulid.New(long timestamp, bool isMonotonic = true)`\
76-
Generates a new ULID using the specified Unix timestamp in milliseconds (`long`).
77-
- `Ulid.New(DateTimeOffset dateTimeOffset, Span<byte> random)`\
78-
Generates a new ULID using the specified `DateTimeOffset` and a pre-existing random byte array.
79-
- `Ulid.New(long timestamp, Span<byte> random)`\
80-
Generates a new ULID using the specified Unix timestamp in milliseconds (`long`) and a pre-existing random byte array.
81-
- `Ulid.New(ReadOnlySpan<byte> bytes)`\
82-
Creates a ULID from an existing byte array.
83-
- `Ulid.New(Guid guid)`\
84-
Create from existing `Guid`.
85-
86-
### Checking Validity
87-
88-
- `Ulid.IsValid(string ulidString)`\
89-
Validates if the given string is a valid ULID.
90-
- `Ulid.IsValid(ReadOnlySpan<char> ulidString)`\
91-
Validates if the given span of characters is a valid ULID.
92-
- `Ulid.IsValid(ReadOnlySpan<byte> ulidBytes)`\
93-
Validates if the given byte array represents a valid ULID.
94-
95-
### Parsing
96-
97-
- `Ulid.Parse(ReadOnlySpan<char> chars, IFormatProvider? provider = null)`\
98-
Parses a ULID from a character span in canonical format. The `IFormatProvider` is ignored.
99-
- `Ulid.TryParse(ReadOnlySpan<char> s, IFormatProvider? provider, out Ulid result)`\
100-
Tries to parse a ULID from a character span in canonical format. Returns `true` if successful.
101-
- `Ulid.Parse(string s, IFormatProvider? provider = null)`\
102-
Parses a ULID from a string in canonical format. The `IFormatProvider` is ignored.
103-
- `Ulid.TryParse(string? s, IFormatProvider? provider, out Ulid result)`\
104-
Tries to parse a ULID from a string in canonical format. Returns `true` if successful.
105-
106-
### Properties
35+
using ByteAether.WeakEvent;
10736

108-
- `.Time`\
109-
Gets the timestamp component of the ULID as a `DateTimeOffset`.
110-
- `.TimeBytes`\
111-
Gets the time component of the ULID as a `ReadOnlySpan<byte>`.
112-
- `.Random`\
113-
Gets the random component of the ULID as a `ReadOnlySpan<byte>`.
37+
// Create an instance of the weak event without event data
38+
var myEvent = new WeakEvent();
11439

115-
### Conversion Methods
40+
// Create a subscriber and subscribe
41+
var subscriber = () => Console.WriteLine("Event received!");
42+
myEvent.Subscribe(subscriber);
11643

117-
- `.AsByteSpan()`\
118-
Provides a `ReadOnlySpan<byte>` representing the contents of the ULID.
119-
- `.ToByteArray()`\
120-
Converts the ULID to a byte array.
121-
- `.ToGuid()`\
122-
Converts the ULID to a `Guid`.
123-
- `.ToString(string? format = null, IFormatProvider? formatProvider = null)`\
124-
Converts the ULID to a canonical string representation. Format arguments are ignored.
125-
126-
### Comparison Operators
127-
128-
- Supports all comparison operators:\
129-
`==`, `!=`, `<`, `<=`, `>`, `>=`.
130-
- Implements standard comparison and equality methods:\
131-
`CompareTo`, `Equals`, `GetHashCode`.
132-
- Provides implicit operators to and from `Guid`.
133-
134-
## Integration with Other Libraries
135-
136-
### ASP.NET Core
137-
138-
Supports seamless integration as a route or query parameter with built-in `TypeConverter`.
139-
140-
### System.Text.Json
141-
142-
Includes a `JsonConverter` for easy serialization and deserialization.
44+
// Raise the event
45+
await myEvent.PublishAsync();
46+
```
14347

144-
### Other Libraries
48+
### Using the `WeakEvent<TEvent>`
14549

146-
Check out [README in GitHub repository](https://github.com/ByteAether/Ulid/blob/main/README.md) for examples to integrate with Entity Framework Core, Dapper, MessagePack and Newtonsoft.Json.
50+
```csharp
51+
using ByteAether.WeakEvent;
14752

148-
## Prior Art
53+
// Create an instance of the weak event with event data
54+
var myEvent = new WeakEvent<MyEventData>();
14955

150-
Much of this implementation is either based on or inspired by existing works. This library is standing on the shoulders of giants.
56+
// Create a subscriber and subscribe
57+
var subscriber = (MyEventData data) => Console.WriteLine("Received: " + data.Message);
58+
myEvent.Subscribe(subscriber);
15159

152-
* [NetUlid](https://github.com/ultimicro/netulid)
153-
* [Ulid](https://github.com/Cysharp/Ulid)
154-
* [NUlid](https://github.com/RobThree/NUlid)
155-
* [Official ULID specification](https://github.com/ulid/spec)
156-
* [Crockford's Base32](https://www.crockford.com/base32.html)
60+
// Raise the event
61+
await myEvent.PublishAsync(new MyEventData("Hello, World!"));
15762

158-
## License
63+
// Define your event data
64+
public record MyEventData(string Message);
65+
```
15966

160-
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
67+
## API Overview
68+
69+
### `WeakEvent`
70+
* `Subscribe(Action handler)`\
71+
`Subscribe(Func<Task> handler)`\
72+
`Subscribe(Func<CancellationToken, Task> handler)`\
73+
Subscribes the specified handler to the event. The handler will be invoked when the event is raised, provided that its target is still alive.
74+
* `Unsubscribe(Action handler)`\
75+
`Unsubscribe(Func<Task> handler)`\
76+
`Unsubscribe(Func<CancellationToken, Task> handler)`\
77+
Unsubscribes the specified handler from the event.
78+
* `PublishAsync(CancellationToken cancellationToken = default)`\
79+
Raises the event by invoking all live subscribers. Dead subscribers (whose targets have been garbage-collected) are removed.
80+
81+
### `WeakEvent<TEvent>`
82+
* `Subscribe(Action<TEvent> handler)`\
83+
`Subscribe(Func<TEvent, Task> handler)`\
84+
`Subscribe(Func<TEvent, CancellationToken, Task> handler)`\
85+
Subscribes the specified handler to the event. The handler will be invoked when the event is raised, provided that its target is still alive.
86+
* `Unsubscribe(Action<TEvent> handler)`\
87+
`Unsubscribe(Func<TEvent, Task> handler)`\
88+
`Unsubscribe(Func<TEvent, CancellationToken, Task> handler)`\
89+
Unsubscribes the specified handler from the event.
90+
* `PublishAsync(TEvent eventData, CancellationToken cancellationToken = default)`\
91+
Raises the event by invoking all live subscribers with the provided event data. Dead subscribers (whose targets have been garbage-collected) are removed.

0 commit comments

Comments
 (0)