diff --git a/en-US_User.dic b/en-US_User.dic index 340dd58f..77156bfc 100644 --- a/en-US_User.dic +++ b/en-US_User.dic @@ -195,6 +195,7 @@ pre prefixdelimiter prefixtoken prefixword +prepended prerelease psake quantized diff --git a/src/RapidField.SolidInstruments.Collections/BinaryTreeNode.cs b/src/RapidField.SolidInstruments.Collections/BinaryTreeNode.cs index 0745a961..93c31780 100644 --- a/src/RapidField.SolidInstruments.Collections/BinaryTreeNode.cs +++ b/src/RapidField.SolidInstruments.Collections/BinaryTreeNode.cs @@ -120,7 +120,7 @@ private BinaryTreeNode(T value, BinaryTreeNode leftChild, BinaryTreeNode r { if (leftChild is not null) { - if (AddChild(leftChild) == false) + if (AddChild(leftChild) is false) { throw new ArgumentException("The specified left child is invalid.", nameof(leftChild)); } @@ -132,7 +132,7 @@ private BinaryTreeNode(T value, BinaryTreeNode leftChild, BinaryTreeNode r if (rightChild is not null) { - if (AddChild(rightChild) == false) + if (AddChild(rightChild) is false) { throw new ArgumentException("The specified right child is invalid.", nameof(rightChild)); } diff --git a/src/RapidField.SolidInstruments.Collections/CircularBuffer.cs b/src/RapidField.SolidInstruments.Collections/CircularBuffer.cs index d97b68c6..8d324edf 100644 --- a/src/RapidField.SolidInstruments.Collections/CircularBuffer.cs +++ b/src/RapidField.SolidInstruments.Collections/CircularBuffer.cs @@ -164,7 +164,7 @@ public void Write(T element) /// public void Write(T element, Boolean permitOverwrite) { - if (permitOverwrite == false && Length == Capacity) + if (permitOverwrite is false && Length == Capacity) { throw new InvalidOperationException("A write operation failed because it would have overwritten an unread element in the buffer."); } diff --git a/src/RapidField.SolidInstruments.Collections/Extensions/ITreeNodeExtensions.cs b/src/RapidField.SolidInstruments.Collections/Extensions/ITreeNodeExtensions.cs index 7c353ec5..fc2079dc 100644 --- a/src/RapidField.SolidInstruments.Collections/Extensions/ITreeNodeExtensions.cs +++ b/src/RapidField.SolidInstruments.Collections/Extensions/ITreeNodeExtensions.cs @@ -54,7 +54,7 @@ public static void TraverseDown(this ITreeNode target, Action action.RejectIf().IsNull(nameof(action)); predicate.RejectIf().IsNull(nameof(predicate)); - if (predicate(target) == false) + if (predicate(target) is false) { return; } @@ -120,7 +120,7 @@ public static TResult TraverseDown(this ITreeNode target, Func(this ITreeNode target, Action> action.RejectIf().IsNull(nameof(action)); predicate.RejectIf().IsNull(nameof(predicate)); - if (predicate(target) == false) + if (predicate(target) is false) { return; } @@ -244,7 +244,7 @@ public static TResult TraverseUp(this ITreeNode target, Func children) /// public void Destroy() { - if (IsRoot == false) + if (IsRoot is false) { ((TreeNode)Parent).RemoveChild(this); } @@ -200,7 +200,7 @@ public TreeNode(T value, IEnumerable> children) { throw new ArgumentException("The specified collection contains a null node.", nameof(children)); } - else if (AddChild(node, true) == false) + else if (AddChild(node, true) is false) { throw new ArgumentException("The specified collection contains a duplicate or invalid node.", nameof(children)); } @@ -340,7 +340,7 @@ public IEnumerable> Children /// /// When true, is an empty collection. /// - public Boolean IsLeaf => ChildrenReference.Any() == false; + public Boolean IsLeaf => ChildrenReference.Any() is false; /// /// Gets a value indicating whether or not the current is a root node (a node without a parent). diff --git a/src/RapidField.SolidInstruments.Command.Autofac/AutofacCommandHandlerModule.cs b/src/RapidField.SolidInstruments.Command.Autofac/AutofacCommandHandlerModule.cs index 31c261aa..a53f0ad3 100644 --- a/src/RapidField.SolidInstruments.Command.Autofac/AutofacCommandHandlerModule.cs +++ b/src/RapidField.SolidInstruments.Command.Autofac/AutofacCommandHandlerModule.cs @@ -139,7 +139,7 @@ protected sealed override void Configure(ContainerBuilder configurator, IConfigu /// Gets the collection of non-abstract public class types defined by that are registered by /// the current . /// - public IEnumerable MatchedTypes => TargetAssembly.GetTypes().Where(type => type.IsPublic && type.IsClass && type.IsAbstract == false && BaseCommandHandlerType.IsAssignableFrom(type)); + public IEnumerable MatchedTypes => TargetAssembly.GetTypes().Where(type => type.IsPublic && type.IsClass && type.IsAbstract is false && BaseCommandHandlerType.IsAssignableFrom(type)); /// /// Gets the assembly from which command handler types are registered by the current diff --git a/src/RapidField.SolidInstruments.Command.DotNetNative/DotNetNativeCommandHandlerModule.cs b/src/RapidField.SolidInstruments.Command.DotNetNative/DotNetNativeCommandHandlerModule.cs index 96f17185..c86980ea 100644 --- a/src/RapidField.SolidInstruments.Command.DotNetNative/DotNetNativeCommandHandlerModule.cs +++ b/src/RapidField.SolidInstruments.Command.DotNetNative/DotNetNativeCommandHandlerModule.cs @@ -139,7 +139,7 @@ protected sealed override void Configure(ServiceCollection configurator, IConfig /// Gets the collection of non-abstract public class types defined by that are registered by /// the current . /// - public IEnumerable MatchedTypes => TargetAssembly.GetTypes().Where(type => type.IsPublic && type.IsClass && type.IsAbstract == false && BaseCommandHandlerType.IsAssignableFrom(type)); + public IEnumerable MatchedTypes => TargetAssembly.GetTypes().Where(type => type.IsPublic && type.IsClass && type.IsAbstract is false && BaseCommandHandlerType.IsAssignableFrom(type)); /// /// Gets the assembly from which command handler types are registered by the current diff --git a/src/RapidField.SolidInstruments.Command/Command.cs b/src/RapidField.SolidInstruments.Command/Command.cs index 52df011b..5eb1ba31 100644 --- a/src/RapidField.SolidInstruments.Command/Command.cs +++ b/src/RapidField.SolidInstruments.Command/Command.cs @@ -60,7 +60,7 @@ public Guid CorrelationIdentifier { get { - if (CorrelationIdentifierField.HasValue == false) + if (CorrelationIdentifierField.HasValue is false) { CorrelationIdentifierField = Guid.NewGuid(); } @@ -143,7 +143,7 @@ public Guid CorrelationIdentifier { get { - if (CorrelationIdentifierField.HasValue == false) + if (CorrelationIdentifierField.HasValue is false) { CorrelationIdentifierField = Guid.NewGuid(); } diff --git a/src/RapidField.SolidInstruments.Core/ArgumentValidation/ValidationTargetIEnumerableExtensions.cs b/src/RapidField.SolidInstruments.Core/ArgumentValidation/ValidationTargetIEnumerableExtensions.cs index f4fc490b..6fd6a9b3 100644 --- a/src/RapidField.SolidInstruments.Core/ArgumentValidation/ValidationTargetIEnumerableExtensions.cs +++ b/src/RapidField.SolidInstruments.Core/ArgumentValidation/ValidationTargetIEnumerableExtensions.cs @@ -97,11 +97,11 @@ public static class ValidationTargetIEnumerableExtensions internal static ValidationResult RejectIfIsNullOrEmpty(this ValidationTarget target, String targetParameterName) where TArgument : IEnumerable { - if (target.Argument == null) + if (target.Argument is null) { throw new ArgumentNullException(targetParameterName); } - else if (target.Argument.Any() == false) + else if (target.Argument.Any() is false) { throw new ArgumentEmptyException(targetParameterName); } diff --git a/src/RapidField.SolidInstruments.Core/Caching/DistributedCacheClient.cs b/src/RapidField.SolidInstruments.Core/Caching/DistributedCacheClient.cs new file mode 100644 index 00000000..74c48b95 --- /dev/null +++ b/src/RapidField.SolidInstruments.Core/Caching/DistributedCacheClient.cs @@ -0,0 +1,288 @@ +// ================================================================================================================================= +// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ================================================================================================================================= + +using Microsoft.Extensions.Caching.Distributed; +using Microsoft.Extensions.Caching.Memory; +using RapidField.SolidInstruments.Core.ArgumentValidation; +using RapidField.SolidInstruments.Core.Concurrency; +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Json; + +namespace RapidField.SolidInstruments.Core.Caching +{ + /// + /// Represents a read-write client for accessing strongly typed, remotely cached objects using textual keys. + /// + /// + /// is the default implementation of . + /// + public sealed class DistributedCacheClient : CacheClient, IDistributedCacheClient + { + /// + /// Initializes a new instance of the class. + /// + /// + /// The underlying distributed cache, or if the distributed cache client is non-operative. + /// + public DistributedCacheClient(IDistributedCache cache) + : base(cache is null ? ConcurrencyControlMode.Unconstrained : ConcurrencyControlMode.ProcessorCountSemaphore) + { + Cache = cache; + } + + /// + /// Manually resets the sliding expiration for the specified object. + /// + /// + /// Under normal use scenarios it is not necessary to invoke because implementations of + /// are expected to reset the sliding expiration. + /// + /// + /// A textual key which uniquely identifies the cached object for which the sliding expiration is reset. + /// + /// + /// is empty. + /// + /// + /// is . + /// + /// + /// An exception was raised while attempting to access the cache. + /// + /// + /// The object is disposed. + /// + public void Refresh(String key) + { + RejectIfDisposed(); + _ = key.RejectIf().IsNullOrEmpty(nameof(key)); + + try + { + if (IsOperative) + { + Cache?.Refresh(key); + } + } + catch (CacheAccessException) + { + throw; + } + catch (Exception exception) + { + throw new CacheAccessException("An exception was raised while refreshing the cached object.", exception); + } + } + + /// + /// Releases all resources consumed by the current . + /// + /// + /// A value indicating whether or not disposal was invoked by user code. + /// + protected override void Dispose(Boolean disposing) => base.Dispose(disposing); + + /// + /// Removes the cached object using the specified textual key. + /// + /// + /// A textual key which uniquely identifies the cached object to remove. + /// + /// + /// A token that represents and manages contextual thread safety. + /// + /// + /// is empty. + /// + /// + /// is . + /// + /// + /// An exception was raised while attempting to access the cache. + /// + /// + /// The object is disposed. + /// + protected override void Invalidate(String key, IConcurrencyControlToken controlToken) + { + if (IsOperative) + { + Cache?.Remove(key); + } + } + + /// + /// Attempts to retrieve the cached object using the specified textual key. + /// + /// + /// The type of the cached object. + /// + /// + /// A textual key which uniquely identifies a value in the cache. + /// + /// + /// The object retrieved from the cache, or if the object was not successfully retrieved. + /// + protected override TValue TryRead(String key) + where TValue : class + { + if (IsOperative) + { + var serializer = new DataContractJsonSerializer(typeof(TValue), SerializerSettings); + var serializedValue = Cache?.Get(key); + + try + { + return serializedValue is null ? null : Deserialize(serializer, serializedValue) as TValue; + } + catch (SerializationException) + { + return null; + } + } + + return null; + } + + /// + /// Adds or updates the specified object using the specified key. + /// + /// + /// The type of the cached object. + /// + /// + /// A textual key which uniquely identifies in the cache. + /// + /// + /// The object to add or update. + /// + /// + /// A token that represents and manages contextual thread safety. + /// + /// + /// is invalid or an error occurred during serialization. + /// + protected override void Write(String key, TValue value, IConcurrencyControlToken controlToken) + where TValue : class + { + if (IsOperative) + { + var serializer = new DataContractJsonSerializer(typeof(TValue), SerializerSettings); + var serializedValue = Serialize(serializer, value); + + if (serializedValue is not null) + { + Cache?.Set(key, serializedValue); + } + } + } + + /// + /// Converts the specified serialized object to its typed equivalent. + /// + /// + /// A serializer that deserializes . + /// + /// + /// A serialized object. + /// + /// + /// The deserialized object. + /// + /// + /// is invalid or an error occurred during deserialization. + /// + [DebuggerHidden] + private static Object Deserialize(DataContractJsonSerializer serializer, Byte[] serializedObject) + { + using (var stream = new MemoryStream(serializedObject)) + { + try + { + return serializer.ReadObject(stream) ?? throw new SerializationException("The specified serialized object is invalid."); + } + catch (SerializationException) + { + throw; + } + catch (Exception exception) + { + throw new SerializationException("An error occurred during deserialization. See inner exception.", exception); + } + } + } + + /// + /// Converts the specified object to a serialized byte array. + /// + /// + /// A serializer that serializes . + /// + /// + /// An object to be serialized. + /// + /// + /// The serialized byte array. + /// + /// + /// is invalid or an error occurred during serialization. + /// + [DebuggerHidden] + private static Byte[] Serialize(DataContractJsonSerializer serializer, Object target) + { + using (var stream = new MemoryStream()) + { + try + { + serializer.WriteObject(stream, target); + } + catch (SerializationException) + { + throw; + } + catch (Exception exception) + { + throw new SerializationException("An error occurred during serialization. See inner exception.", exception); + } + + return stream.ToArray(); + } + } + + /// + /// Gets a value indicating whether or not the client is operative. + /// + public override Boolean IsOperative => Cache is not null; + + /// + /// Gets the underlying distributed cache, or if the distributed cache client is non-operative. + /// + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private IDistributedCache Cache + { + get; + } + + /// + /// Represents the format string that is used by + /// to serialize objects. + /// + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private const String DateTimeSerializationFormatString = "o"; + + /// + /// Represents settings used by to serialize objects. + /// + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private static readonly DataContractJsonSerializerSettings SerializerSettings = new DataContractJsonSerializerSettings + { + DateTimeFormat = new DateTimeFormat(DateTimeSerializationFormatString), + EmitTypeInformation = EmitTypeInformation.AsNeeded, + SerializeReadOnlyTypes = false + }; + } +} \ No newline at end of file diff --git a/src/RapidField.SolidInstruments.Core/Caching/DualLayerCacheClient.cs b/src/RapidField.SolidInstruments.Core/Caching/DualLayerCacheClient.cs new file mode 100644 index 00000000..93b5e9cf --- /dev/null +++ b/src/RapidField.SolidInstruments.Core/Caching/DualLayerCacheClient.cs @@ -0,0 +1,180 @@ +// ================================================================================================================================= +// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ================================================================================================================================= + +using Microsoft.Extensions.Caching.Distributed; +using RapidField.SolidInstruments.Core.ArgumentValidation; +using RapidField.SolidInstruments.Core.Concurrency; +using System; +using System.Diagnostics; + +namespace RapidField.SolidInstruments.Core.Caching +{ + /// + /// Represents a dual layer (local and remote) read-write client for accessing strongly typed cached objects using textual keys. + /// + public sealed class DualLayerCacheClient : CacheClient + { + /// + /// Initializes a new instance of the class. + /// + /// + /// The underlying remote (distributed) cache. + /// + /// + /// is . + /// + public DualLayerCacheClient(IDistributedCache remoteCache) + : this(remoteCache, InMemoryCachingStrategy.Moderate) + { + return; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The underlying remote (distributed) cache. + /// + /// + /// A value specifying the cache access and management behavior of the local (in-memory) client. The default value is + /// . + /// + /// + /// is . + /// + /// + /// is equal to . + /// + public DualLayerCacheClient(IDistributedCache remoteCache, InMemoryCachingStrategy localCachingStrategy) + : base(ConcurrencyControlMode.Unconstrained) + { + LocalCache = new InMemoryCacheClient(localCachingStrategy); + RemoteCache = new DistributedCacheClient(remoteCache.RejectIf().IsNull(nameof(remoteCache)).TargetArgument); + } + + /// + /// Releases all resources consumed by the current . + /// + /// + /// A value indicating whether or not disposal was invoked by user code. + /// + protected override void Dispose(Boolean disposing) + { + try + { + LocalCache?.Dispose(); + RemoteCache?.Dispose(); + } + finally + { + base.Dispose(disposing); + } + } + + /// + /// Removes the cached object using the specified textual key. + /// + /// + /// A textual key which uniquely identifies the cached object to remove. + /// + /// + /// A token that represents and manages contextual thread safety. + /// + /// + /// is empty. + /// + /// + /// is . + /// + /// + /// An exception was raised while attempting to access the cache. + /// + /// + /// The object is disposed. + /// + protected override void Invalidate(String key, IConcurrencyControlToken controlToken) + { + try + { + RemoteCache.Invalidate(key); + } + finally + { + LocalCache.Invalidate(key); + } + } + + /// + /// Attempts to retrieve the cached object using the specified textual key. + /// + /// + /// The type of the cached object. + /// + /// + /// A textual key which uniquely identifies a value in the cache. + /// + /// + /// The object retrieved from the cache, or if the object was not successfully retrieved. + /// + protected override TValue TryRead(String key) + where TValue : class + { + if (LocalCache.TryRead(key, out var localValue)) + { + return localValue; + } + else if (RemoteCache.TryRead(key, out var remoteValue)) + { + return remoteValue; + } + + return null; + } + + /// + /// Adds or updates the specified object using the specified key. + /// + /// + /// The type of the cached object. + /// + /// + /// A textual key which uniquely identifies in the cache. + /// + /// + /// The object to add or update. + /// + /// + /// A token that represents and manages contextual thread safety. + /// + protected override void Write(String key, TValue value, IConcurrencyControlToken controlToken) + where TValue : class + { + try + { + RemoteCache.Write(key, value); + } + finally + { + LocalCache.Write(key, value); + } + } + + /// + /// Gets a value indicating whether or not the client is operative. + /// + public override Boolean IsOperative => LocalCache.IsOperative || RemoteCache.IsOperative; + + /// + /// Represents the underlying local (in-memory) cache client. + /// + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private readonly IInMemoryCacheClient LocalCache; + + /// + /// Represents the underlying remote (distributed) cache client. + /// + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private readonly IDistributedCacheClient RemoteCache; + } +} \ No newline at end of file diff --git a/src/RapidField.SolidInstruments.Core/Caching/ICacheClient.cs b/src/RapidField.SolidInstruments.Core/Caching/ICacheClient.cs index 68855ffa..c8a31c26 100644 --- a/src/RapidField.SolidInstruments.Core/Caching/ICacheClient.cs +++ b/src/RapidField.SolidInstruments.Core/Caching/ICacheClient.cs @@ -2,7 +2,12 @@ // Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. // ================================================================================================================================= +using RapidField.SolidInstruments.Core.ArgumentValidation; +using RapidField.SolidInstruments.Core.Extensions; using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; using System.Threading.Tasks; namespace RapidField.SolidInstruments.Core.Caching @@ -64,6 +69,64 @@ public interface ICacheClient : ICacheReader, ICacheWriter public TValue Process(String key, Func produceValueFunction) where TValue : class; + /// + /// Attempts to retrieve the cached object using the specified textual key and, failing that, invokes the specified function + /// to produce the object and adds it to the cache. + /// + /// + /// The type of the cached object. + /// + /// + /// An ordered collection of objects from which to construct a unique textual key. + /// + /// + /// A function that produces the object if it is not found in the cache. + /// + /// + /// The resulting cached object. + /// + /// + /// is empty. + /// + /// + /// is -or- is + /// . + /// + /// + /// An exception was raised while attempting to access the cache or produce the value. + /// + /// + /// The object is disposed. + /// + public TValue Process(IEnumerable compositeKey, Func produceValueFunction) + where TValue : class + { + _ = compositeKey.RejectIf().IsNullOrEmpty(nameof(compositeKey)); + var valueType = typeof(TValue); + + try + { + var keyMaterial = new StringBuilder($"{valueType.FullName}{CompositeKeyElementDelimitingCharacter}"); + + foreach (var keyElement in compositeKey) + { + var keyElementString = keyElement?.ToString() ?? CompositeKeyNullElementValue; + keyMaterial.Append($"{keyElementString}{CompositeKeyElementDelimitingCharacter}"); + } + + var key = Encoding.Unicode.GetBytes(keyMaterial.ToString()).GenerateChecksumIdentity().ToSerializedString(); + return Process($"{CompositeKeyPrependedCharacter}{key}", produceValueFunction); + } + catch (CacheAccessException) + { + throw; + } + catch (Exception exception) + { + throw new CacheAccessException(valueType, exception); + } + } + /// /// Asynchronously attempts to retrieve the cached object using the specified textual key and, failing that, invokes the /// specified function to produce the object and adds it to the cache. @@ -96,6 +159,38 @@ public TValue Process(String key, Func produceValueFunction) public Task ProcessAsync(String key, Func produceValueFunction) where TValue : class; + /// + /// Asynchronously attempts to retrieve the cached object using the specified textual key and, failing that, invokes the + /// specified function to produce the object and adds it to the cache. + /// + /// + /// The type of the cached object. + /// + /// + /// An ordered collection of objects from which to construct a unique textual key. + /// + /// + /// A function that produces the object if it is not found in the cache. + /// + /// + /// A task representing the asynchronous operation and containing the resulting cached object. + /// + /// + /// is empty. + /// + /// + /// is -or- is + /// . + /// + /// + /// An exception was raised while attempting to access the cache or produce the value. + /// + /// + /// The object is disposed. + /// + public Task ProcessAsync(IEnumerable compositeKey, Func produceValueFunction) + where TValue : class => Task.Factory.StartNew(() => Process(compositeKey, produceValueFunction)); + /// /// Gets a value indicating whether or not the client is operative. /// @@ -103,5 +198,23 @@ public Boolean IsOperative { get; } + + /// + /// Represents a character that is used as a delimiter between composite key element strings. + /// + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private const Char CompositeKeyElementDelimitingCharacter = ':'; + + /// + /// Represents a textual representation of composite key elements. + /// + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private const String CompositeKeyNullElementValue = "_null_"; + + /// + /// Represents a character that is prepended to textual composite keys. + /// + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private const Char CompositeKeyPrependedCharacter = '_'; } } \ No newline at end of file diff --git a/src/RapidField.SolidInstruments.Core/Caching/IDistributedCacheClient.cs b/src/RapidField.SolidInstruments.Core/Caching/IDistributedCacheClient.cs index dbb88358..9b5f3ed3 100644 --- a/src/RapidField.SolidInstruments.Core/Caching/IDistributedCacheClient.cs +++ b/src/RapidField.SolidInstruments.Core/Caching/IDistributedCacheClient.cs @@ -2,6 +2,8 @@ // Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. // ================================================================================================================================= +using System; + namespace RapidField.SolidInstruments.Core.Caching { /// @@ -9,5 +11,28 @@ namespace RapidField.SolidInstruments.Core.Caching /// public interface IDistributedCacheClient : ICacheClient { + /// + /// Manually resets the sliding expiration for the specified object. + /// + /// + /// Under normal use scenarios it is not necessary to invoke because implementations of + /// are expected to reset the sliding expiration. + /// + /// + /// A textual key which uniquely identifies the cached object for which the sliding expiration is reset. + /// + /// + /// is empty. + /// + /// + /// is . + /// + /// + /// An exception was raised while attempting to access the cache. + /// + /// + /// The object is disposed. + /// + public void Refresh(String key); } } \ No newline at end of file diff --git a/src/RapidField.SolidInstruments.Core/Caching/InMemoryCacheClient.cs b/src/RapidField.SolidInstruments.Core/Caching/InMemoryCacheClient.cs index 83b1bcd3..b88b63ba 100644 --- a/src/RapidField.SolidInstruments.Core/Caching/InMemoryCacheClient.cs +++ b/src/RapidField.SolidInstruments.Core/Caching/InMemoryCacheClient.cs @@ -211,11 +211,6 @@ protected override void Write(String key, TValue value, IConcurrencyCont [DebuggerBrowsable(DebuggerBrowsableState.Never)] private IOptions CacheOptions => LazyCacheOptions?.Value; - /// - /// Represents a non-operative in-memory cache client. - /// - public static readonly IInMemoryCacheClient NonOperative = new InMemoryCacheClient(InMemoryCachingStrategy.NoCaching); - /// /// Represents the default value specifying the cache access and management behavior of the client. /// diff --git a/src/RapidField.SolidInstruments.Core/Concurrency/ConcurrencyControlToken.cs b/src/RapidField.SolidInstruments.Core/Concurrency/ConcurrencyControlToken.cs index 929f60ef..0ba3fdff 100644 --- a/src/RapidField.SolidInstruments.Core/Concurrency/ConcurrencyControlToken.cs +++ b/src/RapidField.SolidInstruments.Core/Concurrency/ConcurrencyControlToken.cs @@ -79,7 +79,7 @@ internal ConcurrencyControlToken(SynchronizationContext context, Thread granteeT /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(ConcurrencyControlToken a, IConcurrencyControlToken b) => a == b == false; + public static Boolean operator !=(ConcurrencyControlToken a, IConcurrencyControlToken b) => (a == b) is false; /// /// Determines whether or not a specified instance is less than another specified diff --git a/src/RapidField.SolidInstruments.Core/DateTimeRange.cs b/src/RapidField.SolidInstruments.Core/DateTimeRange.cs index 5768b472..326574d4 100644 --- a/src/RapidField.SolidInstruments.Core/DateTimeRange.cs +++ b/src/RapidField.SolidInstruments.Core/DateTimeRange.cs @@ -111,7 +111,7 @@ public DateTimeRange(DateTime start, DateTime end, DateTimeRangeGranularity gran /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(DateTimeRange dateTimeRangeOne, DateTimeRange dateTimeRangeTwo) => dateTimeRangeOne == dateTimeRangeTwo == false; + public static Boolean operator !=(DateTimeRange dateTimeRangeOne, DateTimeRange dateTimeRangeTwo) => (dateTimeRangeOne == dateTimeRangeTwo) is false; /// /// Determines whether or not two specified instances are equal. @@ -185,7 +185,7 @@ public static DateTimeRange Parse(String input) /// public static Boolean TryParse(String input, out DateTimeRange result) { - if (Parse(input, out var start, out var end, out var granularity, false) == false) + if (Parse(input, out var start, out var end, out var granularity, false) is false) { result = null; return false; @@ -457,21 +457,21 @@ private static Boolean Parse(String input, out DateTime start, out DateTime end, granularity = (DateTimeRangeGranularity)Enum.Parse(typeof(DateTimeRangeGranularity), rawValueSubstrings[2]); return true; } - else if (DateTimeExtensions.TryParseExtendedFormatDateTimeString(rawValueSubstrings[0], out start) == false) + else if (DateTimeExtensions.TryParseExtendedFormatDateTimeString(rawValueSubstrings[0], out start) is false) { start = default; end = default; granularity = DateTimeRangeGranularity.Unspecified; return false; } - else if (DateTimeExtensions.TryParseExtendedFormatDateTimeString(rawValueSubstrings[1], out end) == false) + else if (DateTimeExtensions.TryParseExtendedFormatDateTimeString(rawValueSubstrings[1], out end) is false) { start = default; end = default; granularity = DateTimeRangeGranularity.Unspecified; return false; } - else if (Enum.TryParse(rawValueSubstrings[2], out granularity) == false) + else if (Enum.TryParse(rawValueSubstrings[2], out granularity) is false) { return false; } diff --git a/src/RapidField.SolidInstruments.Core/Extensions/IEnumerableExtensions.cs b/src/RapidField.SolidInstruments.Core/Extensions/IEnumerableExtensions.cs index fd155c5d..8d5b40db 100644 --- a/src/RapidField.SolidInstruments.Core/Extensions/IEnumerableExtensions.cs +++ b/src/RapidField.SolidInstruments.Core/Extensions/IEnumerableExtensions.cs @@ -48,15 +48,15 @@ public static Boolean IsEquivalentTo(this IEnumerable target, IEnumerable< var targetElement = target.ElementAt(i); var otherElement = otherCollection.ElementAt(i); - if (targetElement == null && otherElement == null) + if (targetElement is null && otherElement is null) { continue; } - else if (targetElement == null && otherElement != null) + else if (targetElement is null && otherElement is not null) { return false; } - else if (targetElement != null && otherElement == null) + else if (targetElement is not null && otherElement is null) { return false; } @@ -84,6 +84,6 @@ public static Boolean IsEquivalentTo(this IEnumerable target, IEnumerable< /// if the current is or empty, otherwise /// . /// - public static Boolean IsNullOrEmpty(this IEnumerable target) => target is null || target.Any() == false; + public static Boolean IsNullOrEmpty(this IEnumerable target) => target is null || target.Any() is false; } } \ No newline at end of file diff --git a/src/RapidField.SolidInstruments.Core/Extensions/ObjectExtensions.cs b/src/RapidField.SolidInstruments.Core/Extensions/ObjectExtensions.cs index 67866162..cfb8dff0 100644 --- a/src/RapidField.SolidInstruments.Core/Extensions/ObjectExtensions.cs +++ b/src/RapidField.SolidInstruments.Core/Extensions/ObjectExtensions.cs @@ -21,7 +21,7 @@ namespace RapidField.SolidInstruments.Core.Extensions public static class ObjectExtensions { /// - /// Reflectively interrogates the current object to determine its total size, in bytes, in memory. + /// Reflectively interrogates the current object to determine the total number of bytes that it occupies in memory. /// /// /// The current instance of the . @@ -122,18 +122,6 @@ internal static Object GetSerializedClone(this Object target) } } - /// - /// Reflectively interrogates the current value object to determine its total size, in bytes, in memory. - /// - /// - /// The current instance of the . - /// - /// - /// The total size of the current value object, in bytes. - /// - [DebuggerHidden] - private static Int32 CalculateValueSizeInBytes(this Object target) => target is null ? 0 : Marshal.SizeOf(target); - /// /// Converts the specified serialized object to its typed equivalent. /// @@ -188,7 +176,7 @@ private static Object Deserialize(DataContractJsonSerializer serializer, Byte[] [DebuggerHidden] private static void FlattenCollectionGraph(this Object target, IList collections, IList references, IList values) { - if (target is IEnumerable collection && collections.Contains(collection) == false) + if (target is IEnumerable collection && collections.Contains(collection) is false) { collections.Add(collection); @@ -268,7 +256,7 @@ private static void FlattenObjectGraph(this Object target, IList co [MethodImpl(MethodImplOptions.AggressiveInlining)] private static void FlattenReferenceGraph(this Object target, Type targetType, IList collections, IList references, IList values) { - if (references.Contains(target) == false) + if (references.Contains(target) is false) { references.Add(target); @@ -338,18 +326,12 @@ private static Byte[] Serialize(DataContractJsonSerializer serializer, Object ta } /// - /// Represents the format string that is used by to - /// serialize objects. + /// Represents the format string that is used by and + /// to serialize objects. /// [DebuggerBrowsable(DebuggerBrowsableState.Never)] private const String DateTimeSerializationFormatString = "o"; - /// - /// Represents the type. - /// - [DebuggerBrowsable(DebuggerBrowsableState.Never)] - private static readonly Type CollectionGenericInterfaceType = typeof(IEnumerable<>); - /// /// Represents the type. /// diff --git a/src/RapidField.SolidInstruments.Core/Extensions/UriExtensions.cs b/src/RapidField.SolidInstruments.Core/Extensions/UriExtensions.cs index c954887e..970bca83 100644 --- a/src/RapidField.SolidInstruments.Core/Extensions/UriExtensions.cs +++ b/src/RapidField.SolidInstruments.Core/Extensions/UriExtensions.cs @@ -43,7 +43,7 @@ public static class UriExtensions /// public static Uri AppendQueryStringData(this Uri target, IDictionary queryStringData) { - if (target.IsAbsoluteUri == false) + if (target.IsAbsoluteUri is false) { throw new InvalidOperationException($"{nameof(AppendQueryStringData)} cannot be invoked against instances representing relative URIs."); } diff --git a/src/RapidField.SolidInstruments.Core/Model.cs b/src/RapidField.SolidInstruments.Core/Model.cs index 2848c54b..14c02cbe 100644 --- a/src/RapidField.SolidInstruments.Core/Model.cs +++ b/src/RapidField.SolidInstruments.Core/Model.cs @@ -61,7 +61,7 @@ protected Model(TIdentifier identifier) /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(Model a, IModel b) => a == b == false; + public static Boolean operator !=(Model a, IModel b) => (a == b) is false; /// /// Determines whether or not a specified instance is less than another specified @@ -231,7 +231,7 @@ protected Model() /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(Model a, IModel b) => a == b == false; + public static Boolean operator !=(Model a, IModel b) => (a == b) is false; /// /// Determines whether or not two specified instances are equal. diff --git a/src/RapidField.SolidInstruments.Core/Nix.cs b/src/RapidField.SolidInstruments.Core/Nix.cs index 8847f2de..03a8d06d 100644 --- a/src/RapidField.SolidInstruments.Core/Nix.cs +++ b/src/RapidField.SolidInstruments.Core/Nix.cs @@ -43,7 +43,7 @@ private Nix(Byte value) /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(Nix a, Nix b) => a == b == false; + public static Boolean operator !=(Nix a, Nix b) => (a == b) is false; /// /// Determines whether or not a specified instance is less than another specified instance. diff --git a/src/RapidField.SolidInstruments.Core/ReferenceManager.cs b/src/RapidField.SolidInstruments.Core/ReferenceManager.cs index f9a50751..9af5e54f 100644 --- a/src/RapidField.SolidInstruments.Core/ReferenceManager.cs +++ b/src/RapidField.SolidInstruments.Core/ReferenceManager.cs @@ -144,7 +144,7 @@ private void Prune() reference?.Poll(); } - References = new List(References?.Where(reference => reference.IsDead == false) ?? Array.Empty()); + References = new List(References?.Where(reference => reference.IsDead is false) ?? Array.Empty()); } } @@ -230,7 +230,7 @@ internal ManagedReference(T target, TimeSpan strongReferenceMinimumLifeSpan) /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(ManagedReference a, ManagedReference b) => a == b == false; + public static Boolean operator !=(ManagedReference a, ManagedReference b) => (a == b) is false; /// /// Determines whether or not two specified instances are equal. diff --git a/src/RapidField.SolidInstruments.Core/SemanticVersion.cs b/src/RapidField.SolidInstruments.Core/SemanticVersion.cs index 4b26f18a..2706c7a2 100644 --- a/src/RapidField.SolidInstruments.Core/SemanticVersion.cs +++ b/src/RapidField.SolidInstruments.Core/SemanticVersion.cs @@ -200,7 +200,7 @@ public static SemanticVersion OfAssembly(Assembly assembly) /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(SemanticVersion a, ISemanticVersion b) => a == b == false; + public static Boolean operator !=(SemanticVersion a, ISemanticVersion b) => (a == b) is false; /// /// Determines whether or not a specified instance is less than another specified instance. @@ -463,12 +463,12 @@ public override Int32 GetHashCode() { var hashCode = (433494437 ^ (MajorVersion * 514229) ^ (MinorVersion * 28657) ^ (PatchVersion * 1597) ^ 233).GetHashCode(); - if (PreReleaseLabel.IsNullOrEmpty() == false) + if (PreReleaseLabel.IsNullOrEmpty() is false) { hashCode ^= PreReleaseLabel.GetHashCode(); } - if (BuildMetadata.IsNullOrEmpty() == false) + if (BuildMetadata.IsNullOrEmpty() is false) { hashCode ^= BuildMetadata.GetHashCode(); } @@ -607,12 +607,12 @@ public override String ToString() var versionNumbers = $"{MajorVersion}{DelimiterForVersionNumber}{MinorVersion}{DelimiterForVersionNumber}{PatchVersion}"; var stringBuilder = new StringBuilder(versionNumbers); - if (PreReleaseLabel.IsNullOrEmpty() == false) + if (PreReleaseLabel.IsNullOrEmpty() is false) { _ = stringBuilder.Append($"{DelimiterPrefixForPreReleaseLabel}{PreReleaseLabel}"); } - if (BuildMetadata.IsNullOrEmpty() == false) + if (BuildMetadata.IsNullOrEmpty() is false) { _ = stringBuilder.Append($"{DelimiterPrefixForBuildMetadata}{BuildMetadata}"); } @@ -825,7 +825,7 @@ public String BuildMetadata /// Gets a value indicating whether or not the current includes build metadata. /// [IgnoreDataMember] - public Boolean HasBuildMetadata => BuildMetadata.IsNullOrEmpty() == false; + public Boolean HasBuildMetadata => BuildMetadata.IsNullOrEmpty() is false; /// /// Gets a value indicating whether or not the current represents a new major version (eg. @@ -852,13 +852,13 @@ public String BuildMetadata /// Gets a value indicating whether or not the current represents a pre-release version. /// [IgnoreDataMember] - public Boolean IsPreRelease => PreReleaseLabel.IsNullOrEmpty() == false; + public Boolean IsPreRelease => PreReleaseLabel.IsNullOrEmpty() is false; /// /// Gets a value indicating whether or not the current represents a stable version. /// [IgnoreDataMember] - public Boolean IsStable => IsPreRelease == false; + public Boolean IsStable => IsPreRelease is false; /// /// Gets or sets the major version number, which is incremented for compatibility-breaking feature changes. diff --git a/src/RapidField.SolidInstruments.Core/TimeOfDay.cs b/src/RapidField.SolidInstruments.Core/TimeOfDay.cs index 4e451b47..87b35790 100644 --- a/src/RapidField.SolidInstruments.Core/TimeOfDay.cs +++ b/src/RapidField.SolidInstruments.Core/TimeOfDay.cs @@ -135,7 +135,7 @@ public TimeOfDay(TimeZoneInfo zone, Int32 hour, Int32 minute, Int32 second, Int3 /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(TimeOfDay a, TimeOfDay b) => a == b == false; + public static Boolean operator !=(TimeOfDay a, TimeOfDay b) => (a == b) is false; /// /// Determines whether or not a specified instance is less than another specified instance. @@ -262,7 +262,7 @@ public TimeOfDay(TimeZoneInfo zone, Int32 hour, Int32 minute, Int32 second, Int3 /// public static Boolean TryParse(String input, out TimeOfDay result) { - if (Parse(input, out var zone, out var hour, out var minute, out var second, out var millisecond, false) == false) + if (Parse(input, out var zone, out var hour, out var minute, out var second, out var millisecond, false) is false) { result = null; return false; @@ -783,7 +783,7 @@ private static Boolean Parse(String input, out TimeZoneInfo zone, out Int32 hour second = Int32.Parse(secondString); millisecond = Int32.Parse(millisecondString); } - else if (Int32.TryParse(hourString, out hour) == false) + else if (Int32.TryParse(hourString, out hour) is false) { zone = null; hour = default; @@ -792,7 +792,7 @@ private static Boolean Parse(String input, out TimeZoneInfo zone, out Int32 hour millisecond = default; return false; } - else if (Int32.TryParse(minuteString, out minute) == false) + else if (Int32.TryParse(minuteString, out minute) is false) { zone = null; hour = default; @@ -801,7 +801,7 @@ private static Boolean Parse(String input, out TimeZoneInfo zone, out Int32 hour millisecond = default; return false; } - else if (Int32.TryParse(secondString, out second) == false) + else if (Int32.TryParse(secondString, out second) is false) { zone = null; hour = default; @@ -810,7 +810,7 @@ private static Boolean Parse(String input, out TimeZoneInfo zone, out Int32 hour millisecond = default; return false; } - else if (Int32.TryParse(millisecondString, out millisecond) == false) + else if (Int32.TryParse(millisecondString, out millisecond) is false) { zone = null; hour = default; diff --git a/src/RapidField.SolidInstruments.Cryptography/CryptographicKey.cs b/src/RapidField.SolidInstruments.Cryptography/CryptographicKey.cs index 84c0397b..97f173ba 100644 --- a/src/RapidField.SolidInstruments.Cryptography/CryptographicKey.cs +++ b/src/RapidField.SolidInstruments.Cryptography/CryptographicKey.cs @@ -211,7 +211,7 @@ protected override void Dispose(Boolean disposing) { try { - if (IsDisposed == false) + if (IsDisposed is false) { LazyPbkdf2Provider?.Dispose(); KeySource?.Dispose(); diff --git a/src/RapidField.SolidInstruments.Cryptography/Extensions/RandomNumberGeneratorExtensions.cs b/src/RapidField.SolidInstruments.Cryptography/Extensions/RandomNumberGeneratorExtensions.cs index 10a509a2..8e6829e7 100644 --- a/src/RapidField.SolidInstruments.Cryptography/Extensions/RandomNumberGeneratorExtensions.cs +++ b/src/RapidField.SolidInstruments.Cryptography/Extensions/RandomNumberGeneratorExtensions.cs @@ -574,7 +574,7 @@ public static void FillStringArray(this RandomNumberGenerator target, String[] a array.RejectIf().IsNull(nameof(array)); characterLength.RejectIf().IsLessThan(1, nameof(characterLength)); - if ((permitLowercaseAlphabetic || permitUppercaseAlphabetic || permitNumeric || permitSymbolic || permitWhiteSpace || permitControl) == false) + if ((permitLowercaseAlphabetic || permitUppercaseAlphabetic || permitNumeric || permitSymbolic || permitWhiteSpace || permitControl) is false) { throw new ArgumentException(NoCharacterTypesPermittedExceptionMessageTemplate); } @@ -638,7 +638,7 @@ public static void FillStringArray(this RandomNumberGenerator target, String[] a array.RejectIf().IsNull(nameof(array)); characterLengthFloor.RejectIf().IsLessThan(0, nameof(characterLengthFloor)).OrIf().IsGreaterThan(characterLengthCeiling, nameof(characterLengthFloor), nameof(characterLengthCeiling)); - if ((permitLowercaseAlphabetic || permitUppercaseAlphabetic || permitNumeric || permitSymbolic || permitWhiteSpace || permitControl) == false) + if ((permitLowercaseAlphabetic || permitUppercaseAlphabetic || permitNumeric || permitSymbolic || permitWhiteSpace || permitControl) is false) { throw new ArgumentException(NoCharacterTypesPermittedExceptionMessageTemplate); } @@ -939,7 +939,7 @@ public static Char GetChar(this RandomNumberGenerator target) /// public static Char GetChar(this RandomNumberGenerator target, Boolean permitNonLatin, Boolean permitLowercaseAlphabetic, Boolean permitUppercaseAlphabetic, Boolean permitNumeric, Boolean permitSymbolic, Boolean permitWhiteSpace, Boolean permitControl) { - if ((permitLowercaseAlphabetic || permitUppercaseAlphabetic || permitNumeric || permitSymbolic || permitWhiteSpace || permitControl) == false) + if ((permitLowercaseAlphabetic || permitUppercaseAlphabetic || permitNumeric || permitSymbolic || permitWhiteSpace || permitControl) is false) { throw new ArgumentException(NoCharacterTypesPermittedExceptionMessageTemplate); } @@ -1262,7 +1262,7 @@ public static Single GetSingle(this RandomNumberGenerator target, Single floor, /// public static String GetString(this RandomNumberGenerator target, Int32 characterLength, Boolean permitNonLatin, Boolean permitLowercaseAlphabetic, Boolean permitUppercaseAlphabetic, Boolean permitNumeric, Boolean permitSymbolic, Boolean permitWhiteSpace, Boolean permitControl) { - if ((permitLowercaseAlphabetic || permitUppercaseAlphabetic || permitNumeric || permitSymbolic || permitWhiteSpace || permitControl) == false) + if ((permitLowercaseAlphabetic || permitUppercaseAlphabetic || permitNumeric || permitSymbolic || permitWhiteSpace || permitControl) is false) { throw new ArgumentException(NoCharacterTypesPermittedExceptionMessageTemplate); } @@ -1318,7 +1318,7 @@ public static String GetString(this RandomNumberGenerator target, Int32 characte { characterLengthFloor.RejectIf().IsLessThan(0, nameof(characterLengthFloor)).OrIf().IsGreaterThan(characterLengthCeiling, nameof(characterLengthFloor), nameof(characterLengthCeiling)); - if ((permitLowercaseAlphabetic || permitUppercaseAlphabetic || permitNumeric || permitSymbolic || permitWhiteSpace || permitControl) == false) + if ((permitLowercaseAlphabetic || permitUppercaseAlphabetic || permitNumeric || permitSymbolic || permitWhiteSpace || permitControl) is false) { throw new ArgumentException(NoCharacterTypesPermittedExceptionMessageTemplate); } @@ -1671,7 +1671,7 @@ private static void GenerateChar(RandomNumberGenerator target, Boolean permitNon var singlePassIterationCount = characterBytes.Length - characterByteLength; target.GetBytes(characterBytes); - while (PermuteCharacterGeneration(characterBytes, singlePassIterationCount, characterByteLength, characterEncoding, permitNonLatin, permitLowercaseAlphabetic, permitUppercaseAlphabetic, permitNumeric, permitSymbolic, permitWhiteSpace, permitControl, out randomValue) == false) + while (PermuteCharacterGeneration(characterBytes, singlePassIterationCount, characterByteLength, characterEncoding, permitNonLatin, permitLowercaseAlphabetic, permitUppercaseAlphabetic, permitNumeric, permitSymbolic, permitWhiteSpace, permitControl, out randomValue) is false) { target.GetBytes(characterBytes); } @@ -2261,7 +2261,7 @@ private static Boolean PermuteCharacterGeneration(Byte[] characterBytes, Int32 i for (var i = 0; i < iterationCount; i++) { - if (permitNonLatin == false && characterBytes[i] > 0x7f) + if (permitNonLatin is false && characterBytes[i] > 0x7f) { // 0x7f is the last valid ASCII character. continue; diff --git a/src/RapidField.SolidInstruments.Cryptography/Hashing/HashTree.cs b/src/RapidField.SolidInstruments.Cryptography/Hashing/HashTree.cs index 26f80533..2a1c6dd4 100644 --- a/src/RapidField.SolidInstruments.Cryptography/Hashing/HashTree.cs +++ b/src/RapidField.SolidInstruments.Cryptography/Hashing/HashTree.cs @@ -122,7 +122,7 @@ public HashTree(IHashingProcessor hashingProcessor, HashingAlgorithmSpec /// public void AddBlockRange(IEnumerable blocks) { - if (blocks.Any() == false) + if (blocks.Any() is false) { return; } diff --git a/src/RapidField.SolidInstruments.Cryptography/Secrets/Secret.cs b/src/RapidField.SolidInstruments.Cryptography/Secrets/Secret.cs index ab5330e4..fd60a854 100644 --- a/src/RapidField.SolidInstruments.Cryptography/Secrets/Secret.cs +++ b/src/RapidField.SolidInstruments.Cryptography/Secrets/Secret.cs @@ -492,7 +492,7 @@ private Guid GetDerivedIdentity() [DebuggerHidden] private void Read(Action> readAction, IConcurrencyControlToken controlToken) { - if (HasValue == false) + if (HasValue is false) { throw new InvalidOperationException($"The secret does not have a value. This exception can be avoided by evaluating {nameof(HasValue)} before performing a read operation."); } @@ -628,7 +628,7 @@ private void Write(Func writeFunction, IConcurrencyControlToken controlT { var value = writeFunction(); - if (ValueType.IsValueType == false && value is null) + if (ValueType.IsValueType is false && value is null) { throw new SecretAccessException("The specified write function produced a null secret value."); } diff --git a/src/RapidField.SolidInstruments.Cryptography/SecureMemory.cs b/src/RapidField.SolidInstruments.Cryptography/SecureMemory.cs index a844fb1f..7f727e3a 100644 --- a/src/RapidField.SolidInstruments.Cryptography/SecureMemory.cs +++ b/src/RapidField.SolidInstruments.Cryptography/SecureMemory.cs @@ -212,7 +212,7 @@ protected override void Dispose(Boolean disposing) { try { - if (IsDisposed == false) + if (IsDisposed is false) { Cipher?.Dispose(); CiphertextField?.Dispose(); @@ -461,7 +461,7 @@ protected override void Dispose(Boolean disposing) { try { - if (IsDisposed == false) + if (IsDisposed is false) { ReferenceKey = default; diff --git a/src/RapidField.SolidInstruments.Cryptography/SoftwareSecurityModule.cs b/src/RapidField.SolidInstruments.Cryptography/SoftwareSecurityModule.cs index 306f749a..237a22ec 100644 --- a/src/RapidField.SolidInstruments.Cryptography/SoftwareSecurityModule.cs +++ b/src/RapidField.SolidInstruments.Cryptography/SoftwareSecurityModule.cs @@ -232,7 +232,7 @@ internal SoftwareSecurityModule(IPassword masterPassword, Boolean deleteStateFil /// [DebuggerHidden] private SoftwareSecurityModule(SecretStoreFilePersistenceVehicle persistenceVehicle) - : base(persistenceVehicle, String.IsNullOrEmpty(persistenceVehicle?.FilePath) == false && File.Exists(persistenceVehicle.FilePath)) + : base(persistenceVehicle, String.IsNullOrEmpty(persistenceVehicle?.FilePath) is false && File.Exists(persistenceVehicle.FilePath)) { return; } @@ -913,7 +913,7 @@ private void EnsureExistenceOfMasterKey() { RejectIfDisposed(); - if (InMemoryStore.Secrets.ContainsKey(InMemoryStore.MasterKeyName) == false) + if (InMemoryStore.Secrets.ContainsKey(InMemoryStore.MasterKeyName) is false) { _ = InMemoryStore.CreateMasterKey(); PersistInMemoryStore(); diff --git a/src/RapidField.SolidInstruments.DataAccess.EntityFramework/EntityFrameworkDataAccessModel.cs b/src/RapidField.SolidInstruments.DataAccess.EntityFramework/EntityFrameworkDataAccessModel.cs index dbb40554..5860ccd0 100644 --- a/src/RapidField.SolidInstruments.DataAccess.EntityFramework/EntityFrameworkDataAccessModel.cs +++ b/src/RapidField.SolidInstruments.DataAccess.EntityFramework/EntityFrameworkDataAccessModel.cs @@ -144,7 +144,7 @@ protected EntityFrameworkDataAccessModel(TIdentifier identifier) /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(EntityFrameworkDataAccessModel a, IDataAccessModel b) => a == b == false; + public static Boolean operator !=(EntityFrameworkDataAccessModel a, IDataAccessModel b) => (a == b) is false; /// /// Determines whether or not a specified instance is less than another @@ -316,7 +316,7 @@ protected EntityFrameworkDataAccessModel() /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(EntityFrameworkDataAccessModel a, IDataAccessModel b) => a == b == false; + public static Boolean operator !=(EntityFrameworkDataAccessModel a, IDataAccessModel b) => (a == b) is false; /// /// Determines whether or not two specified instances are equal. diff --git a/src/RapidField.SolidInstruments.DataAccess.EntityFramework/EntityFrameworkGlobalIdentityDataAccessModel.cs b/src/RapidField.SolidInstruments.DataAccess.EntityFramework/EntityFrameworkGlobalIdentityDataAccessModel.cs index 2538b55c..b86fc6df 100644 --- a/src/RapidField.SolidInstruments.DataAccess.EntityFramework/EntityFrameworkGlobalIdentityDataAccessModel.cs +++ b/src/RapidField.SolidInstruments.DataAccess.EntityFramework/EntityFrameworkGlobalIdentityDataAccessModel.cs @@ -53,7 +53,7 @@ protected EntityFrameworkGlobalIdentityDataAccessModel(Guid identifier) /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(EntityFrameworkGlobalIdentityDataAccessModel a, EntityFrameworkGlobalIdentityDataAccessModel b) => a == b == false; + public static Boolean operator !=(EntityFrameworkGlobalIdentityDataAccessModel a, EntityFrameworkGlobalIdentityDataAccessModel b) => (a == b) is false; /// /// Determines whether or not a specified instance @@ -217,7 +217,7 @@ protected EntityFrameworkGlobalIdentityDataAccessModel(Guid identifier) /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(EntityFrameworkGlobalIdentityDataAccessModel a, IDataAccessModel b) => a == b == false; + public static Boolean operator !=(EntityFrameworkGlobalIdentityDataAccessModel a, IDataAccessModel b) => (a == b) is false; /// /// Determines whether or not a specified instance is less than diff --git a/src/RapidField.SolidInstruments.DataAccess.EntityFramework/EntityFrameworkNumericIdentityDataAccessModel.cs b/src/RapidField.SolidInstruments.DataAccess.EntityFramework/EntityFrameworkNumericIdentityDataAccessModel.cs index 706e19c7..b75bd396 100644 --- a/src/RapidField.SolidInstruments.DataAccess.EntityFramework/EntityFrameworkNumericIdentityDataAccessModel.cs +++ b/src/RapidField.SolidInstruments.DataAccess.EntityFramework/EntityFrameworkNumericIdentityDataAccessModel.cs @@ -54,7 +54,7 @@ protected EntityFrameworkNumericIdentityDataAccessModel(Int64 identifier) /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(EntityFrameworkNumericIdentityDataAccessModel a, EntityFrameworkNumericIdentityDataAccessModel b) => a == b == false; + public static Boolean operator !=(EntityFrameworkNumericIdentityDataAccessModel a, EntityFrameworkNumericIdentityDataAccessModel b) => (a == b) is false; /// /// Determines whether or not a specified @@ -219,7 +219,7 @@ protected EntityFrameworkNumericIdentityDataAccessModel(Int64 identifier) /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(EntityFrameworkNumericIdentityDataAccessModel a, IDataAccessModel b) => a == b == false; + public static Boolean operator !=(EntityFrameworkNumericIdentityDataAccessModel a, IDataAccessModel b) => (a == b) is false; /// /// Determines whether or not a specified instance is less than diff --git a/src/RapidField.SolidInstruments.DataAccess.EntityFramework/EntityFrameworkSemanticIdentityDataAccessModel.cs b/src/RapidField.SolidInstruments.DataAccess.EntityFramework/EntityFrameworkSemanticIdentityDataAccessModel.cs index 3ce13d45..be18c2d7 100644 --- a/src/RapidField.SolidInstruments.DataAccess.EntityFramework/EntityFrameworkSemanticIdentityDataAccessModel.cs +++ b/src/RapidField.SolidInstruments.DataAccess.EntityFramework/EntityFrameworkSemanticIdentityDataAccessModel.cs @@ -54,7 +54,7 @@ protected EntityFrameworkSemanticIdentityDataAccessModel(String identifier) /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(EntityFrameworkSemanticIdentityDataAccessModel a, EntityFrameworkSemanticIdentityDataAccessModel b) => a == b == false; + public static Boolean operator !=(EntityFrameworkSemanticIdentityDataAccessModel a, EntityFrameworkSemanticIdentityDataAccessModel b) => (a == b) is false; /// /// Determines whether or not a specified @@ -219,7 +219,7 @@ protected EntityFrameworkSemanticIdentityDataAccessModel(String identifier) /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(EntityFrameworkSemanticIdentityDataAccessModel a, IDataAccessModel b) => a == b == false; + public static Boolean operator !=(EntityFrameworkSemanticIdentityDataAccessModel a, IDataAccessModel b) => (a == b) is false; /// /// Determines whether or not a specified instance is less diff --git a/src/RapidField.SolidInstruments.EventAuthoring/Event.cs b/src/RapidField.SolidInstruments.EventAuthoring/Event.cs index fcf5c7b3..77b49fd7 100644 --- a/src/RapidField.SolidInstruments.EventAuthoring/Event.cs +++ b/src/RapidField.SolidInstruments.EventAuthoring/Event.cs @@ -242,7 +242,7 @@ public Event(EventCategory category, EventVerbosity verbosity, String descriptio /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(Event a, IEvent b) => a == b == false; + public static Boolean operator !=(Event a, IEvent b) => (a == b) is false; /// /// Determines whether or not a specified instance is less than another specified instance. diff --git a/src/RapidField.SolidInstruments.InversionOfControl.Autofac/AutofacDependencyContainer.cs b/src/RapidField.SolidInstruments.InversionOfControl.Autofac/AutofacDependencyContainer.cs index a2447621..531f8077 100644 --- a/src/RapidField.SolidInstruments.InversionOfControl.Autofac/AutofacDependencyContainer.cs +++ b/src/RapidField.SolidInstruments.InversionOfControl.Autofac/AutofacDependencyContainer.cs @@ -88,6 +88,17 @@ internal AutofacDependencyContainer(IConfiguration applicationConfiguration, ISe /// protected override void Dispose(Boolean disposing) => base.Dispose(disposing); + /// + /// Conditionally registers important dependency types if they are missing following user-defined registrations. + /// + /// + /// The object that configures the container. + /// + protected override void RegisterFallbackTypes(ContainerBuilder configurator) + { + return; + } + /// /// Registers a command mediator with the configurator. /// diff --git a/src/RapidField.SolidInstruments.InversionOfControl.DotNetNative/DotNetNativeDependencyContainer.cs b/src/RapidField.SolidInstruments.InversionOfControl.DotNetNative/DotNetNativeDependencyContainer.cs index 361c5c79..1fbce15f 100644 --- a/src/RapidField.SolidInstruments.InversionOfControl.DotNetNative/DotNetNativeDependencyContainer.cs +++ b/src/RapidField.SolidInstruments.InversionOfControl.DotNetNative/DotNetNativeDependencyContainer.cs @@ -89,6 +89,17 @@ internal DotNetNativeDependencyContainer(IConfiguration applicationConfiguration /// protected override void Dispose(Boolean disposing) => base.Dispose(disposing); + /// + /// Conditionally registers important dependency types if they are missing following user-defined registrations. + /// + /// + /// The object that configures the container. + /// + protected override void RegisterFallbackTypes(ServiceCollection configurator) + { + return; + } + /// /// Registers a command mediator with the configurator. /// diff --git a/src/RapidField.SolidInstruments.InversionOfControl/DependencyContainer.cs b/src/RapidField.SolidInstruments.InversionOfControl/DependencyContainer.cs index dcde5c20..210e5a0f 100644 --- a/src/RapidField.SolidInstruments.InversionOfControl/DependencyContainer.cs +++ b/src/RapidField.SolidInstruments.InversionOfControl/DependencyContainer.cs @@ -160,6 +160,7 @@ protected sealed override void Configure(DependencyContainerConfiguration + /// Conditionally registers important dependency types if they are missing following user-defined registrations. + /// + /// + /// The object that configures the container. + /// + protected abstract void RegisterFallbackTypes(TConfigurator configurator); + /// /// Registers a command mediator with the configurator. /// diff --git a/src/RapidField.SolidInstruments.Mathematics/Physics/Area.cs b/src/RapidField.SolidInstruments.Mathematics/Physics/Area.cs index 433d38e4..63c73e98 100644 --- a/src/RapidField.SolidInstruments.Mathematics/Physics/Area.cs +++ b/src/RapidField.SolidInstruments.Mathematics/Physics/Area.cs @@ -177,7 +177,7 @@ public Area(Decimal squareMeters) /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(Area a, Area b) => a == b == false; + public static Boolean operator !=(Area a, Area b) => (a == b) is false; /// /// Determines the product of an value and a multiplier. @@ -509,7 +509,7 @@ private static Boolean Parse(String input, out Area result, Boolean raiseExcepti foreach (var character in processedString) { - if (numericSubstringIsComplete == false) + if (numericSubstringIsComplete is false) { if (character.IsNumeric() || character == '.') { diff --git a/src/RapidField.SolidInstruments.Mathematics/Physics/GeographicCoordinates.cs b/src/RapidField.SolidInstruments.Mathematics/Physics/GeographicCoordinates.cs index 1fecfddc..8f20153d 100644 --- a/src/RapidField.SolidInstruments.Mathematics/Physics/GeographicCoordinates.cs +++ b/src/RapidField.SolidInstruments.Mathematics/Physics/GeographicCoordinates.cs @@ -49,7 +49,7 @@ public GeographicCoordinates(Double latitude, Double longitude) /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(GeographicCoordinates a, GeographicCoordinates b) => a == b == false; + public static Boolean operator !=(GeographicCoordinates a, GeographicCoordinates b) => (a == b) is false; /// /// Determine whether or not two specified instances are equal. diff --git a/src/RapidField.SolidInstruments.Mathematics/Physics/Length.cs b/src/RapidField.SolidInstruments.Mathematics/Physics/Length.cs index 24cc7ccc..ebfc9069 100644 --- a/src/RapidField.SolidInstruments.Mathematics/Physics/Length.cs +++ b/src/RapidField.SolidInstruments.Mathematics/Physics/Length.cs @@ -177,7 +177,7 @@ public Length(Decimal meters) /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(Length a, Length b) => a == b == false; + public static Boolean operator !=(Length a, Length b) => (a == b) is false; /// /// Determines the product of a value and a multiplier. @@ -510,7 +510,7 @@ private static Boolean Parse(String input, out Length result, Boolean raiseExcep foreach (var character in processedString) { - if (numericSubstringIsComplete == false) + if (numericSubstringIsComplete is false) { if (character.IsNumeric() || character == '.') { diff --git a/src/RapidField.SolidInstruments.Mathematics/Physics/Mass.cs b/src/RapidField.SolidInstruments.Mathematics/Physics/Mass.cs index 02fb5b0a..3a5097cc 100644 --- a/src/RapidField.SolidInstruments.Mathematics/Physics/Mass.cs +++ b/src/RapidField.SolidInstruments.Mathematics/Physics/Mass.cs @@ -137,7 +137,7 @@ public Mass(Decimal grams) /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(Mass a, Mass b) => a == b == false; + public static Boolean operator !=(Mass a, Mass b) => (a == b) is false; /// /// Determines the product of a value and a multiplier. @@ -469,7 +469,7 @@ private static Boolean Parse(String input, out Mass result, Boolean raiseExcepti foreach (var character in processedString) { - if (numericSubstringIsComplete == false) + if (numericSubstringIsComplete is false) { if (character.IsNumeric() || character == '.') { diff --git a/src/RapidField.SolidInstruments.Mathematics/Physics/Temperature.cs b/src/RapidField.SolidInstruments.Mathematics/Physics/Temperature.cs index 6456083c..2193f6a0 100644 --- a/src/RapidField.SolidInstruments.Mathematics/Physics/Temperature.cs +++ b/src/RapidField.SolidInstruments.Mathematics/Physics/Temperature.cs @@ -107,7 +107,7 @@ public Temperature(Decimal degreesCelsius) /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(Temperature a, Temperature b) => a == b == false; + public static Boolean operator !=(Temperature a, Temperature b) => (a == b) is false; /// /// Determines the product of a value and a multiplier. @@ -444,7 +444,7 @@ private static Boolean Parse(String input, out Temperature result, Boolean raise foreach (var character in processedString) { - if (numericSubstringIsComplete == false) + if (numericSubstringIsComplete is false) { if (character.IsNumeric() || character == '.') { diff --git a/src/RapidField.SolidInstruments.Mathematics/Physics/Volume.cs b/src/RapidField.SolidInstruments.Mathematics/Physics/Volume.cs index 71ee17fb..df57f31a 100644 --- a/src/RapidField.SolidInstruments.Mathematics/Physics/Volume.cs +++ b/src/RapidField.SolidInstruments.Mathematics/Physics/Volume.cs @@ -187,7 +187,7 @@ public Volume(Decimal cubicMeters) /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(Volume a, Volume b) => a == b == false; + public static Boolean operator !=(Volume a, Volume b) => (a == b) is false; /// /// Determines the product of an value and a multiplier. @@ -520,7 +520,7 @@ private static Boolean Parse(String input, out Volume result, Boolean raiseExcep foreach (var character in processedString) { - if (numericSubstringIsComplete == false) + if (numericSubstringIsComplete is false) { if (character.IsNumeric() || character == '.') { diff --git a/src/RapidField.SolidInstruments.Mathematics/Sequences/PrimeNumberSequence.cs b/src/RapidField.SolidInstruments.Mathematics/Sequences/PrimeNumberSequence.cs index 246c8c7d..dc522f2d 100644 --- a/src/RapidField.SolidInstruments.Mathematics/Sequences/PrimeNumberSequence.cs +++ b/src/RapidField.SolidInstruments.Mathematics/Sequences/PrimeNumberSequence.cs @@ -41,7 +41,7 @@ protected override BigInteger CalculateNext(IEnumerable calculatedTe { var lastTerm = calculatedTerms.Last(); - while (IsPrimeNumber(lastTerm += 2) == false) + while (IsPrimeNumber(lastTerm += 2) is false) { continue; } diff --git a/src/RapidField.SolidInstruments.Messaging.Autofac/AutofacMessageHandlerModule.cs b/src/RapidField.SolidInstruments.Messaging.Autofac/AutofacMessageHandlerModule.cs index 506fbe28..12974e86 100644 --- a/src/RapidField.SolidInstruments.Messaging.Autofac/AutofacMessageHandlerModule.cs +++ b/src/RapidField.SolidInstruments.Messaging.Autofac/AutofacMessageHandlerModule.cs @@ -514,7 +514,7 @@ private void RegisterMessageTransmitterTypes(ContainerBuilder configurator) /// /// Gets the collection of non-abstract public message handler types defined by . /// - public IEnumerable MessageHandlerTypes => TargetAssembly.GetTypes().Where(type => type.IsPublic && type.IsClass && type.IsAbstract == false && MessageHandlerInterfaceType.IsAssignableFrom(type)); + public IEnumerable MessageHandlerTypes => TargetAssembly.GetTypes().Where(type => type.IsPublic && type.IsClass && type.IsAbstract is false && MessageHandlerInterfaceType.IsAssignableFrom(type)); /// /// Gets the collection of non-abstract public message listener types defined by . diff --git a/src/RapidField.SolidInstruments.Messaging.DotNetNative/DotNetNativeMessageHandlerModule.cs b/src/RapidField.SolidInstruments.Messaging.DotNetNative/DotNetNativeMessageHandlerModule.cs index 527342b9..7b3465c4 100644 --- a/src/RapidField.SolidInstruments.Messaging.DotNetNative/DotNetNativeMessageHandlerModule.cs +++ b/src/RapidField.SolidInstruments.Messaging.DotNetNative/DotNetNativeMessageHandlerModule.cs @@ -514,7 +514,7 @@ private void RegisterMessageTransmitterTypes(ServiceCollection configurator) /// /// Gets the collection of non-abstract public message handler types defined by . /// - public IEnumerable MessageHandlerTypes => TargetAssembly.GetTypes().Where(type => type.IsPublic && type.IsClass && type.IsAbstract == false && MessageHandlerInterfaceType.IsAssignableFrom(type)); + public IEnumerable MessageHandlerTypes => TargetAssembly.GetTypes().Where(type => type.IsPublic && type.IsClass && type.IsAbstract is false && MessageHandlerInterfaceType.IsAssignableFrom(type)); /// /// Gets the collection of non-abstract public message listener types defined by . diff --git a/src/RapidField.SolidInstruments.Messaging/Message.cs b/src/RapidField.SolidInstruments.Messaging/Message.cs index 85d110f7..049d3140 100644 --- a/src/RapidField.SolidInstruments.Messaging/Message.cs +++ b/src/RapidField.SolidInstruments.Messaging/Message.cs @@ -151,7 +151,7 @@ public Guid CorrelationIdentifier { get { - if (CorrelationIdentifierField.HasValue == false) + if (CorrelationIdentifierField.HasValue is false) { CorrelationIdentifierField = Guid.NewGuid(); } @@ -169,7 +169,7 @@ public Guid Identifier { get { - if (IdentifierField.HasValue == false) + if (IdentifierField.HasValue is false) { IdentifierField = Guid.NewGuid(); } diff --git a/src/RapidField.SolidInstruments.Messaging/MessageListeningFacade.cs b/src/RapidField.SolidInstruments.Messaging/MessageListeningFacade.cs index 2c22b28f..9bfb44ce 100644 --- a/src/RapidField.SolidInstruments.Messaging/MessageListeningFacade.cs +++ b/src/RapidField.SolidInstruments.Messaging/MessageListeningFacade.cs @@ -88,7 +88,7 @@ public sealed override void RegisterRequestMessageHandler(controlToken) == false) + if (TryAddListenedMessageType(controlToken) is false) { // Disallow registration of duplicate request handlers. return; @@ -453,7 +453,7 @@ internal void RegisterMessageHandler(Action messageHandler, { RejectIfDisposed(); - if (TryAddListenedMessageType(controlToken) == false) + if (TryAddListenedMessageType(controlToken) is false) { if (ResponseMessageInterfaceType.IsAssignableFrom(typeof(TMessage))) { diff --git a/src/RapidField.SolidInstruments.Messaging/MessageRequestingFacade.cs b/src/RapidField.SolidInstruments.Messaging/MessageRequestingFacade.cs index fbb38af7..791738c8 100644 --- a/src/RapidField.SolidInstruments.Messaging/MessageRequestingFacade.cs +++ b/src/RapidField.SolidInstruments.Messaging/MessageRequestingFacade.cs @@ -180,7 +180,7 @@ public Task RequestAsync(TR using (var controlToken = StateControl.Enter()) { - if (TryAddOutstandingRequest(requestMessage, requestMessageIdentifier) == false) + if (TryAddOutstandingRequest(requestMessage, requestMessageIdentifier) is false) { throw new InvalidOperationException("The request was not processed because it is a duplicate."); } diff --git a/src/RapidField.SolidInstruments.Messaging/MessagingEntityPath.cs b/src/RapidField.SolidInstruments.Messaging/MessagingEntityPath.cs index ae7edcce..f402666f 100644 --- a/src/RapidField.SolidInstruments.Messaging/MessagingEntityPath.cs +++ b/src/RapidField.SolidInstruments.Messaging/MessagingEntityPath.cs @@ -112,22 +112,22 @@ private MessagingEntityPath(String messageType, String prefix, String labelOne, { MessageType = messageType; - if (prefix.IsNullOrEmpty() == false) + if (prefix.IsNullOrEmpty() is false) { Prefix = prefix; } - if (labelOne.IsNullOrEmpty() == false) + if (labelOne.IsNullOrEmpty() is false) { LabelOne = labelOne; } - if (labelTwo.IsNullOrEmpty() == false) + if (labelTwo.IsNullOrEmpty() is false) { LabelTwo = labelTwo; } - if (labelThree.IsNullOrEmpty() == false) + if (labelThree.IsNullOrEmpty() is false) { LabelThree = labelThree; } @@ -145,7 +145,7 @@ private MessagingEntityPath(String messageType, String prefix, String labelOne, /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(MessagingEntityPath a, IMessagingEntityPath b) => a == b == false; + public static Boolean operator !=(MessagingEntityPath a, IMessagingEntityPath b) => (a == b) is false; /// /// Determines whether or not a specified instance is less than another specified @@ -352,22 +352,22 @@ public override Int32 GetHashCode() { var hashCode = 433494437 ^ MessageType.GetHashCode(); - if (Prefix.IsNullOrEmpty() == false) + if (Prefix.IsNullOrEmpty() is false) { hashCode ^= Prefix.GetHashCode(); } - if (LabelOne.IsNullOrEmpty() == false) + if (LabelOne.IsNullOrEmpty() is false) { hashCode ^= LabelOne.GetHashCode(); } - if (LabelTwo.IsNullOrEmpty() == false) + if (LabelTwo.IsNullOrEmpty() is false) { hashCode ^= LabelTwo.GetHashCode(); } - if (LabelThree.IsNullOrEmpty() == false) + if (LabelThree.IsNullOrEmpty() is false) { hashCode ^= LabelThree.GetHashCode(); } @@ -385,27 +385,27 @@ public override String ToString() { var stringBuilder = new StringBuilder(); - if (Prefix.IsNullOrEmpty() == false) + if (Prefix.IsNullOrEmpty() is false) { _ = stringBuilder.Append($"{Prefix}{DelimitingCharacterForPrefix}"); } - if (MessageType.IsNullOrEmpty() == false) + if (MessageType.IsNullOrEmpty() is false) { _ = stringBuilder.Append(MessageType); } - if (LabelOne.IsNullOrEmpty() == false) + if (LabelOne.IsNullOrEmpty() is false) { _ = stringBuilder.Append($"{DelimitingCharacterForLabelToken}{LabelOne}"); } - if (LabelTwo.IsNullOrEmpty() == false) + if (LabelTwo.IsNullOrEmpty() is false) { _ = stringBuilder.Append($"{DelimitingCharacterForLabelToken}{LabelTwo}"); } - if (LabelThree.IsNullOrEmpty() == false) + if (LabelThree.IsNullOrEmpty() is false) { _ = stringBuilder.Append($"{DelimitingCharacterForLabelToken}{LabelThree}"); } @@ -461,7 +461,7 @@ private static String ExtractMessageTypeName(Type messageType) { try { - if (messageType.RejectIf().IsNull(nameof(messageType)).TargetArgument.GetCustomAttributes(typeof(DataContractAttribute), false).FirstOrDefault() is DataContractAttribute dataContractAttribute && dataContractAttribute.Name.IsNullOrEmpty() == false) + if (messageType.RejectIf().IsNull(nameof(messageType)).TargetArgument.GetCustomAttributes(typeof(DataContractAttribute), false).FirstOrDefault() is DataContractAttribute dataContractAttribute && dataContractAttribute.Name.IsNullOrEmpty() is false) { return dataContractAttribute.Name.Compress(); } diff --git a/src/RapidField.SolidInstruments.Messaging/Service/HeartbeatScheduleItem.cs b/src/RapidField.SolidInstruments.Messaging/Service/HeartbeatScheduleItem.cs index d1d82f17..b71f8460 100644 --- a/src/RapidField.SolidInstruments.Messaging/Service/HeartbeatScheduleItem.cs +++ b/src/RapidField.SolidInstruments.Messaging/Service/HeartbeatScheduleItem.cs @@ -97,7 +97,7 @@ internal HeartbeatScheduleItem(Int32 intervalInSeconds, MessagingEntityType enti /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(HeartbeatScheduleItem a, IHeartbeatScheduleItem b) => a == b == false; + public static Boolean operator !=(HeartbeatScheduleItem a, IHeartbeatScheduleItem b) => (a == b) is false; /// /// Determines whether or not a specified instance is less than another specified diff --git a/src/RapidField.SolidInstruments.Messaging/TransportPrimitives/MessageLockToken.cs b/src/RapidField.SolidInstruments.Messaging/TransportPrimitives/MessageLockToken.cs index cc31d135..74fd3995 100644 --- a/src/RapidField.SolidInstruments.Messaging/TransportPrimitives/MessageLockToken.cs +++ b/src/RapidField.SolidInstruments.Messaging/TransportPrimitives/MessageLockToken.cs @@ -98,7 +98,7 @@ internal MessageLockToken(UInt64 deliveryTag, Guid identifier, Guid messageIdent /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(MessageLockToken a, MessageLockToken b) => a == b == false; + public static Boolean operator !=(MessageLockToken a, MessageLockToken b) => (a == b) is false; /// /// Determines whether or not a specified instance is less than another specified instance. diff --git a/src/RapidField.SolidInstruments.Messaging/TransportPrimitives/MessageTopic.cs b/src/RapidField.SolidInstruments.Messaging/TransportPrimitives/MessageTopic.cs index b7e72bdd..66c0b784 100644 --- a/src/RapidField.SolidInstruments.Messaging/TransportPrimitives/MessageTopic.cs +++ b/src/RapidField.SolidInstruments.Messaging/TransportPrimitives/MessageTopic.cs @@ -319,7 +319,7 @@ public Boolean TryCreateSubscription(String subscriptionName) { return false; } - else if (SubscriptionQueues.ContainsKey(subscriptionName) == false) + else if (SubscriptionQueues.ContainsKey(subscriptionName) is false) { var subscriptionQueue = new MessageQueue(Guid.NewGuid(), Path, OperationalState, MessageBodySerializationFormat, MessageLockExpirationThreshold, EnqueueTimeoutThreshold); @@ -452,7 +452,7 @@ protected internal sealed override Boolean TryEnqueue(PrimitiveMessage message) foreach (var queue in SubscriptionQueues.Values) { - if (queue.TryEnqueue(message) == false) + if (queue.TryEnqueue(message) is false) { return false; } diff --git a/src/RapidField.SolidInstruments.Messaging/TransportPrimitives/MessageTransport.cs b/src/RapidField.SolidInstruments.Messaging/TransportPrimitives/MessageTransport.cs index 5d19db8a..eaf55a23 100644 --- a/src/RapidField.SolidInstruments.Messaging/TransportPrimitives/MessageTransport.cs +++ b/src/RapidField.SolidInstruments.Messaging/TransportPrimitives/MessageTransport.cs @@ -868,9 +868,9 @@ public Boolean TryCreateSubscription(IMessagingEntityPath path, String subscript { return false; } - else if (TopicExists(path) == false) + else if (TopicExists(path) is false) { - if (TryCreateTopic(path) == false) + if (TryCreateTopic(path) is false) { return false; } diff --git a/src/RapidField.SolidInstruments.Messaging/TransportPrimitives/PrimitiveMessage.cs b/src/RapidField.SolidInstruments.Messaging/TransportPrimitives/PrimitiveMessage.cs index a0fd96b1..2682c777 100644 --- a/src/RapidField.SolidInstruments.Messaging/TransportPrimitives/PrimitiveMessage.cs +++ b/src/RapidField.SolidInstruments.Messaging/TransportPrimitives/PrimitiveMessage.cs @@ -236,7 +236,7 @@ private Type BodyType try { - return AppDomain.CurrentDomain.GetAssemblies().Select(assembly => assembly.GetType(BodyTypeName)).First(type => type != null); + return AppDomain.CurrentDomain.GetAssemblies().Select(assembly => assembly.GetType(BodyTypeName)).First(type => type is not null); } catch (Exception exception) { diff --git a/src/RapidField.SolidInstruments.ObjectComposition/ObjectContainer.cs b/src/RapidField.SolidInstruments.ObjectComposition/ObjectContainer.cs index 85cc9b75..b5841b12 100644 --- a/src/RapidField.SolidInstruments.ObjectComposition/ObjectContainer.cs +++ b/src/RapidField.SolidInstruments.ObjectComposition/ObjectContainer.cs @@ -142,7 +142,7 @@ public T Get() try { - if (Registrations.ContainsKey(requestType) == false) + if (Registrations.ContainsKey(requestType) is false) { throw new ArgumentException($"{requestType.FullName} is not a registered request type.", nameof(T)); } @@ -154,7 +154,7 @@ public T Get() var productType = Registrations[requestType].ProductType; - if (Factory.SupportedProductTypes.Contains(productType) == false) + if (Factory.SupportedProductTypes.Contains(productType) is false) { throw new ArgumentException($"{productType.FullName} is not a registered product type.", nameof(T)); } @@ -211,7 +211,7 @@ public T GetNew() try { - if (Registrations.ContainsKey(requestType) == false) + if (Registrations.ContainsKey(requestType) is false) { throw new ArgumentException($"{requestType.FullName} is not a registered request type.", nameof(T)); } diff --git a/src/RapidField.SolidInstruments.ObjectComposition/ObjectContainerDefinition.cs b/src/RapidField.SolidInstruments.ObjectComposition/ObjectContainerDefinition.cs index efc29fa7..9c2e34e5 100644 --- a/src/RapidField.SolidInstruments.ObjectComposition/ObjectContainerDefinition.cs +++ b/src/RapidField.SolidInstruments.ObjectComposition/ObjectContainerDefinition.cs @@ -53,7 +53,7 @@ internal ObjectContainerDefinition(Type requestType, Type productType) /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(ObjectContainerDefinition a, IObjectContainerDefinition b) => a == b == false; + public static Boolean operator !=(ObjectContainerDefinition a, IObjectContainerDefinition b) => (a == b) is false; /// /// Determines whether or not a specified instance is less than another specified diff --git a/src/RapidField.SolidInstruments.Service/ServiceExecutionLifetime.cs b/src/RapidField.SolidInstruments.Service/ServiceExecutionLifetime.cs index fb8d1e24..e8889424 100644 --- a/src/RapidField.SolidInstruments.Service/ServiceExecutionLifetime.cs +++ b/src/RapidField.SolidInstruments.Service/ServiceExecutionLifetime.cs @@ -62,7 +62,7 @@ public void KeepAlive() { RejectIfDisposed(); - if (IsAlive == false) + if (IsAlive is false) { throw new InvalidOperationException("The service execution lifetime has ended."); } diff --git a/src/RapidField.SolidInstruments.Service/ServiceExecutor.cs b/src/RapidField.SolidInstruments.Service/ServiceExecutor.cs index 4acc4fcb..7f4000cd 100644 --- a/src/RapidField.SolidInstruments.Service/ServiceExecutor.cs +++ b/src/RapidField.SolidInstruments.Service/ServiceExecutor.cs @@ -88,17 +88,17 @@ public void Execute(String[] commandLineArguments) var serviceName = ServiceName?.Trim(); var copyrightNotice = CopyrightNotice?.Trim(); - if (productName.IsNullOrEmpty() == false) + if (productName.IsNullOrEmpty() is false) { Console.WriteLine(productName); } - if (serviceName.IsNullOrEmpty() == false) + if (serviceName.IsNullOrEmpty() is false) { Console.WriteLine(serviceName); } - if (copyrightNotice.IsNullOrEmpty() == false) + if (copyrightNotice.IsNullOrEmpty() is false) { Console.WriteLine(copyrightNotice); } @@ -169,7 +169,7 @@ protected virtual void BuildConfiguration(IConfigurationBuilder configurationBui _ = configurationBuilder.AddEnvironmentVariables(prefix); } - if (CommandLineArguments.IsNullOrEmpty() == false) + if (CommandLineArguments.IsNullOrEmpty() is false) { _ = configurationBuilder.AddCommandLine(CommandLineArguments); } diff --git a/src/RapidField.SolidInstruments.TextEncoding/EnhancedReadabilityGuid.cs b/src/RapidField.SolidInstruments.TextEncoding/EnhancedReadabilityGuid.cs index e5bd590a..9a54d61e 100644 --- a/src/RapidField.SolidInstruments.TextEncoding/EnhancedReadabilityGuid.cs +++ b/src/RapidField.SolidInstruments.TextEncoding/EnhancedReadabilityGuid.cs @@ -69,7 +69,7 @@ public EnhancedReadabilityGuid(Guid value) /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(EnhancedReadabilityGuid a, EnhancedReadabilityGuid b) => a == b == false; + public static Boolean operator !=(EnhancedReadabilityGuid a, EnhancedReadabilityGuid b) => (a == b) is false; /// /// Determines whether or not a specified instance is less than another specified diff --git a/src/RapidField.SolidInstruments.Web/WebExecutor.cs b/src/RapidField.SolidInstruments.Web/WebExecutor.cs index 42e20d84..72fb8576 100644 --- a/src/RapidField.SolidInstruments.Web/WebExecutor.cs +++ b/src/RapidField.SolidInstruments.Web/WebExecutor.cs @@ -200,17 +200,17 @@ public void Execute(String[] commandLineArguments) var applicationName = ApplicationName?.Trim(); var copyrightNotice = CopyrightNotice?.Trim(); - if (productName.IsNullOrEmpty() == false) + if (productName.IsNullOrEmpty() is false) { Console.WriteLine(productName); } - if (applicationName.IsNullOrEmpty() == false) + if (applicationName.IsNullOrEmpty() is false) { Console.WriteLine(applicationName); } - if (copyrightNotice.IsNullOrEmpty() == false) + if (copyrightNotice.IsNullOrEmpty() is false) { Console.WriteLine(copyrightNotice); } @@ -373,7 +373,7 @@ protected virtual void BuildConfiguration(IConfigurationBuilder configurationBui configurationBuilder = configurationBuilder.AddEnvironmentVariables(prefix); } - if (CommandLineArguments.IsNullOrEmpty() == false) + if (CommandLineArguments.IsNullOrEmpty() is false) { configurationBuilder = configurationBuilder.AddCommandLine(CommandLineArguments); } diff --git a/test/RapidField.SolidInstruments.Core.UnitTests/Caching/DistributedCacheClientTests.cs b/test/RapidField.SolidInstruments.Core.UnitTests/Caching/DistributedCacheClientTests.cs new file mode 100644 index 00000000..dad59407 --- /dev/null +++ b/test/RapidField.SolidInstruments.Core.UnitTests/Caching/DistributedCacheClientTests.cs @@ -0,0 +1,141 @@ +// ================================================================================================================================= +// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ================================================================================================================================= + +using FluentAssertions; +using Microsoft.Extensions.Caching.Distributed; +using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.Options; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using RapidField.SolidInstruments.Core.Caching; +using RapidField.SolidInstruments.Core.Extensions; +using System; +using System.Security.Cryptography; + +namespace RapidField.SolidInstruments.Core.UnitTests.Caching +{ + [TestClass] + public class DistributedCacheClientTests + { + [TestMethod] + public void FunctionalLifeSpanTest_ShouldProduceDesiredResults_ForNonOperativeCache() => FunctionalLifeSpanTest_ShouldProduceDesiredResults(null); + + [TestMethod] + public void FunctionalLifeSpanTest_ShouldProduceDesiredResults_ForOperativeCache() => FunctionalLifeSpanTest_ShouldProduceDesiredResults(new MemoryDistributedCache(Options.Create(new MemoryDistributedCacheOptions()))); + + [TestMethod] + public void Process_ShouldProduceDesiredResults_ForNonOperativeCache() => Process_ShouldProduceDesiredResults(null); + + [TestMethod] + public void Process_ShouldProduceDesiredResults_ForOperativeCache() => Process_ShouldProduceDesiredResults(new MemoryDistributedCache(Options.Create(new MemoryDistributedCacheOptions()))); + + private static void FunctionalLifeSpanTest_ShouldProduceDesiredResults(IDistributedCache cache) + { + // Arrange. + var cacheShouldBeOperative = cache is not null; + var keyOne = "foo"; + var keyTwo = "bar"; + using var randomnessProvider = RandomNumberGenerator.Create(); + var valueOne = SimulatedModel.Random(randomnessProvider); + var valueTwo = SimulatedModel.Random(randomnessProvider); + using var target = new DistributedCacheClient(cache); + + // Act. + target.Write(keyOne, valueOne); + var resultOne = target.TryRead(keyOne, out var resultValueOne); + var resultTwo = target.TryRead(keyOne, out var resultValueTwo); + var resultThree = target.TryRead(keyTwo, out var resultValueThree); + target.Write(keyTwo, valueTwo); + var resultFour = target.TryRead(keyOne, out var resultValueFour); + var resultFive = target.TryRead(keyTwo, out var resultValueFive); + var resultSix = target.TryRead(keyTwo, out var resultValueSix); + target.Invalidate(keyOne); + var resultSeven = target.TryRead(keyOne, out var resultValueSeven); + var resultEight = target.TryRead(keyTwo, out var resultValueEight); + target.Refresh(keyTwo); + var resultNine = target.TryRead(keyTwo, out var resultValueNine); + + if (cacheShouldBeOperative) + { + // Assert. + resultOne.Should().BeTrue(); + resultTwo.Should().BeFalse(); + resultThree.Should().BeFalse(); + resultFour.Should().BeTrue(); + resultFive.Should().BeFalse(); + resultSix.Should().BeTrue(); + resultSeven.Should().BeFalse(); + resultEight.Should().BeTrue(); + resultNine.Should().BeTrue(); + resultValueOne.Should().Be(valueOne); + resultValueTwo.Should().BeNull(); + resultValueThree.Should().BeNull(); + resultValueFour.Should().Be(valueOne); + resultValueFive.Should().BeNull(); + resultValueSix.Should().Be(valueTwo); + resultValueSeven.Should().BeNull(); + resultValueEight.Should().Be(valueTwo); + resultValueNine.Should().Be(valueTwo); + } + else + { + // Assert. + resultOne.Should().BeFalse(); + resultTwo.Should().BeFalse(); + resultThree.Should().BeFalse(); + resultFour.Should().BeFalse(); + resultFive.Should().BeFalse(); + resultSix.Should().BeFalse(); + resultSeven.Should().BeFalse(); + resultEight.Should().BeFalse(); + resultNine.Should().BeFalse(); + resultValueOne.Should().BeNull(); + resultValueTwo.Should().BeNull(); + resultValueThree.Should().BeNull(); + resultValueFour.Should().BeNull(); + resultValueFive.Should().BeNull(); + resultValueSix.Should().BeNull(); + resultValueSeven.Should().BeNull(); + resultValueEight.Should().BeNull(); + resultValueNine.Should().BeNull(); + } + } + + private static void Process_ShouldProduceDesiredResults(IDistributedCache cache) + { + // Arrange. + var cacheShouldBeOperative = cache is not null; + var keyOne = "foo"; + var keyTwo = "bar"; + using var randomnessProvider = RandomNumberGenerator.Create(); + var produceValueFunction = new Func(() => SimulatedModel.Random(randomnessProvider)); + using var target = new DistributedCacheClient(cache); + + // Act. + var targetIsOperative = target.IsOperative; + var resultOne = target.Process(keyOne, produceValueFunction); + var resultTwo = target.Process(keyTwo, produceValueFunction); + var resultThree = target.Process(keyOne, produceValueFunction); + var resultFour = target.Process(keyTwo, produceValueFunction); + var resultOneHashCode = resultOne.GetImpliedHashCode(); + var resultTwoHashCode = resultTwo.GetImpliedHashCode(); + var resultThreeHashCode = resultThree.GetImpliedHashCode(); + var resultFourHashCode = resultFour.GetImpliedHashCode(); + var resultsOneAndTwoAreEqual = resultOneHashCode == resultTwoHashCode; + var resultsOneAndThreeAreEqual = resultOneHashCode == resultThreeHashCode; + var resultsOneAndFourAreEqual = resultOneHashCode == resultFourHashCode; + var resultsTwoAndThreeAreEqual = resultTwoHashCode == resultThreeHashCode; + var resultsTwoAndFourAreEqual = resultTwoHashCode == resultFourHashCode; + var resultsThreeAndFourAreEqual = resultThreeHashCode == resultFourHashCode; + + // Assert. + targetIsOperative.Should().Be(cacheShouldBeOperative); + resultsOneAndTwoAreEqual.Should().BeFalse(); + resultsOneAndThreeAreEqual.Should().Be(cacheShouldBeOperative); + resultsOneAndFourAreEqual.Should().BeFalse(); + resultsTwoAndThreeAreEqual.Should().BeFalse(); + resultsTwoAndFourAreEqual.Should().Be(cacheShouldBeOperative); + resultsThreeAndFourAreEqual.Should().BeFalse(); + } + } +} \ No newline at end of file diff --git a/test/RapidField.SolidInstruments.Core.UnitTests/Caching/DualLayerCacheClientTests.cs b/test/RapidField.SolidInstruments.Core.UnitTests/Caching/DualLayerCacheClientTests.cs new file mode 100644 index 00000000..53cc71d3 --- /dev/null +++ b/test/RapidField.SolidInstruments.Core.UnitTests/Caching/DualLayerCacheClientTests.cs @@ -0,0 +1,102 @@ +// ================================================================================================================================= +// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ================================================================================================================================= + +using FluentAssertions; +using Microsoft.Extensions.Caching.Distributed; +using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.Options; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using RapidField.SolidInstruments.Core.Caching; +using RapidField.SolidInstruments.Core.Extensions; +using System; +using System.Security.Cryptography; + +namespace RapidField.SolidInstruments.Core.UnitTests.Caching +{ + [TestClass] + public class DualLayerCacheClientTests + { + [TestMethod] + public void FunctionalLifeSpanTest_ShouldProduceDesiredResults() + { + // Arrange. + var keyOne = "foo"; + var keyTwo = "bar"; + using var randomnessProvider = RandomNumberGenerator.Create(); + var valueOne = SimulatedModel.Random(randomnessProvider); + var valueTwo = SimulatedModel.Random(randomnessProvider); + var remoteCache = new MemoryDistributedCache(Options.Create(new MemoryDistributedCacheOptions())); + using var target = new DualLayerCacheClient(remoteCache); + + // Act. + target.Write(keyOne, valueOne); + var resultOne = target.TryRead(keyOne, out var resultValueOne); + var resultTwo = target.TryRead(keyOne, out var resultValueTwo); + var resultThree = target.TryRead(keyTwo, out var resultValueThree); + target.Write(keyTwo, valueTwo); + var resultFour = target.TryRead(keyOne, out var resultValueFour); + var resultFive = target.TryRead(keyTwo, out var resultValueFive); + var resultSix = target.TryRead(keyTwo, out var resultValueSix); + target.Invalidate(keyOne); + var resultSeven = target.TryRead(keyOne, out var resultValueSeven); + var resultEight = target.TryRead(keyTwo, out var resultValueEight); + + // Assert. + resultOne.Should().BeTrue(); + resultTwo.Should().BeFalse(); + resultThree.Should().BeFalse(); + resultFour.Should().BeTrue(); + resultFive.Should().BeFalse(); + resultSix.Should().BeTrue(); + resultSeven.Should().BeFalse(); + resultEight.Should().BeTrue(); + resultValueOne.Should().Be(valueOne); + resultValueTwo.Should().BeNull(); + resultValueThree.Should().BeNull(); + resultValueFour.Should().Be(valueOne); + resultValueFive.Should().BeNull(); + resultValueSix.Should().Be(valueTwo); + resultValueSeven.Should().BeNull(); + resultValueEight.Should().Be(valueTwo); + } + + [TestMethod] + public void Process_ShouldProduceDesiredResults() + { + // Arrange. + var keyOne = "foo"; + var keyTwo = "bar"; + using var randomnessProvider = RandomNumberGenerator.Create(); + var produceValueFunction = new Func(() => SimulatedModel.Random(randomnessProvider)); + var remoteCache = new MemoryDistributedCache(Options.Create(new MemoryDistributedCacheOptions())); + using var target = new DualLayerCacheClient(remoteCache); + + // Act. + var targetIsOperative = target.IsOperative; + var resultOne = target.Process(keyOne, produceValueFunction); + var resultTwo = target.Process(keyTwo, produceValueFunction); + var resultThree = target.Process(keyOne, produceValueFunction); + var resultFour = target.Process(keyTwo, produceValueFunction); + var resultOneHashCode = resultOne.GetImpliedHashCode(); + var resultTwoHashCode = resultTwo.GetImpliedHashCode(); + var resultThreeHashCode = resultThree.GetImpliedHashCode(); + var resultFourHashCode = resultFour.GetImpliedHashCode(); + var resultsOneAndTwoAreEqual = resultOneHashCode == resultTwoHashCode; + var resultsOneAndThreeAreEqual = resultOneHashCode == resultThreeHashCode; + var resultsOneAndFourAreEqual = resultOneHashCode == resultFourHashCode; + var resultsTwoAndThreeAreEqual = resultTwoHashCode == resultThreeHashCode; + var resultsTwoAndFourAreEqual = resultTwoHashCode == resultFourHashCode; + var resultsThreeAndFourAreEqual = resultThreeHashCode == resultFourHashCode; + + // Assert. + targetIsOperative.Should().BeTrue(); + resultsOneAndTwoAreEqual.Should().BeFalse(); + resultsOneAndThreeAreEqual.Should().BeTrue(); + resultsOneAndFourAreEqual.Should().BeFalse(); + resultsTwoAndThreeAreEqual.Should().BeFalse(); + resultsTwoAndFourAreEqual.Should().BeTrue(); + resultsThreeAndFourAreEqual.Should().BeFalse(); + } + } +} \ No newline at end of file diff --git a/test/RapidField.SolidInstruments.Core.UnitTests/Caching/InMemoryCacheClientTests.cs b/test/RapidField.SolidInstruments.Core.UnitTests/Caching/InMemoryCacheClientTests.cs index 545633cd..ca8266c6 100644 --- a/test/RapidField.SolidInstruments.Core.UnitTests/Caching/InMemoryCacheClientTests.cs +++ b/test/RapidField.SolidInstruments.Core.UnitTests/Caching/InMemoryCacheClientTests.cs @@ -2,6 +2,7 @@ // Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. // ================================================================================================================================= +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using RapidField.SolidInstruments.Core.Caching; using RapidField.SolidInstruments.Core.Extensions; @@ -13,6 +14,18 @@ namespace RapidField.SolidInstruments.Core.UnitTests.Caching [TestClass] public class InMemoryCacheClientTests { + [TestMethod] + public void FunctionalLifeSpanTest_ShouldProduceDesiredResults_ForAggressiveStrategy() => FunctionalLifeSpanTest_ShouldProduceDesiredResults(InMemoryCachingStrategy.Aggressive, true); + + [TestMethod] + public void FunctionalLifeSpanTest_ShouldProduceDesiredResults_ForConservativeStrategy() => FunctionalLifeSpanTest_ShouldProduceDesiredResults(InMemoryCachingStrategy.Conservative, true); + + [TestMethod] + public void FunctionalLifeSpanTest_ShouldProduceDesiredResults_ForModerateStrategy() => FunctionalLifeSpanTest_ShouldProduceDesiredResults(InMemoryCachingStrategy.Moderate, true); + + [TestMethod] + public void FunctionalLifeSpanTest_ShouldProduceDesiredResults_ForNoCachingStrategy() => FunctionalLifeSpanTest_ShouldProduceDesiredResults(InMemoryCachingStrategy.NoCaching, false); + [TestMethod] public void Process_ShouldProduceDesiredResults_ForAggressiveStrategy() => Process_ShouldProduceDesiredResults(InMemoryCachingStrategy.Aggressive, true); @@ -25,7 +38,78 @@ public class InMemoryCacheClientTests [TestMethod] public void Process_ShouldProduceDesiredResults_ForNoCachingStrategy() => Process_ShouldProduceDesiredResults(InMemoryCachingStrategy.NoCaching, false); - private void Process_ShouldProduceDesiredResults(InMemoryCachingStrategy strategy, Boolean cacheShouldBeOperative) + private static void FunctionalLifeSpanTest_ShouldProduceDesiredResults(InMemoryCachingStrategy strategy, Boolean cacheShouldBeOperative) + { + // Arrange. + var keyOne = "foo"; + var keyTwo = "bar"; + using var randomnessProvider = RandomNumberGenerator.Create(); + var valueOne = SimulatedModel.Random(randomnessProvider); + var valueTwo = SimulatedModel.Random(randomnessProvider); + using var target = new InMemoryCacheClient(strategy); + + // Act. + target.Write(keyOne, valueOne); + var resultOne = target.TryRead(keyOne, out var resultValueOne); + var resultTwo = target.TryRead(keyOne, out var resultValueTwo); + var resultThree = target.TryRead(keyTwo, out var resultValueThree); + target.Write(keyTwo, valueTwo); + var resultFour = target.TryRead(keyOne, out var resultValueFour); + var resultFive = target.TryRead(keyTwo, out var resultValueFive); + var resultSix = target.TryRead(keyTwo, out var resultValueSix); + target.Invalidate(keyOne); + var resultSeven = target.TryRead(keyOne, out var resultValueSeven); + var resultEight = target.TryRead(keyTwo, out var resultValueEight); + target.Clear(); + var resultNine = target.TryRead(keyTwo, out var resultValueNine); + + if (cacheShouldBeOperative) + { + // Assert. + resultOne.Should().BeTrue(); + resultTwo.Should().BeFalse(); + resultThree.Should().BeFalse(); + resultFour.Should().BeTrue(); + resultFive.Should().BeFalse(); + resultSix.Should().BeTrue(); + resultSeven.Should().BeFalse(); + resultEight.Should().BeTrue(); + resultNine.Should().BeFalse(); + resultValueOne.Should().BeSameAs(valueOne); + resultValueTwo.Should().BeNull(); + resultValueThree.Should().BeNull(); + resultValueFour.Should().BeSameAs(valueOne); + resultValueFive.Should().BeNull(); + resultValueSix.Should().BeSameAs(valueTwo); + resultValueSeven.Should().BeNull(); + resultValueEight.Should().BeSameAs(valueTwo); + resultValueNine.Should().BeNull(); + } + else + { + // Assert. + resultOne.Should().BeFalse(); + resultTwo.Should().BeFalse(); + resultThree.Should().BeFalse(); + resultFour.Should().BeFalse(); + resultFive.Should().BeFalse(); + resultSix.Should().BeFalse(); + resultSeven.Should().BeFalse(); + resultEight.Should().BeFalse(); + resultNine.Should().BeFalse(); + resultValueOne.Should().BeNull(); + resultValueTwo.Should().BeNull(); + resultValueThree.Should().BeNull(); + resultValueFour.Should().BeNull(); + resultValueFive.Should().BeNull(); + resultValueSix.Should().BeNull(); + resultValueSeven.Should().BeNull(); + resultValueEight.Should().BeNull(); + resultValueNine.Should().BeNull(); + } + } + + private static void Process_ShouldProduceDesiredResults(InMemoryCachingStrategy strategy, Boolean cacheShouldBeOperative) { // Arrange. var keyOne = "foo"; @@ -52,13 +136,13 @@ private void Process_ShouldProduceDesiredResults(InMemoryCachingStrategy strateg var resultsThreeAndFourAreEqual = resultThreeHashCode == resultFourHashCode; // Assert. - Assert.AreEqual(targetIsOperative, cacheShouldBeOperative); - Assert.IsFalse(resultsOneAndTwoAreEqual); - Assert.AreEqual(resultsOneAndThreeAreEqual, cacheShouldBeOperative); - Assert.IsFalse(resultsOneAndFourAreEqual); - Assert.IsFalse(resultsTwoAndThreeAreEqual); - Assert.AreEqual(resultsTwoAndFourAreEqual, cacheShouldBeOperative); - Assert.IsFalse(resultsThreeAndFourAreEqual); + targetIsOperative.Should().Be(cacheShouldBeOperative); + resultsOneAndTwoAreEqual.Should().BeFalse(); + resultsOneAndThreeAreEqual.Should().Be(cacheShouldBeOperative); + resultsOneAndFourAreEqual.Should().BeFalse(); + resultsTwoAndThreeAreEqual.Should().BeFalse(); + resultsTwoAndFourAreEqual.Should().Be(cacheShouldBeOperative); + resultsThreeAndFourAreEqual.Should().BeFalse(); } } } \ No newline at end of file diff --git a/test/RapidField.SolidInstruments.Core.UnitTests/Extensions/ObjectExtensionsTests.cs b/test/RapidField.SolidInstruments.Core.UnitTests/Extensions/ObjectExtensionsTests.cs index 9a51f2de..78db5336 100644 --- a/test/RapidField.SolidInstruments.Core.UnitTests/Extensions/ObjectExtensionsTests.cs +++ b/test/RapidField.SolidInstruments.Core.UnitTests/Extensions/ObjectExtensionsTests.cs @@ -14,6 +14,74 @@ namespace RapidField.SolidInstruments.Core.UnitTests.Extensions [TestClass] public class ObjectExtensionsTests { + [TestMethod] + public void CalculateSizeInBytes_ShouldProduceAccurateResult_ForAnonymousReferenceTarget() + { + // Arrange. + var expectedResult = 255; + var reference = new TimeOfDay(TimeZoneInfo.Utc, 8, 23, 40, 819); + var target = new + { + ReferenceOne = reference, + ReferenceTwo = reference, + ValueOne = 42, + ValueTwo = (Byte)0x01, + ValueThree = (Byte)0x02, + Collection = new String[] + { + "foo", + "bar", + "foobar" + } + }; + + // Act. + var result = target.CalculateSizeInBytes(); + + // Assert. + result.Should().Be(expectedResult); + } + + [TestMethod] + public void CalculateSizeInBytes_ShouldProduceAccurateResult_ForCollectionTarget() + { + // Arrange. + var expectedResult = 52; + var target = new String[] + { + "foo", + "bar", + null, + "foobar" + }; + + // Act. + var result = target.CalculateSizeInBytes(); + + // Assert. + result.Should().Be(expectedResult); + } + + [TestMethod] + public void CalculateSizeInBytes_ShouldProduceAccurateResult_ForComplexReferenceTarget() + { + using (var randomnessProvider = RandomNumberGenerator.Create()) + { + // Arrange. + var target = SimulatedModel.Random(randomnessProvider); + var clone = target.Clone() as SimulatedModel; + + // Act. + var resultOne = target.CalculateSizeInBytes(); + var resultTwo = target.CalculateSizeInBytes(); + + // Assert. + resultOne.Should().BeGreaterThan(0); + resultTwo.Should().BeGreaterThan(0); + resultOne.Should().Be(resultTwo); + } + } + [TestMethod] public void CalculateSizeInBytes_ShouldProduceAccurateResult_ForNullTarget() { @@ -25,7 +93,21 @@ public void CalculateSizeInBytes_ShouldProduceAccurateResult_ForNullTarget() var result = target.CalculateSizeInBytes(); // Assert. - Assert.AreEqual(expectedResult, result); + result.Should().Be(expectedResult); + } + + [TestMethod] + public void CalculateSizeInBytes_ShouldProduceAccurateResult_ForValueTarget() + { + // Arrange. + var expectedResult = 16; + var target = Guid.NewGuid(); + + // Act. + var result = target.CalculateSizeInBytes(); + + // Assert. + result.Should().Be(expectedResult); } [TestMethod] diff --git a/test/RapidField.SolidInstruments.DataAccess.UnitTests/SimulatedEntity.cs b/test/RapidField.SolidInstruments.DataAccess.UnitTests/SimulatedEntity.cs index 52f53ed8..ad4a497c 100644 --- a/test/RapidField.SolidInstruments.DataAccess.UnitTests/SimulatedEntity.cs +++ b/test/RapidField.SolidInstruments.DataAccess.UnitTests/SimulatedEntity.cs @@ -57,7 +57,7 @@ protected SimulatedEntity(Guid identifier, TValue value) /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(SimulatedEntity a, SimulatedEntity b) => a == b == false; + public static Boolean operator !=(SimulatedEntity a, SimulatedEntity b) => (a == b) is false; /// /// Determines whether or not two specified instances are equal. @@ -136,7 +136,7 @@ public Boolean Equals(SimulatedEntity other) { return false; } - else if (Value.Equals(other.Value) == false) + else if (Value.Equals(other.Value) is false) { return false; } diff --git a/test/RapidField.SolidInstruments.InversionOfControl.UnitTests/SimulatedDependecyContainer.cs b/test/RapidField.SolidInstruments.InversionOfControl.UnitTests/SimulatedDependecyContainer.cs index b3d61d09..e01a249c 100644 --- a/test/RapidField.SolidInstruments.InversionOfControl.UnitTests/SimulatedDependecyContainer.cs +++ b/test/RapidField.SolidInstruments.InversionOfControl.UnitTests/SimulatedDependecyContainer.cs @@ -83,6 +83,17 @@ public SimulatedDependecyContainer(IConfiguration applicationConfiguration, ISer /// protected sealed override void Dispose(Boolean disposing) => base.Dispose(disposing); + /// + /// Conditionally registers important dependency types if they are missing following user-defined registrations. + /// + /// + /// The object that configures the container. + /// + protected override void RegisterFallbackTypes(SimulatedSourceConfigurator configurator) + { + return; + } + /// /// Registers a command mediator with the configurator. /// diff --git a/test/RapidField.SolidInstruments.Messaging.InMemory.UnitTests/SimulatedMessagingServiceExecutorTests.cs b/test/RapidField.SolidInstruments.Messaging.InMemory.UnitTests/SimulatedMessagingServiceExecutorTests.cs index 7f3117e7..4e3de820 100644 --- a/test/RapidField.SolidInstruments.Messaging.InMemory.UnitTests/SimulatedMessagingServiceExecutorTests.cs +++ b/test/RapidField.SolidInstruments.Messaging.InMemory.UnitTests/SimulatedMessagingServiceExecutorTests.cs @@ -40,9 +40,9 @@ private void OnStarting(ICommandMediator mediator) private void OnStopping(ICommandMediator mediator) { - Thread.Sleep(2584); - // Arrange. + var customers = SimulatedServiceState.Customers; + Thread.Sleep(2584); var acmeCoCustomer = CustomerModel.Named.AcmeCo; var smithIndustriesCustomer = CustomerModel.Named.SmithIndustries; @@ -51,8 +51,8 @@ private void OnStopping(ICommandMediator mediator) mediator.Process(new CreateCustomerCommandMessage(new CreateCustomerCommand(smithIndustriesCustomer))); // Assert. - Thread.Sleep(10946); - SimulatedServiceState.Customers.Should().HaveCount(2); + Thread.Sleep(6765); + customers.Should().HaveCount(2); // Act. acmeCoCustomer.Name = "New Acme Corporation"; @@ -60,7 +60,7 @@ private void OnStopping(ICommandMediator mediator) // Assert. Thread.Sleep(6765); - SimulatedServiceState.Customers.Where(entity => entity.Identifier == acmeCoCustomer.Identifier).Single().Name.Should().Be(acmeCoCustomer.Name); + customers.Where(entity => entity.Identifier == acmeCoCustomer.Identifier).Single().Name.Should().Be(acmeCoCustomer.Name); // Act. var pingCorrelationIdentifier = Guid.NewGuid(); diff --git a/test/RapidField.SolidInstruments.Messaging.UnitTests/SimulatedObject.cs b/test/RapidField.SolidInstruments.Messaging.UnitTests/SimulatedObject.cs index 5ae0de72..3cf5b054 100644 --- a/test/RapidField.SolidInstruments.Messaging.UnitTests/SimulatedObject.cs +++ b/test/RapidField.SolidInstruments.Messaging.UnitTests/SimulatedObject.cs @@ -41,7 +41,7 @@ public SimulatedObject() /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(SimulatedObject a, SimulatedObject b) => a == b == false; + public static Boolean operator !=(SimulatedObject a, SimulatedObject b) => (a == b) is false; /// /// Determines whether or not two specified instances are equal. diff --git a/test/RapidField.SolidInstruments.Serialization.UnitTests/SimulatedObject.cs b/test/RapidField.SolidInstruments.Serialization.UnitTests/SimulatedObject.cs index 66a05fd0..484a7a51 100644 --- a/test/RapidField.SolidInstruments.Serialization.UnitTests/SimulatedObject.cs +++ b/test/RapidField.SolidInstruments.Serialization.UnitTests/SimulatedObject.cs @@ -41,7 +41,7 @@ public SimulatedObject() /// /// A value indicating whether or not the specified instances are not equal. /// - public static Boolean operator !=(SimulatedObject a, SimulatedObject b) => a == b == false; + public static Boolean operator !=(SimulatedObject a, SimulatedObject b) => (a == b) is false; /// /// Determines whether or not two specified instances are equal.