﻿
{"id":28202,"date":"2025-12-21T09:49:08","date_gmt":"2025-12-21T09:49:08","guid":{"rendered":"https:\/\/www.gencayyildiz.com\/blog\/?p=28202"},"modified":"2025-12-21T09:49:08","modified_gmt":"2025-12-21T09:49:08","slug":"mediatr-yerine-martinothamar-mediator-kutuphanesini-inceleyelim","status":"publish","type":"post","link":"https:\/\/www.gencayyildiz.com\/blog\/mediatr-yerine-martinothamar-mediator-kutuphanesini-inceleyelim\/","title":{"rendered":"MediatR Yerine &#8216;martinothamar\/Mediator&#8217; K\u00fct\u00fcphanesini \u0130nceleyelim"},"content":{"rendered":"<div id=\"fb-root\"><\/div>\n<p>Merhaba,<\/p>\n<p>Bu i\u00e7eri\u011fimizde <a href=\"https:\/\/www.gencayyildiz.com\/blog\/tag\/mediatr\/\" target=\"_blank\">MediatR<\/a> k\u00fct\u00fcphanesine alternatif olarak de\u011ferlendirebilece\u011fimiz <em>martinothamar\/Mediator<\/em> k\u00fct\u00fcphanesini hem teorik hem de pratik olarak inceleyecek, MediatR yerine nas\u0131l konumland\u0131\u011f\u0131n\u0131 en net \u015fekilde ele al\u0131yor olaca\u011f\u0131z.<\/p>\n<h4>martinothamar\/Mediator Nedir?<\/h4>\n<p><em>martinothamar\/Mediator<\/em>, .NET d\u00fcnyas\u0131nda MediatR&#8217;a bir alternatif olarak geli\u015ftirilen lightweight, performans odakl\u0131 ve allocation-free olan bir <a href=\"https:\/\/www.gencayyildiz.com\/blog\/c-mediator-design-patternmediator-tasarim-deseni\/\" target=\"_blank\">Mediator Pattern<\/a> implementasyonu k\u00fct\u00fcphanesidir. MediatR&#8217;a \u00e7ok benzer API yap\u0131s\u0131na sahip olsa da daha modern, source-generator altyap\u0131s\u0131na sahip ve <a href=\"https:\/\/www.gencayyildiz.com\/blog\/net-8-minimal-api-ahead-of-timeaot-compilation-template\/\" target=\"_blank\">AOT<\/a> dostu bir yap\u0131ya sahiptir.<\/p>\n<p>Amac\u0131;<\/p>\n<ul>\n<li>Request\/Response i\u015f ak\u0131\u015flar\u0131n\u0131 desteklemek,<\/li>\n<li>Notification\/Publish-Subscribe olay ak\u0131\u015flar\u0131n\u0131 desteklemek,<\/li>\n<li>Pipeline davran\u0131\u015flar\u0131n\u0131 desteklemektir.<\/li>\n<\/ul>\n<p>Ana \u00f6zellikleri ise;<\/p>\n<ul>\n<li>Source generator (compile-time code generation) kullanabilmektedir.<\/li>\n<li>Native AOT senaryolar\u0131na \u00f6zellikle uyumlu olacak \u015fekilde tasarlanm\u0131\u015ft\u0131r.<\/li>\n<li>Reflection kullanmadan dependency injection registry i\u015flemini ve IMediator implementasyonunu compile-time&#8217;da \u00fcretebilmektedir.<\/li>\n<\/ul>\n<p><strong>Kim taraf\u0131ndan geli\u015ftirilmi\u015ftir?<\/strong><br \/>\nK\u00fct\u00fcphanenin ana geli\u015ftiricisi <em>Martin Othamar<\/em> abimizdir. GitHub reposuda <a href=\"https:\/\/github.com\/martinothamar\/Mediator\" target=\"_blank\">https:\/\/github.com\/martinothamar\/Mediator<\/a> adresindedir.<\/p>\n<h4>.NET&#8217;de Kullan\u0131m\u0131<\/h4>\n<p>Mediator k\u00fct\u00fcphanesini kullanabilmek i\u00e7in \u00f6ncelikle gerekli paketleri<br \/>\n<a href=\"https:\/\/www.nuget.org\/packages\/Mediator.Abstractions\/3.1.0-preview.14\" target=\"_blank\">dotnet add package Mediator.Abstractions<\/a><br \/>\nve<br \/>\n<a href=\"https:\/\/www.nuget.org\/packages\/Mediator.SourceGenerator\/3.1.0-preview.14\" target=\"_blank\">dotnet add package Mediator.SourceGenerator<\/a><br \/>\ntalimatlar\u0131 e\u015fli\u011finde ilgili projeye y\u00fckleyiniz.<\/p>\n<p>Ard\u0131ndan Mediator yap\u0131lar\u0131n\u0131 projeye dahil edebilmek i\u00e7in a\u015fa\u011f\u0131daki gibi servis entegrasyonunu ger\u00e7ekle\u015ftiriniz:<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nvar builder = WebApplication.CreateBuilder(args);\r\n\r\nbuilder.Services.AddMediator();\r\n\r\nvar app = builder.Build();\r\n<\/pre>\n<\/div>\n<p>Bu i\u015flemlerden sonra <em>CQRS<\/em>, <em>Notification<\/em> veya <em>Pipeline Behavior<\/em> davran\u0131\u015flar\u0131ndan hangisini uygulamak istiyorsan\u0131z a\u015fa\u011f\u0131daki gibi \u00e7al\u0131\u015fmalar ger\u00e7ekle\u015ftirebilirsiniz:<\/p>\n<ul>\n<li><strong><em>CQRS<\/em><\/strong><br \/>\n<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2025\/12\/MediatR-Yerine-martinothamar-Mediator-Kutuphanesini-Inceleyelim.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2025\/12\/MediatR-Yerine-martinothamar-Mediator-Kutuphanesini-Inceleyelim.png\" alt=\"MediatR Yerine &#039;martinothamar\/Mediator&#039; K\u00fct\u00fcphanesini \u0130nceleyelim\" width=\"253\" height=\"260\" class=\"alignleft size-full wp-image-28210\" \/><\/a>CQRS pattern&#8217;\u0131 uygularken birebir <a href=\"https:\/\/www.gencayyildiz.com\/blog\/cqrs-pattern-nedir-mediatr-kutuphanesi-ile-nasil-uygulanir\/\" target=\"_blank\">MediatR<\/a> k\u00fct\u00fcphanesinde oldu\u011fu gibi Command ve Query&#8217;ler fiziksel ayr\u0131lmal\u0131 ve <em>Request \/ Response<\/em> implementasyonlar\u0131 e\u015fli\u011finde davran\u0131\u015flar olu\u015fturulmal\u0131d\u0131r.<\/p>\n<p>\u00d6rnek Command \u00e7al\u0131\u015fmas\u0131;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public sealed record CreateUserCommandRequest(string FirstName, string LastName) : IRequest&lt;CreateUserCommandResponse&gt;;\r\n<\/pre>\n<\/div>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public sealed record CreateUserCommandResponse(Guid Id);\r\n<\/pre>\n<\/div>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public sealed class CreateUserCommandHandler : IRequestHandler&lt;CreateUserCommandRequest, CreateUserCommandResponse&gt;\r\n    {\r\n        public async ValueTask&lt;CreateUserCommandResponse&gt; Handle(CreateUserCommandRequest request, CancellationToken cancellationToken)\r\n        {\r\n            await Console.Out.WriteLineAsync($&quot;'{request.FirstName} {request.LastName}' created&quot;);\r\n            var id = Guid.NewGuid();\r\n            return new CreateUserCommandResponse(id);\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<p>\u00d6rnek Query \u00e7al\u0131\u015fmas\u0131;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public sealed record GetUsersQueryRequest : IRequest&lt;GetUsersQueryResponse&#x5B;]&gt;;\r\n<\/pre>\n<\/div>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public sealed record GetUsersQueryResponse(string FirstName, string LastName);\r\n<\/pre>\n<\/div>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public sealed class GetUsersQueryHandler : IRequestHandler&lt;GetUsersQueryRequest, GetUsersQueryResponse&#x5B;]&gt;\r\n    {\r\n        public ValueTask&lt;GetUsersQueryResponse&#x5B;]&gt; Handle(GetUsersQueryRequest request, CancellationToken cancellationToken)\r\n        {\r\n            return ValueTask.FromResult(new&#x5B;]\r\n            {\r\n                new GetUsersQueryResponse(&quot;Ahmet&quot;, &quot;Y\u0131lmaz&quot;),\r\n                new GetUsersQueryResponse(&quot;\u0130brahim&quot;, &quot;Y\u0131lmaz&quot;),\r\n                new GetUsersQueryResponse(&quot;C\u00fcneyt&quot;, &quot;Y\u0131ld\u0131z&quot;),\r\n                new GetUsersQueryResponse(&quot;Mustafa&quot;, &quot;Y\u0131ld\u0131z&quot;)\r\n            });\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<p>Her iki \u00e7al\u0131\u015fmay\u0131 da kullan\u0131rken a\u015fa\u011f\u0131daki gibi basit endpoint&#8217;lerden istifade edebilir ve testimizi ger\u00e7ekle\u015ftirebiliriz;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\napp.MapGet(&quot;\/get-users&quot;, async (IMediator mediator, &#x5B;AsParameters] GetUsersQueryRequest getUsersQueryRequest) =&gt; await mediator.Send(getUsersQueryRequest));\r\n\r\napp.MapPost(&quot;\/create-user-command&quot;, async (IMediator mediator, CreateUserCommandRequest createUserCommandRequest) =&gt; await mediator.Send(createUserCommandRequest));\r\n<\/pre>\n<\/div>\n<\/li>\n<li><strong><em>Notification<\/em><\/strong><br \/>\nNotification&#8217;da da ayn\u0131 al\u0131\u015f\u0131lageldik mant\u0131kla hareket edilmekte ve <code>INotification&lt;T&gt;<\/code> ve <code>INotificationHandler&lt;T&gt;<\/code> aray\u00fczlerinden istifade edilmektedir.<\/p>\n<p>\u015e\u00f6yle ki;<\/p>\n<p>Bir notification tan\u0131m\u0131 tasarlanmal\u0131;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\npublic sealed record UserCreatedNotification(Guid UserId) : INotification;\r\n<\/pre>\n<\/div>\n<p>Ve akabinde bu tan\u0131m\u0131 kar\u015f\u0131layacak a\u015fa\u011f\u0131daki gibi bir veya birden fazla handler olu\u015fturulmal\u0131d\u0131r;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class SendEmailOnUserCreatedHandler : INotificationHandler&lt;UserCreatedNotification&gt;\r\n    {\r\n        public ValueTask Handle(UserCreatedNotification notification, CancellationToken ct)\r\n        {\r\n            Console.WriteLine(&quot;Email sent: &quot; + notification.UserId);\r\n            return ValueTask.CompletedTask;\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class LogUserCreatedHandler : INotificationHandler&lt;UserCreatedNotification&gt;\r\n    {\r\n        public ValueTask Handle(UserCreatedNotification notification, CancellationToken ct)\r\n        {\r\n            Console.WriteLine(&quot;Log: User created &quot; + notification.UserId);\r\n            return ValueTask.CompletedTask;\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<p>Bu \u00e7al\u0131\u015fmay\u0131 da test edebilmek i\u00e7in CQRS \u00f6rne\u011finde olu\u015fturdu\u011fumuz POST endpoint&#8217;ini a\u015fa\u011f\u0131daki gibi geni\u015fletebiliriz;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\napp.MapPost(&quot;\/create-user-command&quot;, async (IMediator mediator, CreateUserCommandRequest createUserCommandRequest) =&gt;\r\n{\r\n    var response = await mediator.Send(createUserCommandRequest);\r\n    await mediator.Publish(new UserCreatedNotification(response.Id));\r\n    return response;\r\n});\r\n<\/pre>\n<\/div>\n<\/li>\n<li><strong><em>Pipeline Behavior<\/em><\/strong><br \/>\nLogging, validation ve caching i\u015flemleri i\u00e7in de Pipeline Behavior davran\u0131\u015flar\u0131ndan a\u015fa\u011f\u0131daki gibi faydalanabilmekteyiz.<\/p>\n<ul>\n<li><em><u>Logging<\/u><\/em>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class LoggingPipelineBehavior&lt;TMessage, TResponse&gt;(ILogger&lt;LoggingPipelineBehavior&lt;TMessage, TResponse&gt;&gt; logger) : IPipelineBehavior&lt;TMessage, TResponse&gt; where TMessage : notnull, IMessage\r\n    {\r\n        public async ValueTask&lt;TResponse&gt; Handle(TMessage message, MessageHandlerDelegate&lt;TMessage, TResponse&gt; next, CancellationToken cancellationToken)\r\n        {\r\n            logger.LogInformation(\r\n                    &quot;Handling {RequestName} with data {@Request}&quot;,\r\n                    typeof(TMessage).Name,\r\n                    message);\r\n\r\n            var response = await next(message, cancellationToken);\r\n\r\n            logger.LogInformation(\r\n                    &quot;Handled {RequestName} with response {@Response}&quot;,\r\n                    typeof(TMessage).Name,\r\n                    response);\r\n\r\n            return response;\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<\/li>\n<li><em><u>Validation<\/u><\/em>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class CreateUserCommandValidator : AbstractValidator&lt;CreateUserCommandRequest&gt;\r\n    {\r\n        public CreateUserCommandValidator()\r\n        {\r\n            RuleFor(x =&gt; x.FirstName)\r\n                .NotEmpty()\r\n                    .WithMessage(&quot;FirstName bo\u015f ge\u00e7ilemez!&quot;)\r\n                    .MaximumLength(15)\r\n                    .MinimumLength(3);\r\n\r\n            RuleFor(x =&gt; x.LastName)\r\n                .NotEmpty()\r\n                    .WithMessage(&quot;LastName bo\u015f ge\u00e7ilemez!&quot;)\r\n                    .MaximumLength(15)\r\n                    .MinimumLength(3);\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public sealed class ValidationPipelineBehavior&lt;TMessage, TResponse&gt;(IServiceProvider serviceProvider) : IPipelineBehavior&lt;TMessage, TResponse&gt; where TMessage : IMessage\r\n    {\r\n        public async ValueTask&lt;TResponse&gt; Handle(TMessage message, MessageHandlerDelegate&lt;TMessage, TResponse&gt; next, CancellationToken cancellationToken)\r\n        {\r\n            using var scope = serviceProvider.CreateScope();\r\n\r\n            var validators = scope.ServiceProvider.GetServices&lt;IValidator&lt;TMessage&gt;&gt;().ToList();\r\n\r\n            if (validators is &#x5B;])\r\n                return await next(message, cancellationToken);\r\n\r\n            var context = new ValidationContext&lt;TMessage&gt;(message);\r\n\r\n            var validationResults = await Task.WhenAll(validators.Select(async validator =&gt; await validator.ValidateAsync(context, cancellationToken)));\r\n\r\n            var failures = validationResults\r\n                .SelectMany(result =&gt; result.Errors)\r\n                .Where(failure =&gt; failure != null)\r\n                .ToList();\r\n\r\n            if (failures is not &#x5B;])\r\n                throw new ValidationException(failures);\r\n\r\n            return await next(message, cancellationToken);\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<\/li>\n<li><em><u>Caching<\/u><\/em>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class RedisService\r\n    {\r\n        ConnectionMultiplexer? connectionMultiplexer;\r\n        public void Connect()\r\n            =&gt; connectionMultiplexer = ConnectionMultiplexer.Connect(&quot;localhost:6379&quot;);\r\n        public IDatabase Database\r\n        {\r\n            get\r\n            {\r\n                if (!connectionMultiplexer?.IsConnected == null)\r\n                    Connect();\r\n\r\n                return connectionMultiplexer.GetDatabase(0);\r\n            }\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public sealed class CachingPipelineBehavior&lt;TMessage, TResponse&gt;(RedisService redisService) : IPipelineBehavior&lt;TMessage, TResponse&gt; where TMessage : IMessage where TResponse : class\r\n    {\r\n        public async ValueTask&lt;TResponse&gt; Handle(TMessage message, MessageHandlerDelegate&lt;TMessage, TResponse&gt; next, CancellationToken cancellationToken)\r\n        {\r\n            var redisDatabase = redisService.Database;\r\n\r\n            var cacheKey = $&quot;{message.GetType().FullName}&quot;;\r\n\r\n            TResponse? cachedResponse = null;\r\n\r\n            var cachedData = await redisDatabase.StringGetAsync(cacheKey);\r\n            if (cachedData.HasValue)\r\n            {\r\n                var cachedResponseJson = Encoding.UTF8.GetString(cachedData);\r\n                cachedResponse = JsonSerializer.Deserialize&lt;TResponse&gt;(cachedResponseJson);\r\n            }\r\n\r\n            if (cachedResponse != null)\r\n                return cachedResponse;\r\n\r\n            var response = await next(message, cancellationToken);\r\n\r\n            \/\/Yeni veriyi cache'e al\u0131yoruz.\r\n            var responseJson = JsonSerializer.Serialize(response);\r\n            var encodedData = Encoding.UTF8.GetBytes(responseJson);\r\n\r\n            var result = await redisDatabase.StringSetAsync(cacheKey, encodedData, expiry: TimeSpan.FromMinutes(60));\r\n            return response;\r\n        }\r\n<\/pre>\n<\/div>\n<\/li>\n<\/ul>\n<p>Tabi t\u00fcm bu Pipeline Behavior davran\u0131\u015flar\u0131n\u0131 sisteme dahil edebilmek i\u00e7in a\u015fa\u011f\u0131daki gibi bir yap\u0131land\u0131rmada bulunmak yeterli olacakt\u0131r:<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nbuilder.Services.AddMediator(options =&gt; options.PipelineBehaviors = &#x5B;\r\n    typeof(LoggingPipelineBehavior&lt;,&gt;),\r\n    typeof(ValidationPipelineBehavior&lt;,&gt;),\r\n    typeof(CachingPipelineBehavior&lt;,&gt;)\r\n        ]);\r\n<\/pre>\n<\/div>\n<\/li>\n<\/ul>\n<h4>Streaming Messages<\/h4>\n<p>Son olarak Mediator k\u00fct\u00fcphanesinin en az bilinen ama en g\u00fc\u00e7l\u00fc diyebilece\u011fim \u00f6zelli\u011fi olan Streaming Messages \u00f6zelli\u011fini de\u011ferlendirelim.<\/p>\n<p>Bu \u00f6zellik; esas\u0131nda ad\u0131 \u00fczerinde, klasik CQRS davran\u0131\u015f\u0131ndaki handler&#8217;\u0131n tek bir response d\u00f6nd\u00fcrmesinden ziyade, zaman i\u00e7inde birden fazla sonu\u00e7 \u00fcretmesi (stream) \u00fczerine kurgulanm\u0131\u015f davran\u0131\u015flar i\u00e7in ge\u00e7erli bir \u00e7\u00f6z\u00fcm sa\u011flamaktad\u0131r.<\/p>\n<p>A\u015fa\u011f\u0131daki \u00f6rne\u011fi incelerseniz e\u011fer;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public sealed record StreamRequest : IStreamRequest&lt;StreamResponse&gt;;\r\n<\/pre>\n<\/div>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public sealed record StreamResponse(Guid Id);\r\n<\/pre>\n<\/div>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public sealed class StreamHandler : IStreamRequestHandler&lt;StreamRequest, StreamResponse&gt;\r\n    {\r\n        public async IAsyncEnumerable&lt;StreamResponse&gt; Handle(StreamRequest request, CancellationToken cancellationToken)\r\n        {\r\n            for (int i = 0; i &lt; 5; i++)\r\n            {\r\n                await Task.Delay(1000, cancellationToken);\r\n                yield return new StreamResponse(Guid.NewGuid());\r\n            }\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<p>\u015feklinde teknik bir kuyguyla rahatl\u0131kla uygulanabilmektedir.<\/p>\n<p>Tabi kullan\u0131rken de a\u015fa\u011f\u0131daki gibi bir endpoint&#8217;ten istifade edilebilir:<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\napp.MapGet(&quot;\/streaming-messages&quot;, async (IMediator mediator, &#x5B;AsParameters] StreamRequest streamRequest) =&gt;\r\n{\r\n    await foreach (var response in mediator.CreateStream(streamRequest))\r\n        Console.WriteLine(response);\r\n});\r\n<\/pre>\n<\/div>\n<p>Fark\u0131ndaysan\u0131z esas\u0131nda bu \u00f6zelli\u011fin t\u00fcm altyap\u0131s\u0131 .NET&#8217;teki asenkron iterasyonel i\u015flevlerin temeli olan <a href=\"https:\/\/www.gencayyildiz.com\/blog\/c-8-0-iasyncenumerablet-ve-iasyncenumeratort-arayuzleri-ile-asenkron-iterasyonel-islev-olusturma\/\" target=\"_blank\"><code>IAsyncEnumerable&lt;T&gt;<\/code><\/a> interface&#8217;ine g\u00f6re yap\u0131land\u0131r\u0131lm\u0131\u015ft\u0131r. Haliyle par\u00e7a par\u00e7a veri aktar\u0131mlar\u0131 s\u00fcre\u00e7lerinde CQRS benimsenmi\u015fse e\u011fer bu streamin \u00f6zelli\u011fi ile h\u0131zl\u0131ca gerekli aksiyonlar al\u0131nabilecektir. B\u00f6ylece, \u00f6zellikle b\u00fcy\u00fck veri setlerinde, uzun s\u00fcren i\u015flemlerde ve real-time ak\u0131\u015flarda ihtiyac\u0131 kar\u015f\u0131layabilecek muazzam bir altyap\u0131 elimizin alt\u0131ndad\u0131r diyebiliriz. Bir yandan, bu \u00f6zellik ile ilgili k\u00fct\u00fcphanenin MediatR&#8217;a fark yaratt\u0131\u011f\u0131n\u0131 da s\u00f6yleyebiliriz.<\/p>\n<p>Nihai olarak;<\/p>\n<p>MediatR \u00fccretli olduktan sonra CQRS gibi \u00f6nemli bir pattern&#8217;\u0131 manuel uygulamay\u0131 \u00f6neren onlarca tavsiyeden sonra (ki bu pattern&#8217;\u0131n nas\u0131l manuel uygulanaca\u011f\u0131na dair teknik makaleyi y\u0131llar \u00f6nce ilk kaleme alan ki\u015fi olarak diyorum ki) martinothamar\/Mediator k\u00fct\u00fcphanesinin ayn\u0131 kullan\u0131m pratikleri e\u015fli\u011finde daha elveri\u015fli bir altyap\u0131 sa\u011flad\u0131\u011f\u0131n\u0131 s\u00f6yleyebilirim.<\/p>\n<p>\u0130lgilenenlerin faydalanmas\u0131 dile\u011fiyle&#8230;<br \/>\nSonraki yaz\u0131lar\u0131mda g\u00f6r\u00fc\u015fmek \u00fczere&#8230;<br \/>\n\u0130yi \u00e7al\u0131\u015fmalar&#8230;<\/p>\n<p>Not : \u00d6rnek \u00e7al\u0131\u015fmaya a\u015fa\u011f\u0131daki GitHub adresinden eri\u015febilirsiniz.<br \/>\n<a href=\"https:\/\/github.com\/gncyyldz\/CQRS_With_martinothamar_Mediator_Example\" target=\"_blank\">https:\/\/github.com\/gncyyldz\/CQRS_With_martinothamar_Mediator_Example<\/a><\/p>\n<!-- AddThis Advanced Settings generic via filter on the_content --><!-- AddThis Share Buttons generic via filter on the_content -->","protected":false},"excerpt":{"rendered":"<p>Merhaba, Bu i\u00e7eri\u011fimizde MediatR k\u00fct\u00fcphanesine alternatif olarak de\u011ferlendirebilece\u011fimiz martinothamar\/Mediator k\u00fct\u00fcphanesini hem teorik hem de pratik olarak inceleyecek, MediatR yerine nas\u0131l konumland\u0131\u011f\u0131n\u0131 en net \u015fekilde ele al\u0131yor olaca\u011f\u0131z. martinothamar\/Mediator Nedir? martinothamar\/Mediator, .NET d\u00fcnyas\u0131nda MediatR&#8217;a bir&#46;&#46;&#46;<!-- AddThis Advanced Settings generic via filter on get_the_excerpt --><!-- AddThis Share Buttons generic via filter on get_the_excerpt --><\/p>\n","protected":false},"author":1,"featured_media":3223,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5206,2739,3102],"tags":[4150,5548,5549,5550,5551,4153,1265,5552,5553],"class_list":["post-28202","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-net","category-net-core","category-asp-net-core","tag-cqrs","tag-cqrs-martinothamar-mediator","tag-cqrs-mediator","tag-martinothamar-mediator","tag-martinothamar-mediator-nedir","tag-mediatr","tag-notification","tag-pipeline-behavior","tag-streaming-messages"],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/28202","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/comments?post=28202"}],"version-history":[{"count":7,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/28202\/revisions"}],"predecessor-version":[{"id":28214,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/28202\/revisions\/28214"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media\/3223"}],"wp:attachment":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media?parent=28202"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/categories?post=28202"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/tags?post=28202"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}