diff --git a/Swan.Lite/Collections/CollectionCacheRepository.cs b/Swan.Lite/Collections/CollectionCacheRepository.cs
index 496f410..008b9a8 100644
--- a/Swan.Lite/Collections/CollectionCacheRepository.cs
+++ b/Swan.Lite/Collections/CollectionCacheRepository.cs
@@ -3,50 +3,47 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
-namespace Swan.Collections
-{
+namespace Swan.Collections {
+ ///
+ /// A thread-safe collection cache repository for types.
+ ///
+ /// The type of member to cache.
+ public class CollectionCacheRepository {
+ private readonly Lazy>> _data = new Lazy>>(() => new ConcurrentDictionary>(), true);
+
///
- /// A thread-safe collection cache repository for types.
+ /// Determines whether the cache contains the specified key.
///
- /// The type of member to cache.
- public class CollectionCacheRepository
- {
- private readonly Lazy>> _data =
- new Lazy>>(() =>
- new ConcurrentDictionary>(), true);
-
- ///
- /// Determines whether the cache contains the specified key.
- ///
- /// The key.
- /// true if the cache contains the key, otherwise false.
- public bool ContainsKey(Type key) => _data.Value.ContainsKey(key);
-
- ///
- /// Retrieves the properties stored for the specified type.
- /// If the properties are not available, it calls the factory method to retrieve them
- /// and returns them as an array of PropertyInfo.
- ///
- /// The key.
- /// The factory.
- ///
- /// An array of the properties stored for the specified type.
- ///
- ///
- /// key
- /// or
- /// factory.
- ///
- /// type.
- public IEnumerable Retrieve(Type key, Func> factory)
- {
- if (key == null)
- throw new ArgumentNullException(nameof(key));
-
- if (factory == null)
- throw new ArgumentNullException(nameof(factory));
-
- return _data.Value.GetOrAdd(key, k => factory.Invoke(k).Where(item => item != null));
- }
- }
+ /// The key.
+ /// true if the cache contains the key, otherwise false.
+ public Boolean ContainsKey(Type key) => this._data.Value.ContainsKey(key);
+
+ ///
+ /// Retrieves the properties stored for the specified type.
+ /// If the properties are not available, it calls the factory method to retrieve them
+ /// and returns them as an array of PropertyInfo.
+ ///
+ /// The key.
+ /// The factory.
+ ///
+ /// An array of the properties stored for the specified type.
+ ///
+ ///
+ /// key
+ /// or
+ /// factory.
+ ///
+ /// type.
+ public IEnumerable Retrieve(Type key, Func> factory) {
+ if(key == null) {
+ throw new ArgumentNullException(nameof(key));
+ }
+
+ if(factory == null) {
+ throw new ArgumentNullException(nameof(factory));
+ }
+
+ return this._data.Value.GetOrAdd(key, k => factory.Invoke(k).Where(item => item != null));
+ }
+ }
}
diff --git a/Swan.Lite/Collections/ComponentCollection`1.cs b/Swan.Lite/Collections/ComponentCollection`1.cs
index 7421c09..118712f 100644
--- a/Swan.Lite/Collections/ComponentCollection`1.cs
+++ b/Swan.Lite/Collections/ComponentCollection`1.cs
@@ -3,74 +3,75 @@ using System.Collections;
using System.Collections.Generic;
using Swan.Configuration;
-namespace Swan.Collections
-{
+namespace Swan.Collections {
+ ///
+ /// Implements a collection of components.
+ /// Each component in the collection may be given a unique name for later retrieval.
+ ///
+ /// The type of components in the collection.
+ ///
+ public class ComponentCollection : ConfiguredObject, IComponentCollection {
+ private readonly List _components = new List();
+
+ private readonly List<(String, T)> _componentsWithSafeNames = new List<(String, T)>();
+
+ private readonly Dictionary _namedComponents = new Dictionary();
+
+ ///
+ public Int32 Count => this._components.Count;
+
+ ///
+ public IReadOnlyDictionary Named => this._namedComponents;
+
+ ///
+ public IReadOnlyList<(String SafeName, T Component)> WithSafeNames => this._componentsWithSafeNames;
+
+ ///
+ public T this[Int32 index] => this._components[index];
+
+ ///
+ public T this[String key] => this._namedComponents[key];
+
+ ///
+ public IEnumerator GetEnumerator() => this._components.GetEnumerator();
+
+ ///
+ IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)this._components).GetEnumerator();
+
+ ///
+ /// The collection is locked.
+ public void Add(String name, T component) {
+ this.EnsureConfigurationNotLocked();
+
+ if(name != null) {
+ if(name.Length == 0) {
+ throw new ArgumentException("Component name is empty.", nameof(name));
+ }
+
+ if(this._namedComponents.ContainsKey(name)) {
+ throw new ArgumentException("Duplicate component name.", nameof(name));
+ }
+ }
+
+ if(component == null) {
+ throw new ArgumentNullException(nameof(component));
+ }
+
+ if(this._components.Contains(component)) {
+ throw new ArgumentException("Component has already been added.", nameof(component));
+ }
+
+ this._components.Add(component);
+ this._componentsWithSafeNames.Add((name ?? $"<{component.GetType().Name}>", component));
+
+ if(name != null) {
+ this._namedComponents.Add(name, component);
+ }
+ }
+
///
- /// Implements a collection of components.
- /// Each component in the collection may be given a unique name for later retrieval.
+ /// Locks the collection, preventing further additions.
///
- /// The type of components in the collection.
- ///
- public class ComponentCollection : ConfiguredObject, IComponentCollection
- {
- private readonly List _components = new List();
-
- private readonly List<(string, T)> _componentsWithSafeNames = new List<(string, T)>();
-
- private readonly Dictionary _namedComponents = new Dictionary();
-
- ///
- public int Count => _components.Count;
-
- ///
- public IReadOnlyDictionary Named => _namedComponents;
-
- ///
- public IReadOnlyList<(string SafeName, T Component)> WithSafeNames => _componentsWithSafeNames;
-
- ///
- public T this[int index] => _components[index];
-
- ///
- public T this[string key] => _namedComponents[key];
-
- ///
- public IEnumerator GetEnumerator() => _components.GetEnumerator();
-
- ///
- IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)_components).GetEnumerator();
-
- ///
- /// The collection is locked.
- public void Add(string name, T component)
- {
- EnsureConfigurationNotLocked();
-
- if (name != null)
- {
- if (name.Length == 0)
- throw new ArgumentException("Component name is empty.", nameof(name));
-
- if (_namedComponents.ContainsKey(name))
- throw new ArgumentException("Duplicate component name.", nameof(name));
- }
-
- if (component == null)
- throw new ArgumentNullException(nameof(component));
-
- if (_components.Contains(component))
- throw new ArgumentException("Component has already been added.", nameof(component));
-
- _components.Add(component);
- _componentsWithSafeNames.Add((name ?? $"<{component.GetType().Name}>", component));
-
- if (name != null)
- _namedComponents.Add(name, component);
- }
-
- ///
- /// Locks the collection, preventing further additions.
- ///
- public void Lock() => LockConfiguration();
- }
+ public void Lock() => this.LockConfiguration();
+ }
}
diff --git a/Swan.Lite/Collections/ConcurrentDataDictionary`2.cs b/Swan.Lite/Collections/ConcurrentDataDictionary`2.cs
index 58fa75a..38a5f15 100644
--- a/Swan.Lite/Collections/ConcurrentDataDictionary`2.cs
+++ b/Swan.Lite/Collections/ConcurrentDataDictionary`2.cs
@@ -4,301 +4,266 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
-namespace Swan.Collections
-{
+namespace Swan.Collections {
+ ///
+ /// Represents a thread-safe collection of key/value pairs that does not store null values
+ /// and can be accessed by multiple threads concurrently.
+ ///
+ /// The type of keys in the dictionary. This must be a reference type.
+ /// The type of values in the dictionary. This must be a reference type.
+ ///
+ public sealed class ConcurrentDataDictionary : IDataDictionary where TKey : class where TValue : class {
+ #region Private data
+
+ private readonly ConcurrentDictionary _dictionary;
+
+ #endregion
+
+ #region Instance management
+
///
- /// Represents a thread-safe collection of key/value pairs that does not store null values
- /// and can be accessed by multiple threads concurrently.
+ /// Initializes a new instance of the class
+ /// that is empty, has the default concurrency level, has the default initial capacity,
+ /// and uses the default comparer for .
///
- /// The type of keys in the dictionary. This must be a reference type.
- /// The type of values in the dictionary. This must be a reference type.
- ///
- public sealed class ConcurrentDataDictionary : IDataDictionary
- where TKey : class
- where TValue : class
- {
- #region Private data
-
- private readonly ConcurrentDictionary _dictionary;
-
- #endregion
-
- #region Instance management
-
- ///
- /// Initializes a new instance of the class
- /// that is empty, has the default concurrency level, has the default initial capacity,
- /// and uses the default comparer for .
- ///
- ///
- public ConcurrentDataDictionary()
- {
- _dictionary = new ConcurrentDictionary();
- }
-
- ///
- /// Initializes a new instance of the class
- /// that contains elements copied from the specified , has the default concurrency level,
- /// has the default initial capacity, and uses the default comparer for .
- ///
- /// The whose elements are copied
- /// to the new .
- /// is .
- ///
- /// Since does not store null values,
- /// key/value pairs whose value is will not be copied from .
- ///
- ///
- public ConcurrentDataDictionary(IEnumerable> collection)
- {
- if (collection == null)
- throw new ArgumentNullException(nameof(collection));
-
- _dictionary = new ConcurrentDictionary(collection.Where(pair => pair.Value != null));
- }
-
- ///
- /// Initializes a new instance of the class
- /// that is empty, has the default concurrency level and capacity, and uses the specified .
- ///
- /// The equality comparison implementation to use when comparing keys.
- /// is .
- ///
- public ConcurrentDataDictionary(IEqualityComparer comparer)
- {
- _dictionary = new ConcurrentDictionary(comparer);
- }
-
- ///
- /// Initializes a new instance of the class
- /// that contains elements copied from the specified , has the default concurrency level,
- /// has the default initial capacity, and uses the specified .
- ///
- /// The whose elements are copied
- /// to the new .
- /// The equality comparison implementation to use when comparing keys.
- ///
- /// Since does not store null values,
- /// key/value pairs whose value is will not be copied from .
- ///
- ///
- /// is .
- /// - or -.
- /// is .
- ///
- ///
- public ConcurrentDataDictionary(IEnumerable> collection, IEqualityComparer comparer)
- {
- if (collection == null)
- throw new ArgumentNullException(nameof(collection));
-
- _dictionary = new ConcurrentDictionary(collection.Where(pair => pair.Value != null), comparer);
- }
-
- ///
- /// Initializes a new instance of the class
- /// that is empty, has the specified concurrency level and capacity, and uses the default comparer for the key type.
- ///
- /// The estimated number of threads that will update
- /// the concurrently.
- /// The initial number of elements that the can contain.
- ///
- /// is less than 1.
- /// - or -.
- /// is less than 0.
- ///
- ///
- public ConcurrentDataDictionary(int concurrencyLevel, int capacity)
- {
- _dictionary = new ConcurrentDictionary(concurrencyLevel, capacity);
- }
-
- ///
- /// Initializes a new instance of the class
- /// that contains elements copied from the specified , has the specified concurrency level,
- /// has the default initial capacity, and uses the specified .
- ///
- /// The estimated number of threads that will update
- /// the concurrently.
- /// The whose elements are copied
- /// to the new .
- /// The equality comparison implementation to use when comparing keys.
- ///
- /// Since does not store null values,
- /// key/value pairs whose value is will not be copied from .
- ///
- ///
- /// is .
- /// - or -.
- /// is .
- ///
- /// is less than 1.
- ///
- public ConcurrentDataDictionary(int concurrencyLevel, IEnumerable> collection, IEqualityComparer comparer)
- {
- if (collection == null)
- throw new ArgumentNullException(nameof(collection));
-
- _dictionary = new ConcurrentDictionary(
- concurrencyLevel,
- collection.Where(pair => pair.Value != null),
- comparer);
- }
-
- #endregion
-
- #region Public APIs
-
- ///
- public int Count => _dictionary.Count;
-
- ///
- public bool IsEmpty => _dictionary.IsEmpty;
-
- ///
- public ICollection Keys => _dictionary.Keys;
-
- ///
- public ICollection Values => _dictionary.Values;
-
- ///
- public TValue? this[TKey key]
- {
- get => _dictionary.TryGetValue(key ?? throw new ArgumentNullException(nameof(key)), out var value) ? value : null;
- set
- {
- if (value != null)
- {
- _dictionary[key] = value;
- }
- else
- {
- _dictionary.TryRemove(key, out _);
- }
- }
- }
-
- ///
- public void Clear() => _dictionary.Clear();
-
- ///
- public bool ContainsKey(TKey key) => _dictionary.ContainsKey(key);
-
- ///
- public TValue? GetOrAdd(TKey key, TValue value)
- {
- if (key == null)
- throw new ArgumentNullException(nameof(key));
-
- if (value != null)
- return _dictionary.GetOrAdd(key, value);
-
- return _dictionary.TryGetValue(key, out var retrievedValue) ? retrievedValue : null;
- }
-
- ///
- public bool Remove(TKey key) => _dictionary.TryRemove(key, out _);
-
- ///
- public bool TryAdd(TKey key, TValue value)
- {
- if (key == null)
- throw new ArgumentNullException(nameof(key));
-
- return value == null || _dictionary.TryAdd(key, value);
- }
-
- ///
- public bool TryGetValue(TKey key, out TValue value) => _dictionary.TryGetValue(key, out value);
-
- ///
- public bool TryRemove(TKey key, out TValue value) => _dictionary.TryRemove(key, out value);
-
- ///
- public bool TryUpdate(TKey key, TValue newValue, TValue comparisonValue)
- {
- if (key == null)
- throw new ArgumentNullException(nameof(key));
-
- return newValue != null && comparisonValue != null && _dictionary.TryUpdate(key, newValue, comparisonValue);
- }
-
- #endregion
-
- #region Implementation of IDictionary
-
- ///
- void IDictionary.Add(TKey key, TValue value)
- {
- if (value != null)
- {
- ((IDictionary)_dictionary).Add(key, value);
- }
- else
- {
- _dictionary.TryRemove(key, out _);
- }
- }
-
- #endregion
-
- #region Implementation of IReadOnlyDictionary
-
- ///
- IEnumerable IReadOnlyDictionary.Keys => _dictionary.Keys;
-
- ///
- IEnumerable IReadOnlyDictionary.Values => _dictionary.Values;
-
- #endregion
-
- #region Implementation of ICollection>
-
- ///
- ///
- /// This property is always for a .
- ///
- bool ICollection>.IsReadOnly => false;
-
- ///
- void ICollection>.Add(KeyValuePair item)
- {
- if (item.Value != null)
- {
- ((ICollection>)_dictionary).Add(item);
- }
- else
- {
- _dictionary.TryRemove(item.Key, out _);
- }
- }
-
- ///
- bool ICollection>.Contains(KeyValuePair item)
- => ((ICollection>)_dictionary).Contains(item);
-
- ///
- void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex)
- => ((ICollection>)_dictionary).CopyTo(array, arrayIndex);
-
- ///
- bool ICollection>.Remove(KeyValuePair item)
- => ((ICollection>)_dictionary).Remove(item);
-
- #endregion
-
- #region Implementation of IEnumerable>
-
- ///
- IEnumerator> IEnumerable>.GetEnumerator() => _dictionary.GetEnumerator();
-
- #endregion
-
- #region Implementation of IEnumerable
-
- ///
- IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)_dictionary).GetEnumerator();
-
- #endregion
- }
+ ///
+ public ConcurrentDataDictionary() => this._dictionary = new ConcurrentDictionary();
+
+ ///
+ /// Initializes a new instance of the class
+ /// that contains elements copied from the specified , has the default concurrency level,
+ /// has the default initial capacity, and uses the default comparer for .
+ ///
+ /// The whose elements are copied
+ /// to the new .
+ /// is .
+ ///
+ /// Since does not store null values,
+ /// key/value pairs whose value is will not be copied from .
+ ///
+ ///
+ public ConcurrentDataDictionary(IEnumerable> collection) {
+ if(collection == null) {
+ throw new ArgumentNullException(nameof(collection));
+ }
+
+ this._dictionary = new ConcurrentDictionary(collection.Where(pair => pair.Value != null));
+ }
+
+ ///
+ /// Initializes a new instance of the class
+ /// that is empty, has the default concurrency level and capacity, and uses the specified .
+ ///
+ /// The equality comparison implementation to use when comparing keys.
+ /// is .
+ ///
+ public ConcurrentDataDictionary(IEqualityComparer comparer) => this._dictionary = new ConcurrentDictionary(comparer);
+
+ ///
+ /// Initializes a new instance of the class
+ /// that contains elements copied from the specified , has the default concurrency level,
+ /// has the default initial capacity, and uses the specified .
+ ///
+ /// The whose elements are copied
+ /// to the new .
+ /// The equality comparison implementation to use when comparing keys.
+ ///
+ /// Since does not store null values,
+ /// key/value pairs whose value is will not be copied from .
+ ///
+ ///
+ /// is .
+ /// - or -.
+ /// is .
+ ///
+ ///
+ public ConcurrentDataDictionary(IEnumerable> collection, IEqualityComparer comparer) {
+ if(collection == null) {
+ throw new ArgumentNullException(nameof(collection));
+ }
+
+ this._dictionary = new ConcurrentDictionary(collection.Where(pair => pair.Value != null), comparer);
+ }
+
+ ///
+ /// Initializes a new instance of the class
+ /// that is empty, has the specified concurrency level and capacity, and uses the default comparer for the key type.
+ ///
+ /// The estimated number of threads that will update
+ /// the concurrently.
+ /// The initial number of elements that the can contain.
+ ///
+ /// is less than 1.
+ /// - or -.
+ /// is less than 0.
+ ///
+ ///
+ public ConcurrentDataDictionary(Int32 concurrencyLevel, Int32 capacity) => this._dictionary = new ConcurrentDictionary(concurrencyLevel, capacity);
+
+ ///
+ /// Initializes a new instance of the class
+ /// that contains elements copied from the specified , has the specified concurrency level,
+ /// has the default initial capacity, and uses the specified .
+ ///
+ /// The estimated number of threads that will update
+ /// the concurrently.
+ /// The whose elements are copied
+ /// to the new .
+ /// The equality comparison implementation to use when comparing keys.
+ ///
+ /// Since does not store null values,
+ /// key/value pairs whose value is will not be copied from .
+ ///
+ ///
+ /// is .
+ /// - or -.
+ /// is .
+ ///
+ /// is less than 1.
+ ///
+ public ConcurrentDataDictionary(Int32 concurrencyLevel, IEnumerable> collection, IEqualityComparer comparer) {
+ if(collection == null) {
+ throw new ArgumentNullException(nameof(collection));
+ }
+
+ this._dictionary = new ConcurrentDictionary(concurrencyLevel, collection.Where(pair => pair.Value != null), comparer);
+ }
+
+ #endregion
+
+ #region Public APIs
+
+ ///
+ public Int32 Count => this._dictionary.Count;
+
+ ///
+ public Boolean IsEmpty => this._dictionary.IsEmpty;
+
+ ///
+ public ICollection Keys => this._dictionary.Keys;
+
+ ///
+ public ICollection Values => this._dictionary.Values;
+
+ ///
+ public TValue this[TKey key] {
+ get => this._dictionary.TryGetValue(key ?? throw new ArgumentNullException(nameof(key)), out TValue value) ? value : null;
+ set {
+ if(value != null) {
+ this._dictionary[key] = value;
+ } else {
+ _ = this._dictionary.TryRemove(key, out _);
+ }
+ }
+ }
+
+ ///
+ public void Clear() => this._dictionary.Clear();
+
+ ///
+ public Boolean ContainsKey(TKey key) => this._dictionary.ContainsKey(key);
+
+ ///
+ public TValue GetOrAdd(TKey key, TValue value) {
+ if(key == null) {
+ throw new ArgumentNullException(nameof(key));
+ }
+
+ return value != null ? this._dictionary.GetOrAdd(key, value) : this._dictionary.TryGetValue(key, out TValue retrievedValue) ? retrievedValue : null;
+ }
+
+ ///
+ public Boolean Remove(TKey key) => this._dictionary.TryRemove(key, out _);
+
+ ///
+ public Boolean TryAdd(TKey key, TValue value) {
+ if(key == null) {
+ throw new ArgumentNullException(nameof(key));
+ }
+
+ return value == null || this._dictionary.TryAdd(key, value);
+ }
+
+ ///
+ public Boolean TryGetValue(TKey key, out TValue value) => this._dictionary.TryGetValue(key, out value);
+
+ ///
+ public Boolean TryRemove(TKey key, out TValue value) => this._dictionary.TryRemove(key, out value);
+
+ ///
+ public Boolean TryUpdate(TKey key, TValue newValue, TValue comparisonValue) {
+ if(key == null) {
+ throw new ArgumentNullException(nameof(key));
+ }
+
+ return newValue != null && comparisonValue != null && this._dictionary.TryUpdate(key, newValue, comparisonValue);
+ }
+
+ #endregion
+
+ #region Implementation of IDictionary
+
+ ///
+ void IDictionary.Add(TKey key, TValue value) {
+ if(value != null) {
+ ((IDictionary)this._dictionary).Add(key, value);
+ } else {
+ _ = this._dictionary.TryRemove(key, out _);
+ }
+ }
+
+ #endregion
+
+ #region Implementation of IReadOnlyDictionary
+
+ ///
+ IEnumerable IReadOnlyDictionary.Keys => this._dictionary.Keys;
+
+ ///
+ IEnumerable IReadOnlyDictionary.Values => this._dictionary.Values;
+
+ #endregion
+
+ #region Implementation of ICollection>
+
+ ///
+ ///
+ /// This property is always for a .
+ ///
+ Boolean ICollection>.IsReadOnly => false;
+
+ ///
+ void ICollection>.Add(KeyValuePair item) {
+ if(item.Value != null) {
+ ((ICollection>)this._dictionary).Add(item);
+ } else {
+ _ = this._dictionary.TryRemove(item.Key, out _);
+ }
+ }
+
+ ///
+ Boolean ICollection>.Contains(KeyValuePair item) => ((ICollection>)this._dictionary).Contains(item);
+
+ ///
+ void ICollection>.CopyTo(KeyValuePair[] array, Int32 arrayIndex) => ((ICollection>)this._dictionary).CopyTo(array, arrayIndex);
+
+ ///
+ Boolean ICollection>.Remove(KeyValuePair item) => ((ICollection>)this._dictionary).Remove(item);
+
+ #endregion
+
+ #region Implementation of IEnumerable>
+
+ ///
+ IEnumerator> IEnumerable>.GetEnumerator() => this._dictionary.GetEnumerator();
+
+ #endregion
+
+ #region Implementation of IEnumerable
+
+ ///
+ IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)this._dictionary).GetEnumerator();
+
+ #endregion
+ }
}
diff --git a/Swan.Lite/Collections/DataDictionary`2.cs b/Swan.Lite/Collections/DataDictionary`2.cs
index 24f5143..e5ed5c9 100644
--- a/Swan.Lite/Collections/DataDictionary`2.cs
+++ b/Swan.Lite/Collections/DataDictionary`2.cs
@@ -1,341 +1,312 @@
-using System;
+
+using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
-namespace Swan.Collections
-{
+namespace Swan.Collections {
+ ///
+ /// Represents a non-thread-safe collection of key/value pairs that does not store null values.
+ ///
+ /// The type of keys in the dictionary. This must be a reference type.
+ /// The type of values in the dictionary. This must be a reference type.
+ ///
+ public sealed class DataDictionary : IDataDictionary
+ where TKey : class
+ where TValue : class {
+ #region Private data
+
+ private readonly Dictionary _dictionary;
+
+ #endregion
+
+ #region Instance management
+
///
- /// Represents a non-thread-safe collection of key/value pairs that does not store null values.
+ /// Initializes a new instance of the class
+ /// that is empty, has the default initial capacity,
+ /// and uses the default comparer for .
///
- /// The type of keys in the dictionary. This must be a reference type.
- /// The type of values in the dictionary. This must be a reference type.
- ///
- public sealed class DataDictionary : IDataDictionary
- where TKey : class
- where TValue : class
- {
- #region Private data
-
- private readonly Dictionary _dictionary;
-
- #endregion
-
- #region Instance management
-
- ///
- /// Initializes a new instance of the class
- /// that is empty, has the default initial capacity,
- /// and uses the default comparer for .
- ///
- ///
- public DataDictionary()
- {
- _dictionary = new Dictionary();
- }
-
- ///
- /// Initializes a new instance of the class
- /// that contains elements copied from the specified ,
- /// has the default initial capacity, and uses the default comparer for .
- ///
- /// The whose elements are copied
- /// to the new .
- /// is .
- ///
- /// Since does not store null values,
- /// key/value pairs whose value is will not be copied from .
- ///
- ///
- public DataDictionary(IEnumerable> collection)
- {
- if (collection == null)
- throw new ArgumentNullException(nameof(collection));
-
- _dictionary = new Dictionary();
- foreach (var pair in collection.Where(pair => pair.Value != null))
- {
- _dictionary.Add(pair.Key, pair.Value);
- }
- }
-
- ///
- /// Initializes a new instance of the class
- /// that is empty, has the default capacity, and uses the specified .
- ///
- /// The equality comparison implementation to use when comparing keys.
- /// is .
- ///
- public DataDictionary(IEqualityComparer comparer)
- {
- _dictionary = new Dictionary(comparer);
- }
-
- ///
- /// Initializes a new instance of the class
- /// that contains elements copied from the specified ,
- /// has the default initial capacity, and uses the specified .
- ///
- /// The whose elements are copied
- /// to the new .
- /// The equality comparison implementation to use when comparing keys.
- ///
- /// Since does not store null values,
- /// key/value pairs whose value is will not be copied from .
- ///
- ///
- /// is .
- /// - or -.
- /// is .
- ///
- ///
- public DataDictionary(IEnumerable> collection, IEqualityComparer comparer)
- {
- if (collection == null)
- throw new ArgumentNullException(nameof(collection));
-
- _dictionary = new Dictionary(comparer);
- foreach (var pair in collection.Where(pair => pair.Value != null))
- {
- _dictionary.Add(pair.Key, pair.Value);
- }
- }
-
- ///
- /// Initializes a new instance of the class
- /// that is empty, has the specified capacity, and uses the default comparer for the key type.
- ///
- /// The initial number of elements that the can contain.
- /// is less than 0.
- ///
- public DataDictionary(int capacity)
- {
- _dictionary = new Dictionary(capacity);
- }
-
- ///
- /// Initializes a new instance of the class
- /// that contains elements copied from the specified ,
- /// has the specified capacity, and uses the specified .
- ///
- /// The initial number of elements that the can contain.
- /// The whose elements are copied
- /// to the new .
- /// The equality comparison implementation to use when comparing keys.
- ///
- /// Since does not store null values,
- /// key/value pairs whose value is will not be copied from .
- ///
- ///
- /// is .
- /// - or -.
- /// is .
- ///
- /// is less than 0.
- ///
- public DataDictionary(int capacity, IEnumerable> collection, IEqualityComparer comparer)
- {
- if (collection == null)
- throw new ArgumentNullException(nameof(collection));
-
- _dictionary = new Dictionary(capacity, comparer);
- foreach (var pair in collection.Where(pair => pair.Value != null))
- {
- _dictionary.Add(pair.Key, pair.Value);
- }
- }
-
- #endregion
-
- #region Public APIs
-
- ///
- public int Count => _dictionary.Count;
-
- ///
- public bool IsEmpty => _dictionary.Count == 0;
-
- ///
- public ICollection Keys => _dictionary.Keys;
-
- ///
- public ICollection Values => _dictionary.Values;
-
- ///
- public TValue? this[TKey key]
- {
- get => _dictionary.TryGetValue(key ?? throw new ArgumentNullException(nameof(key)), out var value) ? value : null;
- set
- {
- if (value != null)
- {
- _dictionary[key] = value;
- }
- else
- {
- _dictionary.Remove(key);
- }
- }
- }
-
- ///
- public void Clear() => _dictionary.Clear();
-
- ///
- public bool ContainsKey(TKey key)
- {
- // _dictionary.ContainsKey will take care of throwing on a null key.
- return _dictionary.ContainsKey(key);
- }
-
- ///
- public TValue? GetOrAdd(TKey key, TValue value)
- {
- // _dictionary.TryGetValue will take care of throwing on a null key.
- if (_dictionary.TryGetValue(key, out var result))
- return result;
-
- if (value == null)
- return null;
-
- _dictionary.Add(key, value);
- return value;
- }
-
- ///
- public bool Remove(TKey key)
- {
- // _dictionary.Remove will take care of throwing on a null key.
- return _dictionary.Remove(key);
- }
-
- ///
- public bool TryAdd(TKey key, TValue value)
- {
- // _dictionary.ContainsKey will take care of throwing on a null key.
- if (_dictionary.ContainsKey(key))
- return false;
-
- if (value != null)
- _dictionary.Add(key, value);
-
- return true;
- }
-
- ///
- public bool TryGetValue(TKey key, out TValue value) => _dictionary.TryGetValue(key, out value);
-
- ///
- public bool TryRemove(TKey key, out TValue value)
- {
- // TryGetValue will take care of throwing on a null key.
- if (!_dictionary.TryGetValue(key, out value))
- return false;
-
- _dictionary.Remove(key);
- return true;
- }
-
- ///
- public bool TryUpdate(TKey key, TValue newValue, TValue comparisonValue)
- {
- // TryGetValue will take care of throwing on a null key.
- if (!_dictionary.TryGetValue(key, out var value))
- return false;
-
- if (value != comparisonValue)
- return false;
-
- _dictionary[key] = newValue;
- return true;
- }
-
- #endregion
-
- #region Implementation of IDictionary
-
- ///
- void IDictionary.Add(TKey key, TValue value)
- {
- // Validating the key seems redundant, because both Add and Remove
- // will throw on a null key.
- // This way, though, the code path on null key does not depend on value.
- // Without this validation, there should be two unit tests for null key,
- // one with a null value and one with a non-null value,
- // which makes no sense.
- if (key == null)
- throw new ArgumentNullException(nameof(key));
-
- if (value != null)
- {
- _dictionary.Add(key, value);
- }
- else
- {
- _dictionary.Remove(key);
- }
- }
-
- #endregion
-
- #region Implementation of IReadOnlyDictionary
-
- ///
- IEnumerable IReadOnlyDictionary.Keys => _dictionary.Keys;
-
- ///
- IEnumerable IReadOnlyDictionary.Values => _dictionary.Values;
-
- #endregion
-
- #region Implementation of ICollection>
-
- ///
- ///
- /// This property is always for a .
- ///
- bool ICollection>.IsReadOnly => false;
-
- ///
- void ICollection>.Add(KeyValuePair item)
- {
- if (item.Value != null)
- {
- ((ICollection>)_dictionary).Add(item);
- }
- else
- {
- _dictionary.Remove(item.Key);
- }
- }
-
- ///
- bool ICollection>.Contains(KeyValuePair item)
- => ((ICollection>)_dictionary).Contains(item);
-
- ///
- void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex)
- => ((ICollection>)_dictionary).CopyTo(array, arrayIndex);
-
- ///
- bool ICollection>.Remove(KeyValuePair item)
- => ((ICollection>) _dictionary).Remove(item);
-
- #endregion
-
- #region Implementation of IEnumerable>
-
- ///
- IEnumerator> IEnumerable>.GetEnumerator() => _dictionary.GetEnumerator();
-
- #endregion
-
- #region Implementation of IEnumerable
-
- ///
- IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)_dictionary).GetEnumerator();
-
- #endregion
- }
+ ///
+ public DataDictionary() => this._dictionary = new Dictionary();
+
+ ///
+ /// Initializes a new instance of the class
+ /// that contains elements copied from the specified ,
+ /// has the default initial capacity, and uses the default comparer for .
+ ///
+ /// The whose elements are copied
+ /// to the new .
+ /// is .
+ ///
+ /// Since does not store null values,
+ /// key/value pairs whose value is will not be copied from .
+ ///
+ ///
+ public DataDictionary(IEnumerable> collection) {
+ if(collection == null) {
+ throw new ArgumentNullException(nameof(collection));
+ }
+
+ this._dictionary = new Dictionary();
+ foreach(KeyValuePair pair in collection.Where(pair => pair.Value != null)) {
+ this._dictionary.Add(pair.Key, pair.Value);
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the class
+ /// that is empty, has the default capacity, and uses the specified .
+ ///
+ /// The equality comparison implementation to use when comparing keys.
+ /// is .
+ ///
+ public DataDictionary(IEqualityComparer comparer) => this._dictionary = new Dictionary(comparer);
+
+ ///
+ /// Initializes a new instance of the class
+ /// that contains elements copied from the specified ,
+ /// has the default initial capacity, and uses the specified .
+ ///
+ /// The whose elements are copied
+ /// to the new .
+ /// The equality comparison implementation to use when comparing keys.
+ ///
+ /// Since does not store null values,
+ /// key/value pairs whose value is will not be copied from .
+ ///
+ ///
+ /// is .
+ /// - or -.
+ /// is .
+ ///
+ ///
+ public DataDictionary(IEnumerable> collection, IEqualityComparer comparer) {
+ if(collection == null) {
+ throw new ArgumentNullException(nameof(collection));
+ }
+
+ this._dictionary = new Dictionary(comparer);
+ foreach(KeyValuePair pair in collection.Where(pair => pair.Value != null)) {
+ this._dictionary.Add(pair.Key, pair.Value);
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the class
+ /// that is empty, has the specified capacity, and uses the default comparer for the key type.
+ ///
+ /// The initial number of elements that the can contain.
+ /// is less than 0.
+ ///
+ public DataDictionary(Int32 capacity) => this._dictionary = new Dictionary(capacity);
+
+ ///
+ /// Initializes a new instance of the class
+ /// that contains elements copied from the specified ,
+ /// has the specified capacity, and uses the specified .
+ ///
+ /// The initial number of elements that the can contain.
+ /// The whose elements are copied
+ /// to the new .
+ /// The equality comparison implementation to use when comparing keys.
+ ///
+ /// Since does not store null values,
+ /// key/value pairs whose value is will not be copied from .
+ ///
+ ///
+ /// is .
+ /// - or -.
+ /// is .
+ ///
+ /// is less than 0.
+ ///
+ public DataDictionary(Int32 capacity, IEnumerable> collection, IEqualityComparer comparer) {
+ if(collection == null) {
+ throw new ArgumentNullException(nameof(collection));
+ }
+
+ this._dictionary = new Dictionary(capacity, comparer);
+ foreach(KeyValuePair pair in collection.Where(pair => pair.Value != null)) {
+ this._dictionary.Add(pair.Key, pair.Value);
+ }
+ }
+
+ #endregion
+
+ #region Public APIs
+
+ ///
+ public Int32 Count => this._dictionary.Count;
+
+ ///
+ public Boolean IsEmpty => this._dictionary.Count == 0;
+
+ ///
+ public ICollection Keys => this._dictionary.Keys;
+
+ ///
+ public ICollection Values => this._dictionary.Values;
+
+ ///
+ public TValue this[TKey key] {
+ get => this._dictionary.TryGetValue(key ?? throw new ArgumentNullException(nameof(key)), out TValue value) ? value : null;
+ set {
+ if(value != null) {
+ this._dictionary[key] = value;
+ } else {
+ _ = this._dictionary.Remove(key);
+ }
+ }
+ }
+
+ ///
+ public void Clear() => this._dictionary.Clear();
+
+ ///
+ public Boolean ContainsKey(TKey key) =>
+ // _dictionary.ContainsKey will take care of throwing on a null key.
+ this._dictionary.ContainsKey(key);
+
+ ///
+ public TValue GetOrAdd(TKey key, TValue value) {
+ // _dictionary.TryGetValue will take care of throwing on a null key.
+ if(this._dictionary.TryGetValue(key, out TValue result)) {
+ return result;
+ }
+
+ if(value == null) {
+ return null;
+ }
+
+ this._dictionary.Add(key, value);
+ return value;
+ }
+
+ ///
+ public Boolean Remove(TKey key) =>
+ // _dictionary.Remove will take care of throwing on a null key.
+ this._dictionary.Remove(key);
+
+ ///
+ public Boolean TryAdd(TKey key, TValue value) {
+ // _dictionary.ContainsKey will take care of throwing on a null key.
+ if(this._dictionary.ContainsKey(key)) {
+ return false;
+ }
+
+ if(value != null) {
+ this._dictionary.Add(key, value);
+ }
+
+ return true;
+ }
+
+ ///
+ public Boolean TryGetValue(TKey key, out TValue value) => this._dictionary.TryGetValue(key, out value);
+
+ ///
+ public Boolean TryRemove(TKey key, out TValue value) {
+ // TryGetValue will take care of throwing on a null key.
+ if(!this._dictionary.TryGetValue(key, out value)) {
+ return false;
+ }
+
+ _ = this._dictionary.Remove(key);
+ return true;
+ }
+
+ ///
+ public Boolean TryUpdate(TKey key, TValue newValue, TValue comparisonValue) {
+ // TryGetValue will take care of throwing on a null key.
+ if(!this._dictionary.TryGetValue(key, out TValue value)) {
+ return false;
+ }
+
+ if(value != comparisonValue) {
+ return false;
+ }
+
+ this._dictionary[key] = newValue;
+ return true;
+ }
+
+ #endregion
+
+ #region Implementation of IDictionary
+
+ ///
+ void IDictionary.Add(TKey key, TValue value) {
+ // Validating the key seems redundant, because both Add and Remove
+ // will throw on a null key.
+ // This way, though, the code path on null key does not depend on value.
+ // Without this validation, there should be two unit tests for null key,
+ // one with a null value and one with a non-null value,
+ // which makes no sense.
+ if(key == null) {
+ throw new ArgumentNullException(nameof(key));
+ }
+
+ if(value != null) {
+ this._dictionary.Add(key, value);
+ } else {
+ _ = this._dictionary.Remove(key);
+ }
+ }
+
+ #endregion
+
+ #region Implementation of IReadOnlyDictionary
+
+ ///
+ IEnumerable IReadOnlyDictionary.Keys => this._dictionary.Keys;
+
+ ///
+ IEnumerable IReadOnlyDictionary.Values => this._dictionary.Values;
+
+ #endregion
+
+ #region Implementation of ICollection>
+
+ ///
+ ///
+ /// This property is always for a .
+ ///
+ Boolean ICollection>.IsReadOnly => false;
+
+ ///
+ void ICollection>.Add(KeyValuePair item) {
+ if(item.Value != null) {
+ ((ICollection>)this._dictionary).Add(item);
+ } else {
+ _ = this._dictionary.Remove(item.Key);
+ }
+ }
+
+ ///
+ Boolean ICollection>.Contains(KeyValuePair item) => ((ICollection>)this._dictionary).Contains(item);
+
+ ///
+ void ICollection>.CopyTo(KeyValuePair[] array, Int32 arrayIndex) => ((ICollection>)this._dictionary).CopyTo(array, arrayIndex);
+
+ ///
+ Boolean ICollection>.Remove(KeyValuePair item) => ((ICollection>)this._dictionary).Remove(item);
+
+ #endregion
+
+ #region Implementation of IEnumerable>
+
+ ///
+ IEnumerator> IEnumerable>.GetEnumerator() => this._dictionary.GetEnumerator();
+
+ #endregion
+
+ #region Implementation of IEnumerable
+
+ ///
+ IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)this._dictionary).GetEnumerator();
+
+ #endregion
+ }
}
diff --git a/Swan.Lite/Collections/DisposableComponentCollection`1.cs b/Swan.Lite/Collections/DisposableComponentCollection`1.cs
index 4f42fa6..60c2e48 100644
--- a/Swan.Lite/Collections/DisposableComponentCollection`1.cs
+++ b/Swan.Lite/Collections/DisposableComponentCollection`1.cs
@@ -1,49 +1,46 @@
using System;
-namespace Swan.Collections
-{
+namespace Swan.Collections {
+ ///
+ /// Implements a collection of components that automatically disposes each component
+ /// implementing .
+ /// Each component in the collection may be given a unique name for later retrieval.
+ ///
+ /// The type of components in the collection.
+ ///
+ ///
+ public class DisposableComponentCollection : ComponentCollection, IDisposable {
///
- /// Implements a collection of components that automatically disposes each component
- /// implementing .
- /// Each component in the collection may be given a unique name for later retrieval.
+ /// Finalizes an instance of the class.
///
- /// The type of components in the collection.
- ///
- ///
- public class DisposableComponentCollection : ComponentCollection, IDisposable
- {
- ///
- /// Finalizes an instance of the class.
- ///
- ~DisposableComponentCollection()
- {
- Dispose(false);
- }
-
- ///
- /// Releases unmanaged and - optionally - managed resources.
- ///
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- ///
- /// Releases unmanaged and - optionally - managed resources.
- ///
- ///
- /// to release both managed and unmanaged resources; to release only unmanaged resources.
- ///
- protected virtual void Dispose(bool disposing)
- {
- if (!disposing) return;
-
- foreach (var component in this)
- {
- if (component is IDisposable disposable)
- disposable.Dispose();
- }
- }
- }
+ ~DisposableComponentCollection() {
+ this.Dispose(false);
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources.
+ ///
+ public void Dispose() {
+ this.Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources.
+ ///
+ ///
+ /// to release both managed and unmanaged resources; to release only unmanaged resources.
+ ///
+ protected virtual void Dispose(Boolean disposing) {
+ if(!disposing) {
+ return;
+ }
+
+ foreach(T component in this) {
+ if(component is IDisposable disposable) {
+ disposable.Dispose();
+ }
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/Swan.Lite/Collections/IComponentCollection`1.cs b/Swan.Lite/Collections/IComponentCollection`1.cs
index cf16760..5d44964 100644
--- a/Swan.Lite/Collections/IComponentCollection`1.cs
+++ b/Swan.Lite/Collections/IComponentCollection`1.cs
@@ -1,54 +1,56 @@
using System;
using System.Collections.Generic;
-namespace Swan.Collections
-{
+namespace Swan.Collections {
+ ///
+ /// Represents a collection of components.
+ /// Each component in the collection may be given a unique name for later retrieval.
+ ///
+ /// The type of components in the collection.
+ public interface IComponentCollection : IReadOnlyList {
///
- /// Represents a collection of components.
- /// Each component in the collection may be given a unique name for later retrieval.
+ /// Gets an interface representing the named components.
///
- /// The type of components in the collection.
- public interface IComponentCollection : IReadOnlyList
- {
- ///
- /// Gets an interface representing the named components.
- ///
- ///
- /// The named components.
- ///
- IReadOnlyDictionary Named { get; }
-
- ///
- /// Gets an interface representing all components
- /// associated with safe names.
- /// The safe name of a component is never .
- /// If a component's unique name if , its safe name
- /// will be some non- string somehow identifying it.
- /// Note that safe names are not necessarily unique.
- ///
- ///
- /// A list of s, each containing a safe name and a component.
- ///
- IReadOnlyList<(string SafeName, T Component)> WithSafeNames { get; }
-
- ///
- /// Gets the component with the specified name.
- ///
- ///
- /// The component.
- ///
- /// The name.
- /// The component with the specified .
- /// is null.
- /// The property is retrieved and is not found.
- T this[string name] { get; }
-
- ///
- /// Adds a component to the collection,
- /// giving it the specified if it is not .
- ///
- /// The name given to the module, or .
- /// The component.
- void Add(string name, T component);
- }
+ ///
+ /// The named components.
+ ///
+ IReadOnlyDictionary Named {
+ get;
+ }
+
+ ///
+ /// Gets an interface representing all components
+ /// associated with safe names.
+ /// The safe name of a component is never .
+ /// If a component's unique name if , its safe name
+ /// will be some non- string somehow identifying it.
+ /// Note that safe names are not necessarily unique.
+ ///
+ ///
+ /// A list of s, each containing a safe name and a component.
+ ///
+ IReadOnlyList<(String SafeName, T Component)> WithSafeNames {
+ get;
+ }
+
+ ///
+ /// Gets the component with the specified name.
+ ///
+ ///
+ /// The component.
+ ///
+ /// The name.
+ /// The component with the specified .
+ /// is null.
+ /// The property is retrieved and is not found.
+ T this[String name] { get; }
+
+ ///
+ /// Adds a component to the collection,
+ /// giving it the specified if it is not .
+ ///
+ /// The name given to the module, or .
+ /// The component.
+ void Add(String name, T component);
+ }
}
\ No newline at end of file
diff --git a/Swan.Lite/Collections/IDataDictionary`2.cs b/Swan.Lite/Collections/IDataDictionary`2.cs
index 800a7b0..e5f4885 100644
--- a/Swan.Lite/Collections/IDataDictionary`2.cs
+++ b/Swan.Lite/Collections/IDataDictionary`2.cs
@@ -1,34 +1,32 @@
using System;
using System.Collections.Generic;
-namespace Swan.Collections
-{
+namespace Swan.Collections {
+ ///
+ /// Represents a generic collection of key/value pairs that does not store
+ /// null values.
+ ///
+ /// The type of keys in the dictionary. This must be a reference type.
+ /// The type of values in the dictionary. This must be a reference type.
+ public interface IDataDictionary : IDictionary, IReadOnlyDictionary where TKey : class where TValue : class {
///
- /// Represents a generic collection of key/value pairs that does not store
- /// null values.
+ /// Gets a value that indicates whether the is empty.
///
- /// The type of keys in the dictionary. This must be a reference type.
- /// The type of values in the dictionary. This must be a reference type.
- public interface IDataDictionary : IDictionary, IReadOnlyDictionary
- where TKey : class
- where TValue : class
- {
- ///
- /// Gets a value that indicates whether the is empty.
- ///
- ///
- /// if the is empty; otherwise, .
- ///
- bool IsEmpty { get; }
-
- ///
- /// Attempts to remove and return the value that has the specified key from the .
- ///
- /// The key of the element to remove and return.
- /// When this method returns, the value removed from the ,
- /// if the key is found; otherwise, . This parameter is passed uninitialized.
- /// if the value was removed successfully; otherwise, .
- /// is .
- bool TryRemove(TKey key, out TValue value);
- }
+ ///
+ /// if the is empty; otherwise, .
+ ///
+ Boolean IsEmpty {
+ get;
+ }
+
+ ///
+ /// Attempts to remove and return the value that has the specified key from the .
+ ///
+ /// The key of the element to remove and return.
+ /// When this method returns, the value removed from the ,
+ /// if the key is found; otherwise, . This parameter is passed uninitialized.
+ /// if the value was removed successfully; otherwise, .
+ /// is .
+ Boolean TryRemove(TKey key, out TValue value);
+ }
}
diff --git a/Swan.Lite/Configuration/ConfiguredObject.cs b/Swan.Lite/Configuration/ConfiguredObject.cs
index 1855c81..57702a8 100644
--- a/Swan.Lite/Configuration/ConfiguredObject.cs
+++ b/Swan.Lite/Configuration/ConfiguredObject.cs
@@ -1,77 +1,70 @@
using System;
-namespace Swan.Configuration
-{
+namespace Swan.Configuration {
+ ///
+ /// Base class for objects whose configuration may be locked,
+ /// thus becoming read-only, at a certain moment in their lifetime.
+ ///
+ public abstract class ConfiguredObject {
+ private readonly Object _syncRoot = new Object();
+ private Boolean _configurationLocked;
+
///
- /// Base class for objects whose configuration may be locked,
- /// thus becoming read-only, at a certain moment in their lifetime.
+ /// Gets a value indicating whether s configuration has already been locked
+ /// and has therefore become read-only.
///
- public abstract class ConfiguredObject
- {
- private readonly object _syncRoot = new object();
- private bool _configurationLocked;
-
- ///
- /// Gets a value indicating whether s configuration has already been locked
- /// and has therefore become read-only.
- ///
- ///
- /// if the configuration is locked; otherwise, .
- ///
- ///
- protected bool ConfigurationLocked
- {
- get
- {
- lock (_syncRoot)
- {
- return _configurationLocked;
- }
- }
- }
-
- ///
- /// Locks this instance's configuration, preventing further modifications.
- ///
- ///
- /// Configuration locking must be enforced by derived classes
- /// by calling at the start
- /// of methods and property setters that could change the object's
- /// configuration.
- /// Immediately before locking the configuration, this method calls
- /// as a last chance to validate configuration data, and to lock the configuration of contained objects.
- ///
- ///
- protected void LockConfiguration()
- {
- lock (_syncRoot)
- {
- if (_configurationLocked)
- return;
-
- OnBeforeLockConfiguration();
- _configurationLocked = true;
- }
- }
-
- ///
- /// Called immediately before locking the configuration.
- ///
- ///
- protected virtual void OnBeforeLockConfiguration()
- {
- }
-
- ///
- /// Checks whether a module's configuration has become read-only
- /// and, if so, throws an .
- ///
- /// The configuration is locked.
- ///
- protected void EnsureConfigurationNotLocked()
- {
- if (ConfigurationLocked)
- throw new InvalidOperationException($"Configuration of this {GetType().Name} instance is locked.");
- }
- }
+ ///
+ /// if the configuration is locked; otherwise, .
+ ///
+ ///
+ protected Boolean ConfigurationLocked {
+ get {
+ lock(this._syncRoot) {
+ return this._configurationLocked;
+ }
+ }
+ }
+
+ ///
+ /// Locks this instance's configuration, preventing further modifications.
+ ///
+ ///
+ /// Configuration locking must be enforced by derived classes
+ /// by calling at the start
+ /// of methods and property setters that could change the object's
+ /// configuration.
+ /// Immediately before locking the configuration, this method calls
+ /// as a last chance to validate configuration data, and to lock the configuration of contained objects.
+ ///
+ ///
+ protected void LockConfiguration() {
+ lock(this._syncRoot) {
+ if(this._configurationLocked) {
+ return;
+ }
+
+ this.OnBeforeLockConfiguration();
+ this._configurationLocked = true;
+ }
+ }
+
+ ///
+ /// Called immediately before locking the configuration.
+ ///
+ ///
+ protected virtual void OnBeforeLockConfiguration() {
+ }
+
+ ///
+ /// Checks whether a module's configuration has become read-only
+ /// and, if so, throws an .
+ ///
+ /// The configuration is locked.
+ ///
+ protected void EnsureConfigurationNotLocked() {
+ if(this.ConfigurationLocked) {
+ throw new InvalidOperationException($"Configuration of this {this.GetType().Name} instance is locked.");
+ }
+ }
+ }
}
diff --git a/Swan.Lite/Configuration/PropertyDisplayAttribute.cs b/Swan.Lite/Configuration/PropertyDisplayAttribute.cs
index 2f45af5..c5e9d97 100644
--- a/Swan.Lite/Configuration/PropertyDisplayAttribute.cs
+++ b/Swan.Lite/Configuration/PropertyDisplayAttribute.cs
@@ -1,54 +1,62 @@
using System;
-namespace Swan.Configuration
-{
+namespace Swan.Configuration {
+ ///
+ /// An attribute used to include additional information to a Property for serialization.
+ ///
+ /// Previously we used DisplayAttribute from DataAnnotation.
+ ///
+ ///
+ [AttributeUsage(AttributeTargets.Property)]
+ public sealed class PropertyDisplayAttribute : Attribute {
///
- /// An attribute used to include additional information to a Property for serialization.
- ///
- /// Previously we used DisplayAttribute from DataAnnotation.
+ /// Gets or sets the name.
///
- ///
- [AttributeUsage(AttributeTargets.Property)]
- public sealed class PropertyDisplayAttribute : Attribute
- {
- ///
- /// Gets or sets the name.
- ///
- ///
- /// The name.
- ///
- public string Name { get; set; }
-
- ///
- /// Gets or sets the description.
- ///
- ///
- /// The description.
- ///
- public string Description { get; set; }
-
- ///
- /// Gets or sets the name of the group.
- ///
- ///
- /// The name of the group.
- ///
- public string GroupName { get; set; }
-
- ///
- /// Gets or sets the default value.
- ///
- ///
- /// The default value.
- ///
- public object DefaultValue { get; set; }
-
- ///
- /// Gets or sets the format string to call with method ToString.
- ///
- ///
- /// The format.
- ///
- public string Format { get; set; }
- }
+ ///
+ /// The name.
+ ///
+ public String Name {
+ get; set;
+ }
+
+ ///
+ /// Gets or sets the description.
+ ///
+ ///
+ /// The description.
+ ///
+ public String Description {
+ get; set;
+ }
+
+ ///
+ /// Gets or sets the name of the group.
+ ///
+ ///
+ /// The name of the group.
+ ///
+ public String GroupName {
+ get; set;
+ }
+
+ ///
+ /// Gets or sets the default value.
+ ///
+ ///
+ /// The default value.
+ ///
+ public Object DefaultValue {
+ get; set;
+ }
+
+ ///
+ /// Gets or sets the format string to call with method ToString.
+ ///
+ ///
+ /// The format.
+ ///
+ public String Format {
+ get; set;
+ }
+ }
}
diff --git a/Swan.Lite/Configuration/SettingsProvider.cs b/Swan.Lite/Configuration/SettingsProvider.cs
index 6e1020b..2ba5e5a 100644
--- a/Swan.Lite/Configuration/SettingsProvider.cs
+++ b/Swan.Lite/Configuration/SettingsProvider.cs
@@ -41,10 +41,9 @@ namespace Swan.Configuration
///
///
/// The type of settings model.
- public sealed class SettingsProvider
- : SingletonBase>
+ public sealed class SettingsProvider : SingletonBase>
{
- private readonly object _syncRoot = new object();
+ private readonly Object _syncRoot = new Object();
private T _global;
@@ -55,8 +54,7 @@ namespace Swan.Configuration
///
/// The configuration file path.
///
- public string ConfigurationFilePath { get; set; } =
- Path.Combine(SwanRuntime.EntryAssemblyDirectory, "appsettings.json");
+ public String ConfigurationFilePath { get; set; } = Path.Combine(SwanRuntime.EntryAssemblyDirectory, "appsettings.json");
///
/// Gets the global settings object.
@@ -68,12 +66,13 @@ namespace Swan.Configuration
{
get
{
- lock (_syncRoot)
+ lock (this._syncRoot)
{
- if (Equals(_global, default(T)))
- ReloadGlobalSettings();
-
- return _global;
+ if (Equals(this._global, default(T)!)) {
+ this.ReloadGlobalSettings();
+ }
+
+ return this._global;
}
}
}
@@ -83,20 +82,21 @@ namespace Swan.Configuration
///
public void ReloadGlobalSettings()
{
- if (File.Exists(ConfigurationFilePath) == false || File.ReadAllText(ConfigurationFilePath).Length == 0)
- {
- ResetGlobalSettings();
+ if (File.Exists(this.ConfigurationFilePath) == false || File.ReadAllText(this.ConfigurationFilePath).Length == 0)
+ {
+ this.ResetGlobalSettings();
return;
}
- lock (_syncRoot)
- _global = Json.Deserialize(File.ReadAllText(ConfigurationFilePath));
- }
+ lock (this._syncRoot) {
+ this._global = Json.Deserialize(File.ReadAllText(this.ConfigurationFilePath));
+ }
+ }
///
/// Persists the global settings.
///
- public void PersistGlobalSettings() => File.WriteAllText(ConfigurationFilePath, Json.Serialize(Global, true));
+ public void PersistGlobalSettings() => File.WriteAllText(this.ConfigurationFilePath, Json.Serialize(this.Global, true));
///
/// Updates settings from list.
@@ -106,29 +106,34 @@ namespace Swan.Configuration
/// A list of settings of type ref="ExtendedPropertyInfo".
///
/// propertyList.
- public List RefreshFromList(List> propertyList)
+ public List RefreshFromList(List> propertyList)
{
- if (propertyList == null)
- throw new ArgumentNullException(nameof(propertyList));
+ if (propertyList == null) {
+ throw new ArgumentNullException(nameof(propertyList));
+ }
+
+ List changedSettings = new List();
+ IEnumerable globalProps = PropertyTypeCache.DefaultCache.Value.RetrieveAllProperties();
- var changedSettings = new List();
- var globalProps = PropertyTypeCache.DefaultCache.Value.RetrieveAllProperties();
+ foreach (ExtendedPropertyInfo property in propertyList)
+ {
+ PropertyInfo propertyInfo = globalProps.FirstOrDefault(x => x.Name == property.Property);
- foreach (var property in propertyList)
- {
- var propertyInfo = globalProps.FirstOrDefault(x => x.Name == property.Property);
+ if (propertyInfo == null) {
+ continue;
+ }
+
+ Object originalValue = propertyInfo.GetValue(this.Global);
+ Boolean isChanged = propertyInfo.PropertyType.IsArray
+ ? property.Value is IEnumerable enumerable && propertyInfo.TrySetArray(enumerable.Cast
/// A List of ExtendedPropertyInfo of the type T.
- public List>? GetList()
- {
- var jsonData = Json.Deserialize(Json.Serialize(Global)) as Dictionary;
+ public List> GetList()
+ {
+ Dictionary jsonData = Json.Deserialize(Json.Serialize(this.Global)) as Dictionary;
return jsonData?.Keys
.Select(p => new ExtendedPropertyInfo(p) { Value = jsonData[p] })
@@ -152,26 +157,27 @@ namespace Swan.Configuration
///
public void ResetGlobalSettings()
{
- lock (_syncRoot)
- _global = Activator.CreateInstance();
-
- PersistGlobalSettings();
+ lock (this._syncRoot) {
+ this._global = Activator.CreateInstance();
+ }
+
+ this.PersistGlobalSettings();
}
- private bool SetValue(object property, object originalValue, PropertyInfo propertyInfo)
+ private Boolean SetValue(Object property, Object originalValue, PropertyInfo propertyInfo)
{
switch (property)
{
case null when originalValue == null:
break;
case null:
- propertyInfo.SetValue(Global, null);
+ propertyInfo.SetValue(this.Global, null);
return true;
default:
- if (propertyInfo.PropertyType.TryParseBasicType(property, out var propertyValue) &&
+ if (propertyInfo.PropertyType.TryParseBasicType(property, out Object propertyValue) &&
!propertyValue.Equals(originalValue))
{
- propertyInfo.SetValue(Global, propertyValue);
+ propertyInfo.SetValue(this.Global, propertyValue);
return true;
}
diff --git a/Swan.Lite/Cryptography/Hasher.cs b/Swan.Lite/Cryptography/Hasher.cs
index a78adac..5dfc677 100644
--- a/Swan.Lite/Cryptography/Hasher.cs
+++ b/Swan.Lite/Cryptography/Hasher.cs
@@ -3,122 +3,123 @@ using System.IO;
using System.Security.Cryptography;
using System.Text;
-namespace Swan.Cryptography
-{
+namespace Swan.Cryptography {
+ ///
+ /// Use this class to compute a hash in MD4, SHA1, SHA256 or SHA512.
+ ///
+ public static class Hasher {
+ private static readonly Lazy Md5Hasher = new Lazy(MD5.Create, true);
+ private static readonly Lazy SHA1Hasher = new Lazy(SHA1.Create, true);
+ private static readonly Lazy SHA256Hasher = new Lazy(SHA256.Create, true);
+ private static readonly Lazy SHA512Hasher = new Lazy(SHA512.Create, true);
+
///
- /// Use this class to compute a hash in MD4, SHA1, SHA256 or SHA512.
+ /// Computes the MD5 hash of the given stream.
+ /// Do not use for large streams as this reads ALL bytes at once.
///
- public static class Hasher
- {
- private static readonly Lazy Md5Hasher = new Lazy(MD5.Create, true);
- private static readonly Lazy SHA1Hasher = new Lazy(SHA1.Create, true);
- private static readonly Lazy SHA256Hasher = new Lazy(SHA256.Create, true);
- private static readonly Lazy SHA512Hasher = new Lazy(SHA512.Create, true);
-
- ///
- /// Computes the MD5 hash of the given stream.
- /// Do not use for large streams as this reads ALL bytes at once.
- ///
- /// The stream.
- /// if set to true [create hasher].
- ///
- /// The computed hash code.
- ///
- /// stream.
- [Obsolete("Use a better hasher.")]
- public static byte[] ComputeMD5(Stream @this, bool createHasher = false)
- {
- if (@this == null)
- throw new ArgumentNullException(nameof(@this));
-
- var md5 = MD5.Create();
- const int bufferSize = 4096;
-
- var readAheadBuffer = new byte[bufferSize];
- var readAheadBytesRead = @this.Read(readAheadBuffer, 0, readAheadBuffer.Length);
-
- do
- {
- var bytesRead = readAheadBytesRead;
- var buffer = readAheadBuffer;
-
- readAheadBuffer = new byte[bufferSize];
- readAheadBytesRead = @this.Read(readAheadBuffer, 0, readAheadBuffer.Length);
-
- if (readAheadBytesRead == 0)
- md5.TransformFinalBlock(buffer, 0, bytesRead);
- else
- md5.TransformBlock(buffer, 0, bytesRead, buffer, 0);
- }
- while (readAheadBytesRead != 0);
-
- return md5.Hash;
- }
-
- ///
- /// Computes the MD5 hash of the given string using UTF8 byte encoding.
- ///
- /// The input string.
- /// if set to true [create hasher].
- /// The computed hash code.
- [Obsolete("Use a better hasher.")]
- public static byte[] ComputeMD5(string value, bool createHasher = false) =>
- ComputeMD5(Encoding.UTF8.GetBytes(value), createHasher);
-
- ///
- /// Computes the MD5 hash of the given byte array.
- ///
- /// The data.
- /// if set to true [create hasher].
- /// The computed hash code.
- [Obsolete("Use a better hasher.")]
- public static byte[] ComputeMD5(byte[] data, bool createHasher = false) =>
- (createHasher ? MD5.Create() : Md5Hasher.Value).ComputeHash(data);
-
- ///
- /// Computes the SHA-1 hash of the given string using UTF8 byte encoding.
- ///
- /// The input string.
- /// if set to true [create hasher].
- ///
- /// The computes a Hash-based Message Authentication Code (HMAC)
- /// using the SHA1 hash function.
- ///
- [Obsolete("Use a better hasher.")]
- public static byte[] ComputeSha1(string @this, bool createHasher = false)
- {
- var inputBytes = Encoding.UTF8.GetBytes(@this);
- return (createHasher ? SHA1.Create() : SHA1Hasher.Value).ComputeHash(inputBytes);
- }
-
- ///
- /// Computes the SHA-256 hash of the given string using UTF8 byte encoding.
- ///
- /// The input string.
- /// if set to true [create hasher].
- ///
- /// The computes a Hash-based Message Authentication Code (HMAC)
- /// by using the SHA256 hash function.
- ///
- public static byte[] ComputeSha256(string value, bool createHasher = false)
- {
- var inputBytes = Encoding.UTF8.GetBytes(value);
- return (createHasher ? SHA256.Create() : SHA256Hasher.Value).ComputeHash(inputBytes);
- }
-
- ///
- /// Computes the SHA-512 hash of the given string using UTF8 byte encoding.
- ///
- /// The input string.
- /// if set to true [create hasher].
- ///
- /// The computes a Hash-based Message Authentication Code (HMAC)
- /// using the SHA512 hash function.
- ///
- public static byte[] ComputeSha512(string value, bool createHasher = false)
- {
- var inputBytes = Encoding.UTF8.GetBytes(value);
- return (createHasher ? SHA512.Create() : SHA512Hasher.Value).ComputeHash(inputBytes);
- }
- }
+ /// The stream.
+ /// if set to true [create hasher].
+ ///
+ /// The computed hash code.
+ ///
+ /// stream.
+ [Obsolete("Use a better hasher.")]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Codequalität", "IDE0067:Objekte verwerfen, bevor Bereich verloren geht", Justification = "")]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Stil", "IDE0045:In bedingten Ausdruck konvertieren", Justification = "")]
+ public static Byte[] ComputeMD5(Stream @this, Boolean createHasher = false) {
+ if(@this == null) {
+ throw new ArgumentNullException(nameof(@this));
+ }
+
+ MD5 md5 = MD5.Create();
+ const Int32 bufferSize = 4096;
+
+ Byte[] readAheadBuffer = new Byte[bufferSize];
+ Int32 readAheadBytesRead = @this.Read(readAheadBuffer, 0, readAheadBuffer.Length);
+
+ do {
+ Int32 bytesRead = readAheadBytesRead;
+ Byte[] buffer = readAheadBuffer;
+
+ readAheadBuffer = new Byte[bufferSize];
+ readAheadBytesRead = @this.Read(readAheadBuffer, 0, readAheadBuffer.Length);
+
+ if(readAheadBytesRead == 0) {
+ _ = md5.TransformFinalBlock(buffer, 0, bytesRead);
+ } else {
+ _ = md5.TransformBlock(buffer, 0, bytesRead, buffer, 0);
+ }
+ }
+ while(readAheadBytesRead != 0);
+
+ return md5.Hash;
+ }
+
+ ///
+ /// Computes the MD5 hash of the given string using UTF8 byte encoding.
+ ///
+ /// The input string.
+ /// if set to true [create hasher].
+ /// The computed hash code.
+ [Obsolete("Use a better hasher.")]
+ public static Byte[] ComputeMD5(String value, Boolean createHasher = false) => ComputeMD5(Encoding.UTF8.GetBytes(value), createHasher);
+
+ ///
+ /// Computes the MD5 hash of the given byte array.
+ ///
+ /// The data.
+ /// if set to true [create hasher].
+ /// The computed hash code.
+ [Obsolete("Use a better hasher.")]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Codequalität", "IDE0067:Objekte verwerfen, bevor Bereich verloren geht", Justification = "")]
+ public static Byte[] ComputeMD5(Byte[] data, Boolean createHasher = false) => (createHasher ? MD5.Create() : Md5Hasher.Value).ComputeHash(data);
+
+ ///
+ /// Computes the SHA-1 hash of the given string using UTF8 byte encoding.
+ ///
+ /// The input string.
+ /// if set to true [create hasher].
+ ///
+ /// The computes a Hash-based Message Authentication Code (HMAC)
+ /// using the SHA1 hash function.
+ ///
+ [Obsolete("Use a better hasher.")]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Codequalität", "IDE0067:Objekte verwerfen, bevor Bereich verloren geht", Justification = "")]
+ public static Byte[] ComputeSha1(String @this, Boolean createHasher = false) {
+ Byte[] inputBytes = Encoding.UTF8.GetBytes(@this);
+ return (createHasher ? SHA1.Create() : SHA1Hasher.Value).ComputeHash(inputBytes);
+ }
+
+
+ ///
+ /// Computes the SHA-256 hash of the given string using UTF8 byte encoding.
+ ///
+ /// The input string.
+ /// if set to true [create hasher].
+ ///
+ /// The computes a Hash-based Message Authentication Code (HMAC)
+ /// by using the SHA256 hash function.
+ ///
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Codequalität", "IDE0067:Objekte verwerfen, bevor Bereich verloren geht", Justification = "")]
+ public static Byte[] ComputeSha256(String value, Boolean createHasher = false) {
+ Byte[] inputBytes = Encoding.UTF8.GetBytes(value);
+ return (createHasher ? SHA256.Create() : SHA256Hasher.Value).ComputeHash(inputBytes);
+ }
+
+
+ ///
+ /// Computes the SHA-512 hash of the given string using UTF8 byte encoding.
+ ///
+ /// The input string.
+ /// if set to true [create hasher].
+ ///
+ /// The computes a Hash-based Message Authentication Code (HMAC)
+ /// using the SHA512 hash function.
+ ///
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Codequalität", "IDE0067:Objekte verwerfen, bevor Bereich verloren geht", Justification = "")]
+ public static Byte[] ComputeSha512(String value, Boolean createHasher = false) {
+ Byte[] inputBytes = Encoding.UTF8.GetBytes(value);
+ return (createHasher ? SHA512.Create() : SHA512Hasher.Value).ComputeHash(inputBytes);
+ }
+ }
}
diff --git a/Swan.Lite/DateTimeSpan.cs b/Swan.Lite/DateTimeSpan.cs
index f512d9c..1c45ff4 100644
--- a/Swan.Lite/DateTimeSpan.cs
+++ b/Swan.Lite/DateTimeSpan.cs
@@ -1,174 +1,165 @@
using System;
-namespace Swan
-{
+namespace Swan {
+ ///
+ /// Represents a struct of DateTimeSpan to compare dates and get in
+ /// separate fields the amount of time between those dates.
+ ///
+ /// Based on https://stackoverflow.com/a/9216404/1096693.
+ ///
+ public struct DateTimeSpan {
///
- /// Represents a struct of DateTimeSpan to compare dates and get in
- /// separate fields the amount of time between those dates.
- ///
- /// Based on https://stackoverflow.com/a/9216404/1096693.
+ /// Initializes a new instance of the struct.
///
- public struct DateTimeSpan
- {
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The years.
- /// The months.
- /// The days.
- /// The hours.
- /// The minutes.
- /// The seconds.
- /// The milliseconds.
- public DateTimeSpan(int years, int months, int days, int hours, int minutes, int seconds, int milliseconds)
- {
- Years = years;
- Months = months;
- Days = days;
- Hours = hours;
- Minutes = minutes;
- Seconds = seconds;
- Milliseconds = milliseconds;
- }
-
- ///
- /// Gets the years.
- ///
- ///
- /// The years.
- ///
- public int Years { get; }
-
- ///
- /// Gets the months.
- ///
- ///
- /// The months.
- ///
- public int Months { get; }
-
- ///
- /// Gets the days.
- ///
- ///
- /// The days.
- ///
- public int Days { get; }
-
- ///
- /// Gets the hours.
- ///
- ///
- /// The hours.
- ///
- public int Hours { get; }
-
- ///
- /// Gets the minutes.
- ///
- ///
- /// The minutes.
- ///
- public int Minutes { get; }
-
- ///
- /// Gets the seconds.
- ///
- ///
- /// The seconds.
- ///
- public int Seconds { get; }
-
- ///
- /// Gets the milliseconds.
- ///
- ///
- /// The milliseconds.
- ///
- public int Milliseconds { get; }
-
- internal static DateTimeSpan CompareDates(DateTime date1, DateTime date2)
- {
- if (date2 < date1)
- {
- var sub = date1;
- date1 = date2;
- date2 = sub;
- }
-
- var current = date1;
- var years = 0;
- var months = 0;
- var days = 0;
-
- var phase = Phase.Years;
- var span = new DateTimeSpan();
- var officialDay = current.Day;
-
- while (phase != Phase.Done)
- {
- switch (phase)
- {
- case Phase.Years:
- if (current.AddYears(years + 1) > date2)
- {
- phase = Phase.Months;
- current = current.AddYears(years);
- }
- else
- {
- years++;
- }
-
- break;
- case Phase.Months:
- if (current.AddMonths(months + 1) > date2)
- {
- phase = Phase.Days;
- current = current.AddMonths(months);
- if (current.Day < officialDay &&
- officialDay <= DateTime.DaysInMonth(current.Year, current.Month))
- current = current.AddDays(officialDay - current.Day);
- }
- else
- {
- months++;
- }
-
- break;
- case Phase.Days:
- if (current.AddDays(days + 1) > date2)
- {
- current = current.AddDays(days);
- var timespan = date2 - current;
- span = new DateTimeSpan(
- years,
- months,
- days,
- timespan.Hours,
- timespan.Minutes,
- timespan.Seconds,
- timespan.Milliseconds);
- phase = Phase.Done;
- }
- else
- {
- days++;
- }
-
- break;
- }
- }
-
- return span;
- }
-
- private enum Phase
- {
- Years,
- Months,
- Days,
- Done,
- }
- }
+ /// The years.
+ /// The months.
+ /// The days.
+ /// The hours.
+ /// The minutes.
+ /// The seconds.
+ /// The milliseconds.
+ public DateTimeSpan(Int32 years, Int32 months, Int32 days, Int32 hours, Int32 minutes, Int32 seconds, Int32 milliseconds) {
+ this.Years = years;
+ this.Months = months;
+ this.Days = days;
+ this.Hours = hours;
+ this.Minutes = minutes;
+ this.Seconds = seconds;
+ this.Milliseconds = milliseconds;
+ }
+
+ ///
+ /// Gets the years.
+ ///
+ ///
+ /// The years.
+ ///
+ public Int32 Years {
+ get;
+ }
+
+ ///
+ /// Gets the months.
+ ///
+ ///
+ /// The months.
+ ///
+ public Int32 Months {
+ get;
+ }
+
+ ///
+ /// Gets the days.
+ ///
+ ///
+ /// The days.
+ ///
+ public Int32 Days {
+ get;
+ }
+
+ ///
+ /// Gets the hours.
+ ///
+ ///
+ /// The hours.
+ ///
+ public Int32 Hours {
+ get;
+ }
+
+ ///
+ /// Gets the minutes.
+ ///
+ ///
+ /// The minutes.
+ ///
+ public Int32 Minutes {
+ get;
+ }
+
+ ///
+ /// Gets the seconds.
+ ///
+ ///
+ /// The seconds.
+ ///
+ public Int32 Seconds {
+ get;
+ }
+
+ ///
+ /// Gets the milliseconds.
+ ///
+ ///
+ /// The milliseconds.
+ ///
+ public Int32 Milliseconds {
+ get;
+ }
+
+ internal static DateTimeSpan CompareDates(DateTime date1, DateTime date2) {
+ if(date2 < date1) {
+ DateTime sub = date1;
+ date1 = date2;
+ date2 = sub;
+ }
+
+ DateTime current = date1;
+ Int32 years = 0;
+ Int32 months = 0;
+ Int32 days = 0;
+
+ Phase phase = Phase.Years;
+ DateTimeSpan span = new DateTimeSpan();
+ Int32 officialDay = current.Day;
+
+ while(phase != Phase.Done) {
+ switch(phase) {
+ case Phase.Years:
+ if(current.AddYears(years + 1) > date2) {
+ phase = Phase.Months;
+ current = current.AddYears(years);
+ } else {
+ years++;
+ }
+
+ break;
+ case Phase.Months:
+ if(current.AddMonths(months + 1) > date2) {
+ phase = Phase.Days;
+ current = current.AddMonths(months);
+ if(current.Day < officialDay &&
+ officialDay <= DateTime.DaysInMonth(current.Year, current.Month)) {
+ current = current.AddDays(officialDay - current.Day);
+ }
+ } else {
+ months++;
+ }
+
+ break;
+ case Phase.Days:
+ if(current.AddDays(days + 1) > date2) {
+ current = current.AddDays(days);
+ TimeSpan timespan = date2 - current;
+ span = new DateTimeSpan(years, months, days, timespan.Hours, timespan.Minutes, timespan.Seconds, timespan.Milliseconds);
+ phase = Phase.Done;
+ } else {
+ days++;
+ }
+
+ break;
+ }
+ }
+
+ return span;
+ }
+
+ private enum Phase {
+ Years,
+ Months,
+ Days,
+ Done,
+ }
+ }
}
\ No newline at end of file
diff --git a/Swan.Lite/Definitions.Types.cs b/Swan.Lite/Definitions.Types.cs
index 68895e9..6fc4742 100644
--- a/Swan.Lite/Definitions.Types.cs
+++ b/Swan.Lite/Definitions.Types.cs
@@ -3,136 +3,123 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net;
+
using Swan.Reflection;
-namespace Swan
-{
+namespace Swan {
+ ///
+ /// Contains useful constants and definitions.
+ ///
+ public static partial class Definitions {
+ #region Main Dictionary Definition
+
///
- /// Contains useful constants and definitions.
+ /// The basic types information.
///
- public static partial class Definitions
- {
- #region Main Dictionary Definition
-
- ///
- /// The basic types information.
- ///
- public static readonly Lazy> BasicTypesInfo = new Lazy>(() =>
- new Dictionary
- {
- // Non-Nullables
- {typeof(DateTime), new ExtendedTypeInfo()},
- {typeof(byte), new ExtendedTypeInfo()},
- {typeof(sbyte), new ExtendedTypeInfo