diff --git a/Examples/Caching/Examples.Caching.MemoryCaching/Examples.Caching.MemoryCaching.csproj b/Examples/Caching/Examples.Caching.MemoryCaching/Examples.Caching.MemoryCaching.csproj index d186fa66..50f73b04 100644 --- a/Examples/Caching/Examples.Caching.MemoryCaching/Examples.Caching.MemoryCaching.csproj +++ b/Examples/Caching/Examples.Caching.MemoryCaching/Examples.Caching.MemoryCaching.csproj @@ -8,6 +8,7 @@ + diff --git a/Examples/Caching/Examples.Caching.MemoryCaching/ITestApplicationService.cs b/Examples/Caching/Examples.Caching.MemoryCaching/ITestApplicationService.cs new file mode 100644 index 00000000..f836e032 --- /dev/null +++ b/Examples/Caching/Examples.Caching.MemoryCaching/ITestApplicationService.cs @@ -0,0 +1,11 @@ + +namespace Examples.Caching.MemoryCaching +{ + public interface ITestApplicationService + { + TestDto GetDistributedMemoryCache(string key); + TestDto GetMemoryCache(string key); + void SetDistributedMemoryCache(string key, Type type, object data); + void SetMemoryCache(string key, TestDto data); + } +} \ No newline at end of file diff --git a/Examples/Caching/Examples.Caching.MemoryCaching/Program.cs b/Examples/Caching/Examples.Caching.MemoryCaching/Program.cs index 57e646a1..e96e237f 100644 --- a/Examples/Caching/Examples.Caching.MemoryCaching/Program.cs +++ b/Examples/Caching/Examples.Caching.MemoryCaching/Program.cs @@ -21,23 +21,38 @@ { // Configure RCommon services.AddRCommon() - .WithCaching(cache => + .WithMemoryCaching(cache => { - - + cache.Configure(x => + { + x.ExpirationScanFrequency = TimeSpan.FromMinutes(1); + }); + }) + .WithDistributedCaching(cache => + { + cache.Configure(x => + { + x.ExpirationScanFrequency = TimeSpan.FromMinutes(1); + }); }); - + services.AddTransient(); }).Build(); Console.WriteLine("Example Starting"); var appService = host.Services.GetRequiredService(); - await appService.SetCache(); - await appService.GetCache(); - Console.WriteLine(""); - Console.WriteLine(""); + // In Memory Cache + appService.SetMemoryCache("test-key", new TestDto("test data 1")); + var testData1 = appService.GetMemoryCache("test-key"); + + // In Memory Distributed Cache + appService.SetDistributedMemoryCache("test-key", typeof(TestDto), new TestDto("test data 2")); + var testData2 = appService.GetDistributedMemoryCache("test-key"); + + Console.WriteLine(testData1.Message); + Console.WriteLine(testData2.Message); Console.WriteLine("Example Complete"); Console.ReadLine(); diff --git a/Examples/Caching/Examples.Caching.MemoryCaching/TestApplicationService.cs b/Examples/Caching/Examples.Caching.MemoryCaching/TestApplicationService.cs index 47d5134b..de3218ab 100644 --- a/Examples/Caching/Examples.Caching.MemoryCaching/TestApplicationService.cs +++ b/Examples/Caching/Examples.Caching.MemoryCaching/TestApplicationService.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Caching.Memory; +using RCommon.Json; using System; using System.Collections.Generic; using System.Linq; @@ -8,35 +9,38 @@ namespace Examples.Caching.MemoryCaching { - public class TestApplicationService + public class TestApplicationService : ITestApplicationService { private readonly IMemoryCache _memoryCache; private readonly IDistributedCache _distributedCache; + private readonly IJsonSerializer _serializer; - public TestApplicationService(IMemoryCache memoryCache, IDistributedCache distributedCache) + public TestApplicationService(IMemoryCache memoryCache, IDistributedCache distributedCache, IJsonSerializer serializer) { _memoryCache = memoryCache; _distributedCache = distributedCache; + _serializer = serializer; } - public async Task SetMemoryCache() + public void SetMemoryCache(string key, TestDto data) { - + _memoryCache.Set(key, data); } - public async Task GetMemoryCache() + public TestDto GetMemoryCache(string key) { - + return _memoryCache.Get(key); } - public async Task SetDistributedMemoryCache() + public void SetDistributedMemoryCache(string key, Type type, object data) { - + _distributedCache.Set(key, Encoding.UTF8.GetBytes(_serializer.Serialize(data, type))); } - public async Task GetDistributedMemoryCache() + public TestDto GetDistributedMemoryCache(string key) { - + var cache = _distributedCache.Get(key); + return _serializer.Deserialize(Encoding.UTF8.GetString(cache)); } } } diff --git a/Examples/Caching/Examples.Caching.PersistenceCaching/Program.cs b/Examples/Caching/Examples.Caching.PersistenceCaching/Program.cs index 912fe152..4b9626dc 100644 --- a/Examples/Caching/Examples.Caching.PersistenceCaching/Program.cs +++ b/Examples/Caching/Examples.Caching.PersistenceCaching/Program.cs @@ -1,18 +1,15 @@ -using Examples.ApplicationServices.CQRS.Validators; + using Examples.Caching.PersistenceCaching; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using RCommon; -using RCommon.ApplicationServices; -using RCommon.ApplicationServices.ExecutionResults; -using RCommon.FluentValidation; using System.Diagnostics; using System.Reflection; try { - var host = Host.CreateDefaultBuilder(args) + /*var host = Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration((context, builder) => { @@ -22,39 +19,17 @@ .ConfigureServices(services => { // Configure RCommon - services.AddRCommon() - .WithCQRS(cqrs => - { - // You can do it this way which is pretty straight forward but verbose - //cqrs.AddQueryHandler(); - //cqrs.AddCommandHandler(); - - // Or this way which uses a little magic but is simple - cqrs.AddCommandHandlers((typeof(Program).GetTypeInfo().Assembly)); - cqrs.AddQueryHandlers((typeof(Program).GetTypeInfo().Assembly)); - }) - .WithValidation(validation => - { - validation.AddValidatorsFromAssemblyContaining(typeof(TestCommand)); - - validation.UseWithCqrs(options => - { - options.ValidateCommands = true; - options.ValidateQueries = true; - }); - }); + services.AddRCommon(); services.AddTransient(); }).Build(); Console.WriteLine("Example Starting"); - var appService = host.Services.GetRequiredService(); - var commandResult = await appService.ExecuteTestCommand(new TestCommand("test")); - var queryResult = await appService.ExecuteTestQuery(new TestQuery()); + var appService = host.Services.GetRequiredService();*/ - Console.WriteLine(commandResult.ToString()); - Console.WriteLine(queryResult.Message); + Console.WriteLine(""); + Console.WriteLine(""); Console.WriteLine("Example Complete"); Console.ReadLine(); diff --git a/Examples/Caching/Examples.Caching.PersistenceCaching/TestApplicationService.cs b/Examples/Caching/Examples.Caching.PersistenceCaching/TestApplicationService.cs index c9c91b3f..4f56f9ce 100644 --- a/Examples/Caching/Examples.Caching.PersistenceCaching/TestApplicationService.cs +++ b/Examples/Caching/Examples.Caching.PersistenceCaching/TestApplicationService.cs @@ -1,7 +1,4 @@ -using RCommon.ApplicationServices.Commands; -using RCommon.ApplicationServices.ExecutionResults; -using RCommon.ApplicationServices.Queries; -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -9,25 +6,15 @@ namespace Examples.Caching.PersistenceCaching { - public class TestApplicationService : ITestApplicationService + public class TestApplicationService { - private readonly ICommandBus _commandBus; - private readonly IQueryBus _queryBus; + - public TestApplicationService(ICommandBus commandBus, IQueryBus queryBus) + public TestApplicationService() { - _commandBus = commandBus; - _queryBus = queryBus; + } - public async Task ExecuteTestQuery(TestQuery query) - { - return await _queryBus.DispatchQueryAsync(query, CancellationToken.None); - } - - public async Task ExecuteTestCommand(TestCommand command) - { - return await _commandBus.DispatchCommandAsync(command, CancellationToken.None); - } + } } diff --git a/Examples/Caching/Examples.Caching.RedisCaching/Examples.Caching.RedisCaching.csproj b/Examples/Caching/Examples.Caching.RedisCaching/Examples.Caching.RedisCaching.csproj index 5ef0ed61..93b3dda3 100644 --- a/Examples/Caching/Examples.Caching.RedisCaching/Examples.Caching.RedisCaching.csproj +++ b/Examples/Caching/Examples.Caching.RedisCaching/Examples.Caching.RedisCaching.csproj @@ -8,6 +8,7 @@ + diff --git a/Examples/Caching/Examples.Caching.RedisCaching/ITestApplicationService.cs b/Examples/Caching/Examples.Caching.RedisCaching/ITestApplicationService.cs new file mode 100644 index 00000000..3712102f --- /dev/null +++ b/Examples/Caching/Examples.Caching.RedisCaching/ITestApplicationService.cs @@ -0,0 +1,9 @@ + +namespace Examples.Caching.RedisCaching +{ + public interface ITestApplicationService + { + TestDto GetDistributedMemoryCache(string key); + void SetDistributedMemoryCache(string key, Type type, object data); + } +} \ No newline at end of file diff --git a/Examples/Caching/Examples.Caching.RedisCaching/Program.cs b/Examples/Caching/Examples.Caching.RedisCaching/Program.cs index 2ce9f68a..cb11238f 100644 --- a/Examples/Caching/Examples.Caching.RedisCaching/Program.cs +++ b/Examples/Caching/Examples.Caching.RedisCaching/Program.cs @@ -1,12 +1,10 @@ -using Examples.ApplicationServices.CQRS.Validators; -using Examples.Caching.RedisCaching; +using Examples.Caching.RedisCaching; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using RCommon; -using RCommon.ApplicationServices; -using RCommon.ApplicationServices.ExecutionResults; -using RCommon.FluentValidation; +using RCommon.Caching; +using RCommon.RedisCache; using System.Diagnostics; using System.Reflection; @@ -23,38 +21,27 @@ { // Configure RCommon services.AddRCommon() - .WithCQRS(cqrs => + .WithDistributedCaching(cache => { - // You can do it this way which is pretty straight forward but verbose - //cqrs.AddQueryHandler(); - //cqrs.AddCommandHandler(); - - // Or this way which uses a little magic but is simple - cqrs.AddCommandHandlers((typeof(Program).GetTypeInfo().Assembly)); - cqrs.AddQueryHandlers((typeof(Program).GetTypeInfo().Assembly)); - }) - .WithValidation(validation => - { - validation.AddValidatorsFromAssemblyContaining(typeof(TestCommand)); - - validation.UseWithCqrs(options => + cache.Configure(redis => { - options.ValidateCommands = true; - options.ValidateQueries = true; + // Redis Configuration }); + }); - + services.AddTransient(); - + }).Build(); Console.WriteLine("Example Starting"); var appService = host.Services.GetRequiredService(); - var commandResult = await appService.ExecuteTestCommand(new TestCommand("test")); - var queryResult = await appService.ExecuteTestQuery(new TestQuery()); - Console.WriteLine(commandResult.ToString()); - Console.WriteLine(queryResult.Message); + // In Memory Distributed Cache + appService.SetDistributedMemoryCache("test-key", typeof(TestDto), new TestDto("test data 1")); + var testData1 = appService.GetDistributedMemoryCache("test-key"); + + Console.WriteLine(testData1.Message); Console.WriteLine("Example Complete"); Console.ReadLine(); @@ -65,3 +52,4 @@ } + diff --git a/Examples/Caching/Examples.Caching.RedisCaching/TestApplicationService.cs b/Examples/Caching/Examples.Caching.RedisCaching/TestApplicationService.cs index af7a92cd..4c5fa5ef 100644 --- a/Examples/Caching/Examples.Caching.RedisCaching/TestApplicationService.cs +++ b/Examples/Caching/Examples.Caching.RedisCaching/TestApplicationService.cs @@ -1,6 +1,5 @@ -using RCommon.ApplicationServices.Commands; -using RCommon.ApplicationServices.ExecutionResults; -using RCommon.ApplicationServices.Queries; +using Microsoft.Extensions.Caching.Distributed; +using RCommon.Json; using System; using System.Collections.Generic; using System.Linq; @@ -11,23 +10,24 @@ namespace Examples.Caching.RedisCaching { public class TestApplicationService : ITestApplicationService { - private readonly ICommandBus _commandBus; - private readonly IQueryBus _queryBus; + private readonly IDistributedCache _distributedCache; + private readonly IJsonSerializer _serializer; - public TestApplicationService(ICommandBus commandBus, IQueryBus queryBus) + public TestApplicationService(IDistributedCache distributedCache, IJsonSerializer serializer) { - _commandBus = commandBus; - _queryBus = queryBus; + _distributedCache = distributedCache; + _serializer = serializer; } - public async Task ExecuteTestQuery(TestQuery query) + public void SetDistributedMemoryCache(string key, Type type, object data) { - return await _queryBus.DispatchQueryAsync(query, CancellationToken.None); + _distributedCache.Set(key, Encoding.UTF8.GetBytes(_serializer.Serialize(data, type))); } - public async Task ExecuteTestCommand(TestCommand command) + public TestDto GetDistributedMemoryCache(string key) { - return await _commandBus.DispatchCommandAsync(command, CancellationToken.None); + var cache = _distributedCache.Get(key); + return _serializer.Deserialize(Encoding.UTF8.GetString(cache)); } } } diff --git a/Examples/Caching/Examples.Caching.RedisCaching/TestDto.cs b/Examples/Caching/Examples.Caching.RedisCaching/TestDto.cs new file mode 100644 index 00000000..1a980228 --- /dev/null +++ b/Examples/Caching/Examples.Caching.RedisCaching/TestDto.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Examples.Caching.RedisCaching +{ + public record TestDto + { + public TestDto(string message) + { + Message = message; + } + + public string Message { get; } + } +} diff --git a/Examples/Mediator/Examples.Mediator.MediatR/Program.cs b/Examples/Mediator/Examples.Mediator.MediatR/Program.cs index 2aaf6d06..d80b9a8b 100644 --- a/Examples/Mediator/Examples.Mediator.MediatR/Program.cs +++ b/Examples/Mediator/Examples.Mediator.MediatR/Program.cs @@ -31,7 +31,7 @@ mediator.AddNotification(); mediator.AddRequest(); mediator.AddRequest(); - + // Additional configurations can be set like below mediator.Configure(config => { diff --git a/Examples/Messaging/Examples.Messaging.Wolverine/Program.cs b/Examples/Messaging/Examples.Messaging.Wolverine/Program.cs index 99e2eceb..b23338bd 100644 --- a/Examples/Messaging/Examples.Messaging.Wolverine/Program.cs +++ b/Examples/Messaging/Examples.Messaging.Wolverine/Program.cs @@ -5,6 +5,7 @@ using RCommon; using RCommon.EventHandling; using RCommon.EventHandling.Producers; +using RCommon.Wolverine; using RCommon.Wolverine.Producers; using System.Diagnostics; using Wolverine; @@ -26,7 +27,7 @@ { // Configure RCommon services.AddRCommon() - .WithEventHandling(eventHandling => + .WithEventHandling(eventHandling => { eventHandling.AddProducer(); eventHandling.AddSubscriber(); diff --git a/Src/RCommon.Core/EventHandling/Producers/InMemoryTransactionalEventRouter.cs b/Src/RCommon.Core/EventHandling/Producers/InMemoryTransactionalEventRouter.cs index 278ba6d6..2bec9937 100644 --- a/Src/RCommon.Core/EventHandling/Producers/InMemoryTransactionalEventRouter.cs +++ b/Src/RCommon.Core/EventHandling/Producers/InMemoryTransactionalEventRouter.cs @@ -41,31 +41,23 @@ public async Task RouteEventsAsync(IEnumerable transactional var asyncEvents = transactionalEvents.Where(x => x is IAsyncEvent); var eventProducers = _serviceProvider.GetServices(); - _logger.LogInformation($"{this.GetGenericTypeName()} is routing {syncEvents.Count().ToString()} synchronized transactional events."); - - // Produce the Synchronized Events first - foreach (var @event in syncEvents) + if (syncEvents.Any() && asyncEvents.Any()) { - _logger.LogDebug($"{this.GetGenericTypeName()} is routing event: {@event}"); - foreach (var producer in eventProducers) - { - await producer.ProduceEventAsync(@event); - } - } - - _logger.LogInformation($"{this.GetGenericTypeName()} is routing {asyncEvents.Count().ToString()} asynchronous transactional events."); + // Produce the Synchronized Events first + _logger.LogInformation($"{this.GetGenericTypeName()} is routing {syncEvents.Count().ToString()} synchronized transactional events."); + await this.ProduceSyncEvents(syncEvents, eventProducers); - // Produce the Async Events - var eventTaskList = new List(); - foreach (var @event in asyncEvents) + // Produce the Async Events + _logger.LogInformation($"{this.GetGenericTypeName()} is routing {asyncEvents.Count().ToString()} asynchronous transactional events."); + await this.ProduceAsyncEvents(asyncEvents, eventProducers); + } + else { - foreach (var producer in eventProducers) - { - eventTaskList.Add(producer.ProduceEventAsync(@event)); - } + // Send as synchronized by default + _logger.LogInformation($"No sync/async events found. {this.GetGenericTypeName()} is routing {syncEvents.Count().ToString()} as synchronized transactional events by default."); + await this.ProduceSyncEvents(transactionalEvents, eventProducers); } - await Task.WhenAll(eventTaskList); } } catch(EventProductionException ex) @@ -83,6 +75,31 @@ public async Task RouteEventsAsync(IEnumerable transactional } } + private async Task ProduceAsyncEvents(IEnumerable asyncEvents, IEnumerable eventProducers) + { + var eventTaskList = new List(); + foreach (var @event in asyncEvents) + { + foreach (var producer in eventProducers) + { + eventTaskList.Add(producer.ProduceEventAsync(@event)); + } + } + await Task.WhenAll(eventTaskList); + } + + private async Task ProduceSyncEvents(IEnumerable syncEvents, IEnumerable eventProducers) + { + foreach (var @event in syncEvents) + { + _logger.LogDebug($"{this.GetGenericTypeName()} is routing event: {@event}"); + foreach (var producer in eventProducers) + { + await producer.ProduceEventAsync(@event); + } + } + } + public async Task RouteEventsAsync() { await this.RouteEventsAsync(this._storedTransactionalEvents); diff --git a/Src/RCommon.Json/IJsonSerializer.cs b/Src/RCommon.Json/IJsonSerializer.cs index 047b23a0..b53cc0bb 100644 --- a/Src/RCommon.Json/IJsonSerializer.cs +++ b/Src/RCommon.Json/IJsonSerializer.cs @@ -10,6 +10,8 @@ public interface IJsonSerializer { public string Serialize(object obj, JsonSerializeOptions? options = null); + public string Serialize(object obj, Type type, JsonSerializeOptions? options = null); + public T Deserialize(string json, JsonDeserializeOptions? options = null); public object Deserialize(string json, Type type, JsonDeserializeOptions? options = null); diff --git a/Src/RCommon.JsonNet/JsonNetSerializer.cs b/Src/RCommon.JsonNet/JsonNetSerializer.cs index eec3fe62..7bc778b2 100644 --- a/Src/RCommon.JsonNet/JsonNetSerializer.cs +++ b/Src/RCommon.JsonNet/JsonNetSerializer.cs @@ -52,5 +52,20 @@ public string Serialize(object obj, JsonSerializeOptions? options = null) return JsonConvert.SerializeObject(obj, _settings); } + + public string Serialize(object obj, Type type, JsonSerializeOptions? options = null) + { + if (options != null && options.CamelCase) + { + _settings.ContractResolver = new CamelCasePropertyNamesContractResolver(); + } + + if (options != null && options.Indented) + { + _settings.Formatting = Formatting.Indented; + } + + return JsonConvert.SerializeObject(obj, type, _settings); + } } } diff --git a/Src/RCommon.RedisCache/RedisCachingBuilder.cs b/Src/RCommon.RedisCache/RedisCachingBuilder.cs index b3bb8af6..a0adf641 100644 --- a/Src/RCommon.RedisCache/RedisCachingBuilder.cs +++ b/Src/RCommon.RedisCache/RedisCachingBuilder.cs @@ -8,7 +8,7 @@ namespace RCommon.RedisCache { - public class RedisCachingBuilder : IDistributedCachingBuilder + public class RedisCachingBuilder : IRedisCachingBuilder { public RedisCachingBuilder(IRCommonBuilder builder) { diff --git a/Src/RCommon.SystemTextJson/TextJsonSerializer.cs b/Src/RCommon.SystemTextJson/TextJsonSerializer.cs index bd241471..75fd91c9 100644 --- a/Src/RCommon.SystemTextJson/TextJsonSerializer.cs +++ b/Src/RCommon.SystemTextJson/TextJsonSerializer.cs @@ -58,5 +58,20 @@ public string Serialize(object obj, JsonSerializeOptions? options = null) return JsonSerializer.Serialize(obj, _jsonOptions); } + + public string Serialize(object obj, Type type, JsonSerializeOptions? options = null) + { + if (options != null) + { + _jsonOptions.WriteIndented = options.Indented; + + if (options.CamelCase) + { + _jsonOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; + } + } + + return JsonSerializer.Serialize(obj, type, _jsonOptions); + } } }