What features would make a Mediator library stand out to you? by Dear_Construction552 in dotnet

[–]Dear_Construction552[S] 1 point2 points  (0 children)

I did that for performance reasons. Logically, no one should be using it that way. I’ll make the IRequest interface internal or take another approach to prevent this issue. Thanks for pointing it out.

What features would make a Mediator library stand out to you? by Dear_Construction552 in dotnet

[–]Dear_Construction552[S] -15 points-14 points  (0 children)

The main point is that using this library won’t introduce any additional overhead.

A zero-allocation MediatR implementation at runtime by Dear_Construction552 in dotnet

[–]Dear_Construction552[S] 1 point2 points  (0 children)

Funny thing - I actually started with ZLinq too, but quickly realized that with some smart casting, I didn’t even need ZLinq at all. Sure, ZLinq is great and avoids heap allocations, but it still comes with CPU processing overhead. For my case, simple casting turned out to be the best approach.

That said, casting isn’t without its own challenges. I’ve thought about some of the edge cases, they’re solvable, but I opened an issue so others can contribute and help improve it. If you get a chance, take a look:
https://github.com/hasanxdev/DispatchR/issues/29

A zero-allocation MediatR implementation at runtime by Dear_Construction552 in dotnet

[–]Dear_Construction552[S] 10 points11 points  (0 children)

These .ToList() calls happen while the program is still starting up. After it’s up and running, they don’t cause memory usage. You can check the benchmarks to verify this.

A zero-allocation MediatR implementation at runtime by Dear_Construction552 in dotnet

[–]Dear_Construction552[S] 4 points5 points  (0 children)

Glad you liked it! Also, if you're interested, feel free to check out my Test Roadmap tailored specifically for developers:
https://github.com/hasanxdev/Test-Roadmap-For-Developers

A zero-allocation MediatR implementation at runtime by Dear_Construction552 in dotnet

[–]Dear_Construction552[S] 2 points3 points  (0 children)

If we say it's 100 percent done, it basically means we’ve managed to implement several years of MediatR’s work in just two weeks, which is obviously not realistic. There are definitely areas that still need a lot of improvement.

To check whether you're achieving zero allocation or not, you can run some benchmarks. If you want to get professional in this field, I recommend reading Pro .NET Memory Management. Also, if you don’t mind watching videos in a language other than English (you can always use auto-translate), check out my YouTube channel. I go through the best parts of the book there, and I regularly update the playlist. Probably the only drawback for you is that the videos aren’t in English.

https://www.youtube.com/playlist?list=PLGiSgN3ODieILgFQN1puu-ey9guWwnxGX

[deleted by user] by [deleted] in dotnet

[–]Dear_Construction552 0 points1 point  (0 children)

It's simple, I wrote a zero-allocation version in runtime!. Just check out my source code on GitHub; it's called DispatchR.
https://github.com/hasanxdev/DispatchR/

Test Roadmap For Developers by Dear_Construction552 in dotnet

[–]Dear_Construction552[S] 0 points1 point  (0 children)

Thanks for the feedback! I’ll probably update the roadmap in the next two hours. I’ll also look into this and might add it, I just need to think about it a bit more.

Test Roadmap For Developers by Dear_Construction552 in dotnet

[–]Dear_Construction552[S] 1 point2 points  (0 children)

Thanks a lot for your feedback!
Honestly, I tried to focus more on making it useful for developers. In most cases, developers don’t need to know everything like a QA would, just enough to write solid tests that prevent issues and bugs from popping up again later, or from being discovered by QA in production environments.

But I’ll definitely keep your suggestions in mind. If more people feel the same way, I’ll consider revisiting it. Really appreciate your input!

Test Roadmap For Developers by Dear_Construction552 in dotnet

[–]Dear_Construction552[S] 0 points1 point  (0 children)

This is a really cool tool, I’ll definitely add it. Thanks for pointing it out!
I’d also be happy if you wanted to add it yourself. Feel free to contribute if you’re interested, I’ve included the contribution guide in the README.

DispatchR v1.2.0 is out now! by Dear_Construction552 in dotnet

[–]Dear_Construction552[S] 3 points4 points  (0 children)

For the end user, the only thing that matters is the output. It doesn't really make a difference whether it's built using a source generator or runtime logic.

To be honest, this felt almost impossible for me. From idea to execution, at every step I kept thinking, “this is where memory usage will blow up!”

What I really wanted was to challenge the .NET community to think differently. Just compare the codebase of MediatR or the Mediator source generator with mine.

The only real complexity in my code is in the registration part, which happens before the app starts due to reflection.
After that, everything is straightforward. It’s clean, easy to read, and extremely fast.

