using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Tapeti.Config; namespace Tapeti.Default { internal class MessageContext : IMessageContext { private readonly Dictionary payloads = new(); /// public ITapetiConfig Config { get; set; } /// public string Queue { get; set; } /// public string Exchange { get; set; } /// public string RoutingKey { get; set; } /// public byte[] RawBody { get; set; } /// public object Message { get; set; } /// public IMessageProperties Properties { get; set; } /// public IBinding Binding { get; set; } /// public CancellationToken ConnectionClosed { get; set; } public void Store(T payload) where T : IMessageContextPayload { payloads.Add(typeof(T), payload); } public void StoreOrUpdate(Func onAdd, Action onUpdate) where T : IMessageContextPayload { if (payloads.TryGetValue(typeof(T), out var payload)) onUpdate((T)payload); else payloads.Add(typeof(T), onAdd()); } public T Get() where T : IMessageContextPayload { return (T)payloads[typeof(T)]; } public bool TryGet(out T payload) where T : IMessageContextPayload { if (payloads.TryGetValue(typeof(T), out var payloadValue)) { payload = (T)payloadValue; return true; } payload = default; return false; } /// public async ValueTask DisposeAsync() { foreach (var payload in payloads.Values) { switch (payload) { case IAsyncDisposable asyncDisposable: await asyncDisposable.DisposeAsync(); break; case IDisposable disposable: disposable.Dispose(); break; } } } /// public void Store(string key, object value) { StoreOrUpdate( () => new KeyValuePayload(key, value), payload => payload.Add(key, value)); } /// public bool Get(string key, out T value) where T : class { if (!TryGet(out var payload) || !payload.TryGetValue(key, out var objectValue)) { value = null; return false; } value = (T)objectValue; return true; } // ReSharper disable once InconsistentNaming public class KeyValuePayload : IMessageContextPayload, IDisposable, IAsyncDisposable { private readonly Dictionary items = new(); public KeyValuePayload(string key, object value) { Add(key, value); } public void Add(string key, object value) { items.Add(key, value); } public bool TryGetValue(string key, out object value) { return items.TryGetValue(key, out value); } public void Dispose() { foreach (var item in items.Values) (item as IDisposable)?.Dispose(); } public async ValueTask DisposeAsync() { foreach (var item in items.Values) { if (item is IAsyncDisposable asyncDisposable) await asyncDisposable.DisposeAsync(); } } } } }