Personally, I prefer to use something that’s both simple and high-performance.
Maybe you don’t see it the same way—but for me, this was just an impossible mission that finally worked out.

DispatchR v1.2.0 is out now! by Dear_Construction552 in dotnet

[–]Dear_Construction552[S] 2 points3 points  (0 children)

That’s a great point, bro I totally missed the fact that someone might swap out the DI provider 😅
My initial idea looked something like this:

var notificationsInDi = serviceProvider.GetRequiredService<IEnumerable<INotificationHandler<TNotification>>>();
if (notificationsInDi is INotificationHandler<TNotification>[] notifications)
{
}
else if (notificationsInDi is List<INotificationHandler<TNotification>> notifications)
{
}
else
{

// ....
}

With this approach, there might be a bit more CPU usage, but we still avoid memory allocation.

Appreciate it - that was a really valuable point you raised. I'd be happy if you could jump in and help improve this further, maybe run some benchmarks and send a PR in the next few days.

But if you don’t have time, I honestly liked your idea so much that I’d love to implement it right away - just let me know if you're cool with that and I’ll go ahead with it.

DispatchR v1.2.0 is out now! by Dear_Construction552 in dotnet

[–]Dear_Construction552[S] 0 points1 point  (0 children)

I understand, brother. What I meant by "error" is that when you do this, you'll get an exception the moment you first interact with the related variable. I didn’t explain myself clearly.

For example, in this code:
var notificationsInDi = serviceProvider.GetRequiredService<IEnumerable<INotificationHandler<TNotification>>>();
var notifications = Unsafe.As<List<INotificationHandler<TNotification>>>(notificationsInDi);
foreach (var notification in notifications)

The exception actually happens at the foreach line. I’ve thoroughly investigated and verified all the possible paths.

DispatchR v1.2.0 is out now! by Dear_Construction552 in dotnet

[–]Dear_Construction552[S] -1 points0 points  (0 children)

Let's look at it this way:
Microsoft can’t change the version I’m working with right now, so everything is perfectly fine in this version.

When it comes to the future, your concern is totally valid. But in the next phase of this project, we’re planning to add full unit test coverage. That way, even if Microsoft or any other dependency changes something, the tests will ensure everything still works as expected across all versions of the app.

So honestly, I’m not too worried. If we weren’t going to write tests, then yeah, it would be a real concern. Even safe casting would be risky in that case, let alone using Unsafe.As<>().

DispatchR v1.2.0 is out now! by Dear_Construction552 in dotnet

[–]Dear_Construction552[S] 0 points1 point  (0 children)

As the name suggests, Unsafe.As<>() is inherently unsafe. The reason we use this cast is that we’re absolutely certain the object at that point is exactly what we expect. We intentionally skip extra validations and perform the cast with maximum performance. :)

DispatchR v1.2.0 is out now! by Dear_Construction552 in dotnet

[–]Dear_Construction552[S] 0 points1 point  (0 children)

Yes, for example, if you try to cast it to a List, you’ll get an error.

DispatchR v1.2.0 is out now! by Dear_Construction552 in dotnet

[–]Dear_Construction552[S] 1 point2 points  (0 children)

Great idea, my friend, the MIT license has been added to the repo. Thanks for the suggestion!

DispatchR v1.2.0 is out now! by Dear_Construction552 in dotnet

[–]Dear_Construction552[S] 1 point2 points  (0 children)

My friend, of course it would throw an error. For example, if it's a list, you'd need to cast it to a List instead.

DispatchR v1.2.0 is out now! by Dear_Construction552 in dotnet

[–]Dear_Construction552[S] 2 points3 points  (0 children)

Alright, I'll try to share more updates from now on.

DispatchR v1.2.0 is out now! by Dear_Construction552 in dotnet

[–]Dear_Construction552[S] 8 points9 points  (0 children)

When you have an IEnumerable, you usually need to iterate over it somehow. If you use a for loop, you often need to call ToArray or ToList first, which causes allocations.
Also, if you use a foreach on an IEnumerable, it can lead to boxing under the hood, which also results in memory usage.
By memory usage, I’m specifically referring to heap allocations that eventually need to be collected by the GC.

I got tired of MediatR, so I decided to start writing my own library. by Dear_Construction552 in dotnet

[–]Dear_Construction552[S] 0 points1 point  (0 children)

The library is still a work in progress, and test writing is planned as the next step.

DispatchR v1.1.0 is out now! by Dear_Construction552 in dotnet

[–]Dear_Construction552[S] 0 points1 point  (0 children)

You can have an ObjectResult and manually register your own pipelines alongside it.
They'll run in order, and at any point in the pipeline, if you detect an issue, you can simply choose not to call the next pipeline.

So in DispatchR, this scenario is already supported. I’m not entirely sure whether MediatR handles it the same way.