Bleeding next
This commit is contained in:
parent
b2f110b8d6
commit
dfe1d86af2
@ -11,12 +11,12 @@ namespace Swan.Collections {
|
||||
public class CollectionCacheRepository<TValue> {
|
||||
private readonly Lazy<ConcurrentDictionary<Type, IEnumerable<TValue>>> _data = new Lazy<ConcurrentDictionary<Type, IEnumerable<TValue>>>(() => new ConcurrentDictionary<Type, IEnumerable<TValue>>(), true);
|
||||
|
||||
/// <summary>
|
||||
/*/// <summary>
|
||||
/// Determines whether the cache contains the specified key.
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <returns><c>true</c> if the cache contains the key, otherwise <c>false</c>.</returns>
|
||||
public Boolean ContainsKey(Type key) => this._data.Value.ContainsKey(key);
|
||||
public Boolean ContainsKey(Type key) => this._data.Value.ContainsKey(key);*/
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the properties stored for the specified type.
|
||||
|
@ -1,62 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Swan.Configuration {
|
||||
/// <summary>
|
||||
/// An attribute used to include additional information to a Property for serialization.
|
||||
///
|
||||
/// Previously we used DisplayAttribute from DataAnnotation.
|
||||
/// </summary>
|
||||
/// <seealso cref="System.Attribute" />
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public sealed class PropertyDisplayAttribute : Attribute {
|
||||
/*/// <summary>
|
||||
/// Gets or sets the name.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The name.
|
||||
/// </value>
|
||||
public String Name {
|
||||
get; set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the description.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The description.
|
||||
/// </value>
|
||||
public String Description {
|
||||
get; set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the group.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The name of the group.
|
||||
/// </value>
|
||||
public String GroupName {
|
||||
get; set;
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the default value.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The default value.
|
||||
/// </value>
|
||||
public Object DefaultValue {
|
||||
get; set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the format string to call with method <c>ToString</c>.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The format.
|
||||
/// </value>
|
||||
public String Format {
|
||||
get; set;
|
||||
}
|
||||
}
|
||||
}
|
@ -62,36 +62,6 @@ namespace Swan {
|
||||
|
||||
#endregion
|
||||
|
||||
/*/// <summary>
|
||||
/// Contains all basic types, including string, date time, and all of their nullable counterparts.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// All basic types.
|
||||
/// </value>
|
||||
public static IReadOnlyCollection<Type> AllBasicTypes { get; } = new ReadOnlyCollection<Type>(BasicTypesInfo.Value.Keys.ToArray());
|
||||
|
||||
/// <summary>
|
||||
/// Gets all numeric types including their nullable counterparts.
|
||||
/// Note that Booleans and Guids are not considered numeric types.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// All numeric types.
|
||||
/// </value>
|
||||
public static IReadOnlyCollection<Type> AllNumericTypes {
|
||||
get;
|
||||
} = new ReadOnlyCollection<Type>(BasicTypesInfo.Value.Where(kvp => kvp.Value.IsNumeric).Select(kvp => kvp.Key).ToArray());
|
||||
|
||||
/// <summary>
|
||||
/// Gets all numeric types without their nullable counterparts.
|
||||
/// Note that Booleans and Guids are not considered numeric types.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// All numeric value types.
|
||||
/// </value>
|
||||
public static IReadOnlyCollection<Type> AllNumericValueTypes {
|
||||
get;
|
||||
} = new ReadOnlyCollection<Type>(BasicTypesInfo.Value.Where(kvp => kvp.Value.IsNumeric && !kvp.Value.IsNullableValueType).Select(kvp => kvp.Key).ToArray());*/
|
||||
|
||||
/// <summary>
|
||||
/// Contains all basic value types. i.e. excludes string and nullables.
|
||||
/// </summary>
|
||||
@ -101,25 +71,5 @@ namespace Swan {
|
||||
public static IReadOnlyCollection<Type> AllBasicValueTypes {
|
||||
get;
|
||||
} = new ReadOnlyCollection<Type>(BasicTypesInfo.Value.Where(kvp => kvp.Value.IsValueType).Select(kvp => kvp.Key).ToArray());
|
||||
|
||||
/*/// <summary>
|
||||
/// Contains all basic value types including the string type. i.e. excludes nullables.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// All basic value and string types.
|
||||
/// </value>
|
||||
public static IReadOnlyCollection<Type> AllBasicValueAndStringTypes {
|
||||
get;
|
||||
} = new ReadOnlyCollection<Type>(BasicTypesInfo.Value.Where(kvp => kvp.Value.IsValueType || kvp.Key == typeof(String)).Select(kvp => kvp.Key).ToArray());
|
||||
|
||||
/// <summary>
|
||||
/// Gets all nullable value types. i.e. excludes string and all basic value types.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// All basic nullable value types.
|
||||
/// </value>
|
||||
public static IReadOnlyCollection<Type> AllBasicNullableValueTypes {
|
||||
get;
|
||||
} = new ReadOnlyCollection<Type>(BasicTypesInfo.Value.Where(kvp => kvp.Value.IsNullableValueType).Select(kvp => kvp.Key).ToArray());*/
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Swan.DependencyInjection {
|
||||
/// <summary>
|
||||
@ -10,13 +8,8 @@ namespace Swan.DependencyInjection {
|
||||
/// </summary>
|
||||
/// <seealso cref="System.IDisposable" />
|
||||
public partial class DependencyContainer : IDisposable {
|
||||
/*private readonly Object _autoRegisterLock = new Object();*/
|
||||
|
||||
private Boolean _disposed;
|
||||
|
||||
/*static DependencyContainer() {
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DependencyContainer"/> class.
|
||||
/// </summary>
|
||||
@ -25,8 +18,6 @@ namespace Swan.DependencyInjection {
|
||||
_ = this.Register(this);
|
||||
}
|
||||
|
||||
/*private DependencyContainer(DependencyContainer parent) : this() => this.Parent = parent;*/
|
||||
|
||||
/// <summary>
|
||||
/// Lazy created Singleton instance of the container for simple scenarios.
|
||||
/// </summary>
|
||||
@ -55,91 +46,8 @@ namespace Swan.DependencyInjection {
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/*/// <summary>
|
||||
/// Gets the child container.
|
||||
/// </summary>
|
||||
/// <returns>A new instance of the <see cref="DependencyContainer"/> class.</returns>
|
||||
public DependencyContainer GetChildContainer() => new DependencyContainer(this);*/
|
||||
|
||||
#region Registration
|
||||
|
||||
/*/// <summary>
|
||||
/// Attempt to automatically register all non-generic classes and interfaces in the current app domain.
|
||||
/// Types will only be registered if they pass the supplied registration predicate.
|
||||
/// </summary>
|
||||
/// <param name="duplicateAction">What action to take when encountering duplicate implementations of an interface/base class.</param>
|
||||
/// <param name="registrationPredicate">Predicate to determine if a particular type should be registered.</param>
|
||||
public void AutoRegister(DependencyContainerDuplicateImplementationAction duplicateAction = DependencyContainerDuplicateImplementationAction.RegisterSingle, Func<Type, Boolean> registrationPredicate = null) => this.AutoRegister(AppDomain.CurrentDomain.GetAssemblies().Where(a => !IsIgnoredAssembly(a)), duplicateAction, registrationPredicate);
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to automatically register all non-generic classes and interfaces in the specified assemblies
|
||||
/// Types will only be registered if they pass the supplied registration predicate.
|
||||
/// </summary>
|
||||
/// <param name="assemblies">Assemblies to process.</param>
|
||||
/// <param name="duplicateAction">What action to take when encountering duplicate implementations of an interface/base class.</param>
|
||||
/// <param name="registrationPredicate">Predicate to determine if a particular type should be registered.</param>
|
||||
public void AutoRegister(IEnumerable<Assembly> assemblies, DependencyContainerDuplicateImplementationAction duplicateAction = DependencyContainerDuplicateImplementationAction.RegisterSingle, Func<Type, Boolean> registrationPredicate = null) {
|
||||
lock(this._autoRegisterLock) {
|
||||
List<Type> types = assemblies.SelectMany(a => a.GetAllTypes()).Where(t => !IsIgnoredType(t, registrationPredicate)).ToList();
|
||||
|
||||
List<Type> concreteTypes = types.Where(type => type.IsClass && !type.IsAbstract && type != this.GetType() && type.DeclaringType != this.GetType() && !type.IsGenericTypeDefinition).ToList();
|
||||
|
||||
foreach(Type type in concreteTypes) {
|
||||
try {
|
||||
_ = this.RegisteredTypes.Register(type, String.Empty, GetDefaultObjectFactory(type, type));
|
||||
} catch(MethodAccessException) {
|
||||
// Ignore methods we can't access - added for Silverlight
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerable<Type> abstractInterfaceTypes = types.Where(type => (type.IsInterface || type.IsAbstract) && type.DeclaringType != this.GetType() && !type.IsGenericTypeDefinition);
|
||||
|
||||
foreach(Type type in abstractInterfaceTypes) {
|
||||
Type localType = type;
|
||||
List<Type> implementations = concreteTypes.Where(implementationType => localType.IsAssignableFrom(implementationType)).ToList();
|
||||
|
||||
if(implementations.Skip(1).Any()) {
|
||||
if(duplicateAction == DependencyContainerDuplicateImplementationAction.Fail) {
|
||||
throw new DependencyContainerRegistrationException(type, implementations);
|
||||
}
|
||||
|
||||
if(duplicateAction == DependencyContainerDuplicateImplementationAction.RegisterMultiple) {
|
||||
_ = this.RegisterMultiple(type, implementations);
|
||||
}
|
||||
}
|
||||
|
||||
Type firstImplementation = implementations.FirstOrDefault();
|
||||
|
||||
if(firstImplementation == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
_ = this.RegisteredTypes.Register(type, String.Empty, GetDefaultObjectFactory(type, firstImplementation));
|
||||
} catch(MethodAccessException) {
|
||||
// Ignore methods we can't access - added for Silverlight
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates/replaces a named container class registration with default options.
|
||||
/// </summary>
|
||||
/// <param name="registerType">Type to register.</param>
|
||||
/// <param name="name">Name of registration.</param>
|
||||
/// <returns>RegisterOptions for fluent API.</returns>
|
||||
public RegisterOptions Register(Type registerType, String name = "") => this.RegisteredTypes.Register(registerType, name, GetDefaultObjectFactory(registerType, registerType));
|
||||
|
||||
/// <summary>
|
||||
/// Creates/replaces a named container class registration with a given implementation and default options.
|
||||
/// </summary>
|
||||
/// <param name="registerType">Type to register.</param>
|
||||
/// <param name="registerImplementation">Type to instantiate that implements RegisterType.</param>
|
||||
/// <param name="name">Name of registration.</param>
|
||||
/// <returns>RegisterOptions for fluent API.</returns>
|
||||
public RegisterOptions Register(Type registerType, Type registerImplementation, String name = "") => this.RegisteredTypes.Register(registerType, name, GetDefaultObjectFactory(registerType, registerImplementation));*/
|
||||
|
||||
/// <summary>
|
||||
/// Creates/replaces a named container class registration with a specific, strong referenced, instance.
|
||||
/// </summary>
|
||||
@ -149,42 +57,6 @@ namespace Swan.DependencyInjection {
|
||||
/// <returns>RegisterOptions for fluent API.</returns>
|
||||
public RegisterOptions Register(Type registerType, Object instance, String name = "") => this.RegisteredTypes.Register(registerType, name, new InstanceFactory(registerType, registerType, instance));
|
||||
|
||||
/*/// <summary>
|
||||
/// Creates/replaces a named container class registration with a specific, strong referenced, instance.
|
||||
/// </summary>
|
||||
/// <param name="registerType">Type to register.</param>
|
||||
/// <param name="registerImplementation">Type of instance to register that implements RegisterType.</param>
|
||||
/// <param name="instance">Instance of RegisterImplementation to register.</param>
|
||||
/// <param name="name">Name of registration.</param>
|
||||
/// <returns>RegisterOptions for fluent API.</returns>
|
||||
public RegisterOptions Register(Type registerType, Type registerImplementation, Object instance, String name = "") => this.RegisteredTypes.Register(registerType, name, new InstanceFactory(registerType, registerImplementation, instance));
|
||||
|
||||
/// <summary>
|
||||
/// Creates/replaces a container class registration with a user specified factory.
|
||||
/// </summary>
|
||||
/// <param name="registerType">Type to register.</param>
|
||||
/// <param name="factory">Factory/lambda that returns an instance of RegisterType.</param>
|
||||
/// <param name="name">Name of registration.</param>
|
||||
/// <returns>RegisterOptions for fluent API.</returns>
|
||||
public RegisterOptions Register(Type registerType, Func<DependencyContainer, Dictionary<String, Object>, Object> factory, String name = "") => this.RegisteredTypes.Register(registerType, name, new DelegateFactory(registerType, factory));
|
||||
|
||||
/// <summary>
|
||||
/// Creates/replaces a named container class registration with default options.
|
||||
/// </summary>
|
||||
/// <typeparam name="TRegister">Type to register.</typeparam>
|
||||
/// <param name="name">Name of registration.</param>
|
||||
/// <returns>RegisterOptions for fluent API.</returns>
|
||||
public RegisterOptions Register<TRegister>(String name = "") where TRegister : class => this.Register(typeof(TRegister), name);
|
||||
|
||||
/// <summary>
|
||||
/// Creates/replaces a named container class registration with a given implementation and default options.
|
||||
/// </summary>
|
||||
/// <typeparam name="TRegister">Type to register.</typeparam>
|
||||
/// <typeparam name="TRegisterImplementation">Type to instantiate that implements RegisterType.</typeparam>
|
||||
/// <param name="name">Name of registration.</param>
|
||||
/// <returns>RegisterOptions for fluent API.</returns>
|
||||
public RegisterOptions Register<TRegister, TRegisterImplementation>(String name = "") where TRegister : class where TRegisterImplementation : class, TRegister => this.Register(typeof(TRegister), typeof(TRegisterImplementation), name);*/
|
||||
|
||||
/// <summary>
|
||||
/// Creates/replaces a named container class registration with a specific, strong referenced, instance.
|
||||
/// </summary>
|
||||
@ -195,91 +67,6 @@ namespace Swan.DependencyInjection {
|
||||
// [Obsolete("NEED", false)]
|
||||
public RegisterOptions Register<TRegister>(TRegister instance, String name = "") where TRegister : class => this.Register(typeof(TRegister), instance, name);
|
||||
|
||||
/*/// <summary>
|
||||
/// Creates/replaces a named container class registration with a specific, strong referenced, instance.
|
||||
/// </summary>
|
||||
/// <typeparam name="TRegister">Type to register.</typeparam>
|
||||
/// <typeparam name="TRegisterImplementation">Type of instance to register that implements RegisterType.</typeparam>
|
||||
/// <param name="instance">Instance of RegisterImplementation to register.</param>
|
||||
/// <param name="name">Name of registration.</param>
|
||||
/// <returns>RegisterOptions for fluent API.</returns>
|
||||
public RegisterOptions Register<TRegister, TRegisterImplementation>(TRegisterImplementation instance, String name = "") where TRegister : class where TRegisterImplementation : class, TRegister => this.Register(typeof(TRegister), typeof(TRegisterImplementation), instance, name);
|
||||
|
||||
/// <summary>
|
||||
/// Creates/replaces a named container class registration with a user specified factory.
|
||||
/// </summary>
|
||||
/// <typeparam name="TRegister">Type to register.</typeparam>
|
||||
/// <param name="factory">Factory/lambda that returns an instance of RegisterType.</param>
|
||||
/// <param name="name">Name of registration.</param>
|
||||
/// <returns>RegisterOptions for fluent API.</returns>
|
||||
public RegisterOptions Register<TRegister>(Func<DependencyContainer, Dictionary<String, Object>, TRegister> factory, String name = "") where TRegister : class {
|
||||
if(factory == null) {
|
||||
throw new ArgumentNullException(nameof(factory));
|
||||
}
|
||||
|
||||
return this.Register(typeof(TRegister), factory, name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register multiple implementations of a type.
|
||||
///
|
||||
/// Internally this registers each implementation using the full name of the class as its registration name.
|
||||
/// </summary>
|
||||
/// <typeparam name="TRegister">Type that each implementation implements.</typeparam>
|
||||
/// <param name="implementationTypes">Types that implement RegisterType.</param>
|
||||
/// <returns>MultiRegisterOptions for the fluent API.</returns>
|
||||
public MultiRegisterOptions RegisterMultiple<TRegister>(IEnumerable<Type> implementationTypes) => this.RegisterMultiple(typeof(TRegister), implementationTypes);
|
||||
|
||||
/// <summary>
|
||||
/// Register multiple implementations of a type.
|
||||
///
|
||||
/// Internally this registers each implementation using the full name of the class as its registration name.
|
||||
/// </summary>
|
||||
/// <param name="registrationType">Type that each implementation implements.</param>
|
||||
/// <param name="implementationTypes">Types that implement RegisterType.</param>
|
||||
/// <returns>MultiRegisterOptions for the fluent API.</returns>
|
||||
public MultiRegisterOptions RegisterMultiple(Type registrationType, IEnumerable<Type> implementationTypes) {
|
||||
if(implementationTypes == null) {
|
||||
throw new ArgumentNullException(nameof(implementationTypes), "types is null.");
|
||||
}
|
||||
|
||||
foreach(Type type in implementationTypes.Where(type => !registrationType.IsAssignableFrom(type))) {
|
||||
throw new ArgumentException($"types: The type {registrationType.FullName} is not assignable from {type.FullName}");
|
||||
}
|
||||
|
||||
if(implementationTypes.Count() != implementationTypes.Distinct().Count()) {
|
||||
IEnumerable<String> queryForDuplicatedTypes = implementationTypes.GroupBy(i => i).Where(j => j.Count() > 1).Select(j => j.Key.FullName);
|
||||
|
||||
String fullNamesOfDuplicatedTypes = String.Join(",\n", queryForDuplicatedTypes.ToArray());
|
||||
|
||||
throw new ArgumentException($"types: The same implementation type cannot be specified multiple times for {registrationType.FullName}\n\n{fullNamesOfDuplicatedTypes}");
|
||||
}
|
||||
|
||||
List<RegisterOptions> registerOptions = implementationTypes.Select(type => this.Register(registrationType, type, type.FullName)).ToList();
|
||||
|
||||
return new MultiRegisterOptions(registerOptions);
|
||||
}*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unregistration
|
||||
|
||||
/*/// <summary>
|
||||
/// Remove a named container class registration.
|
||||
/// </summary>
|
||||
/// <typeparam name="TRegister">Type to unregister.</typeparam>
|
||||
/// <param name="name">Name of registration.</param>
|
||||
/// <returns><c>true</c> if the registration is successfully found and removed; otherwise, <c>false</c>.</returns>
|
||||
public Boolean Unregister<TRegister>(String name = "") => this.Unregister(typeof(TRegister), name);
|
||||
|
||||
/// <summary>
|
||||
/// Remove a named container class registration.
|
||||
/// </summary>
|
||||
/// <param name="registerType">Type to unregister.</param>
|
||||
/// <param name="name">Name of registration.</param>
|
||||
/// <returns><c>true</c> if the registration is successfully found and removed; otherwise, <c>false</c>.</returns>
|
||||
public Boolean Unregister(Type registerType, String name = "") => this.RegisteredTypes.RemoveRegistration(new TypeRegistration(registerType, name));*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region Resolution
|
||||
@ -342,179 +129,6 @@ namespace Swan.DependencyInjection {
|
||||
// [Obsolete("NEED", false)]
|
||||
public Boolean CanResolve<TResolveType>(String name = null, DependencyContainerResolveOptions options = null) where TResolveType : class => this.CanResolve(typeof(TResolveType), name, options);
|
||||
|
||||
/*/// <summary>
|
||||
/// Attempts to resolve a type using the default options.
|
||||
/// </summary>
|
||||
/// <param name="resolveType">Type to resolve.</param>
|
||||
/// <param name="resolvedType">Resolved type or default if resolve fails.</param>
|
||||
/// <returns><c>true</c> if resolved successfully, <c>false</c> otherwise.</returns>
|
||||
public Boolean TryResolve(Type resolveType, out Object resolvedType) {
|
||||
try {
|
||||
resolvedType = this.Resolve(resolveType);
|
||||
return true;
|
||||
} catch(DependencyContainerResolutionException) {
|
||||
resolvedType = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to resolve a type using the given options.
|
||||
/// </summary>
|
||||
/// <param name="resolveType">Type to resolve.</param>
|
||||
/// <param name="options">Resolution options.</param>
|
||||
/// <param name="resolvedType">Resolved type or default if resolve fails.</param>
|
||||
/// <returns><c>true</c> if resolved successfully, <c>false</c> otherwise.</returns>
|
||||
public Boolean TryResolve(Type resolveType, DependencyContainerResolveOptions options, out Object resolvedType) {
|
||||
try {
|
||||
resolvedType = this.Resolve(resolveType, options: options);
|
||||
return true;
|
||||
} catch(DependencyContainerResolutionException) {
|
||||
resolvedType = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to resolve a type using the default options and given name.
|
||||
/// </summary>
|
||||
/// <param name="resolveType">Type to resolve.</param>
|
||||
/// <param name="name">Name of registration.</param>
|
||||
/// <param name="resolvedType">Resolved type or default if resolve fails.</param>
|
||||
/// <returns><c>true</c> if resolved successfully, <c>false</c> otherwise.</returns>
|
||||
public Boolean TryResolve(Type resolveType, String name, out Object resolvedType) {
|
||||
try {
|
||||
resolvedType = this.Resolve(resolveType, name);
|
||||
return true;
|
||||
} catch(DependencyContainerResolutionException) {
|
||||
resolvedType = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to resolve a type using the given options and name.
|
||||
/// </summary>
|
||||
/// <param name="resolveType">Type to resolve.</param>
|
||||
/// <param name="name">Name of registration.</param>
|
||||
/// <param name="options">Resolution options.</param>
|
||||
/// <param name="resolvedType">Resolved type or default if resolve fails.</param>
|
||||
/// <returns><c>true</c> if resolved successfully, <c>false</c> otherwise.</returns>
|
||||
public Boolean TryResolve(Type resolveType, String name, DependencyContainerResolveOptions options, out Object resolvedType) {
|
||||
try {
|
||||
resolvedType = this.Resolve(resolveType, name, options);
|
||||
return true;
|
||||
} catch(DependencyContainerResolutionException) {
|
||||
resolvedType = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to resolve a type using the default options.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResolveType">Type to resolve.</typeparam>
|
||||
/// <param name="resolvedType">Resolved type or default if resolve fails.</param>
|
||||
/// <returns><c>true</c> if resolved successfully, <c>false</c> otherwise.</returns>
|
||||
public Boolean TryResolve<TResolveType>(out TResolveType resolvedType) where TResolveType : class {
|
||||
try {
|
||||
resolvedType = this.Resolve<TResolveType>();
|
||||
return true;
|
||||
} catch(DependencyContainerResolutionException) {
|
||||
resolvedType = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to resolve a type using the given options.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResolveType">Type to resolve.</typeparam>
|
||||
/// <param name="options">Resolution options.</param>
|
||||
/// <param name="resolvedType">Resolved type or default if resolve fails.</param>
|
||||
/// <returns><c>true</c> if resolved successfully, <c>false</c> otherwise.</returns>
|
||||
public Boolean TryResolve<TResolveType>(DependencyContainerResolveOptions options, out TResolveType resolvedType) where TResolveType : class {
|
||||
try {
|
||||
resolvedType = this.Resolve<TResolveType>(options: options);
|
||||
return true;
|
||||
} catch(DependencyContainerResolutionException) {
|
||||
resolvedType = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to resolve a type using the default options and given name.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResolveType">Type to resolve.</typeparam>
|
||||
/// <param name="name">Name of registration.</param>
|
||||
/// <param name="resolvedType">Resolved type or default if resolve fails.</param>
|
||||
/// <returns><c>true</c> if resolved successfully, <c>false</c> otherwise.</returns>
|
||||
public Boolean TryResolve<TResolveType>(String name, out TResolveType resolvedType) where TResolveType : class {
|
||||
try {
|
||||
resolvedType = this.Resolve<TResolveType>(name);
|
||||
return true;
|
||||
} catch(DependencyContainerResolutionException) {
|
||||
resolvedType = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to resolve a type using the given options and name.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResolveType">Type to resolve.</typeparam>
|
||||
/// <param name="name">Name of registration.</param>
|
||||
/// <param name="options">Resolution options.</param>
|
||||
/// <param name="resolvedType">Resolved type or default if resolve fails.</param>
|
||||
/// <returns><c>true</c> if resolved successfully, <c>false</c> otherwise.</returns>
|
||||
public Boolean TryResolve<TResolveType>(String name, DependencyContainerResolveOptions options, out TResolveType resolvedType) where TResolveType : class {
|
||||
try {
|
||||
resolvedType = this.Resolve<TResolveType>(name, options);
|
||||
return true;
|
||||
} catch(DependencyContainerResolutionException) {
|
||||
resolvedType = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all registrations of a type.
|
||||
/// </summary>
|
||||
/// <param name="resolveType">Type to resolveAll.</param>
|
||||
/// <param name="includeUnnamed">Whether to include un-named (default) registrations.</param>
|
||||
/// <returns>IEnumerable.</returns>
|
||||
public IEnumerable<Object> ResolveAll(Type resolveType, Boolean includeUnnamed = false) => this.RegisteredTypes.Resolve(resolveType, includeUnnamed);
|
||||
|
||||
/// <summary>
|
||||
/// Returns all registrations of a type.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResolveType">Type to resolveAll.</typeparam>
|
||||
/// <param name="includeUnnamed">Whether to include un-named (default) registrations.</param>
|
||||
/// <returns>IEnumerable.</returns>
|
||||
public IEnumerable<TResolveType> ResolveAll<TResolveType>(Boolean includeUnnamed = true) where TResolveType : class => this.ResolveAll(typeof(TResolveType), includeUnnamed).Cast<TResolveType>();
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to resolve all public property dependencies on the given object using the given resolve options.
|
||||
/// </summary>
|
||||
/// <param name="input">Object to "build up".</param>
|
||||
/// <param name="resolveOptions">Resolve options to use.</param>
|
||||
public void BuildUp(Object input, DependencyContainerResolveOptions resolveOptions = null) {
|
||||
if(resolveOptions == null) {
|
||||
resolveOptions = DependencyContainerResolveOptions.Default;
|
||||
}
|
||||
|
||||
IEnumerable<PropertyInfo> properties = input.GetType().GetProperties().Where(property => property.GetCacheGetMethod() != null && property.GetCacheSetMethod() != null && !property.PropertyType.IsValueType);
|
||||
|
||||
foreach(PropertyInfo property in properties.Where(property => property.GetValue(input, null) == null)) {
|
||||
try {
|
||||
property.SetValue(input, this.RegisteredTypes.ResolveInternal(new TypeRegistration(property.PropertyType), resolveOptions), null);
|
||||
} catch(DependencyContainerResolutionException) {
|
||||
// Catch any resolution errors and ignore them
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Methods
|
||||
@ -537,44 +151,6 @@ namespace Swan.DependencyInjection {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*private static Boolean IsIgnoredAssembly(Assembly assembly) {
|
||||
// TODO - find a better way to remove "system" assemblies from the auto registration
|
||||
List<Func<Assembly, Boolean>> ignoreChecks = new List<Func<Assembly, Boolean>>
|
||||
{
|
||||
asm => asm.FullName.StartsWith("Microsoft.", StringComparison.Ordinal),
|
||||
asm => asm.FullName.StartsWith("System.", StringComparison.Ordinal),
|
||||
asm => asm.FullName.StartsWith("System,", StringComparison.Ordinal),
|
||||
asm => asm.FullName.StartsWith("CR_ExtUnitTest", StringComparison.Ordinal),
|
||||
asm => asm.FullName.StartsWith("mscorlib,", StringComparison.Ordinal),
|
||||
asm => asm.FullName.StartsWith("CR_VSTest", StringComparison.Ordinal),
|
||||
asm => asm.FullName.StartsWith("DevExpress.CodeRush", StringComparison.Ordinal),
|
||||
asm => asm.FullName.StartsWith("xunit.", StringComparison.Ordinal),
|
||||
};
|
||||
|
||||
return ignoreChecks.Any(check => check(assembly));
|
||||
}
|
||||
|
||||
private static Boolean IsIgnoredType(Type type, Func<Type, Boolean> registrationPredicate) {
|
||||
// TODO - find a better way to remove "system" types from the auto registration
|
||||
List<Func<Type, Boolean>> ignoreChecks = new List<Func<Type, Boolean>>()
|
||||
{
|
||||
t => t.FullName?.StartsWith("System.", StringComparison.Ordinal) ?? false,
|
||||
t => t.FullName?.StartsWith("Microsoft.", StringComparison.Ordinal) ?? false,
|
||||
t => t.IsPrimitive,
|
||||
t => t.IsGenericTypeDefinition,
|
||||
t => t.GetConstructors(BindingFlags.Instance | BindingFlags.Public).Length == 0 &&
|
||||
!(t.IsInterface || t.IsAbstract),
|
||||
};
|
||||
|
||||
if(registrationPredicate != null) {
|
||||
ignoreChecks.Add(t => !registrationPredicate(t));
|
||||
}
|
||||
|
||||
return ignoreChecks.Any(check => check(type));
|
||||
}
|
||||
|
||||
private static ObjectFactoryBase GetDefaultObjectFactory(Type registerType, Type registerImplementation) => registerType.IsInterface || registerType.IsAbstract ? (ObjectFactoryBase)new SingletonFactory(registerType, registerImplementation) : new MultiInstanceFactory(registerType, registerImplementation);*/
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Swan.DependencyInjection {
|
||||
/// <summary>
|
||||
@ -10,15 +8,6 @@ namespace Swan.DependencyInjection {
|
||||
public class DependencyContainerRegistrationException : Exception {
|
||||
private const String ConvertErrorText = "Cannot convert current registration of {0} to {1}";
|
||||
private const String RegisterErrorText = "Cannot register type {0} - abstract classes or interfaces are not valid implementation types for {1}.";
|
||||
/*private const String ErrorText = "Duplicate implementation of type {0} found ({1}).";*/
|
||||
|
||||
/*/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DependencyContainerRegistrationException"/> class.
|
||||
/// </summary>
|
||||
/// <param name="registerType">Type of the register.</param>
|
||||
/// <param name="types">The types.</param>
|
||||
public DependencyContainerRegistrationException(Type registerType, IEnumerable<Type> types) : base(String.Format(ErrorText, registerType, GetTypesString(types))) {
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DependencyContainerRegistrationException" /> class.
|
||||
@ -28,7 +17,5 @@ namespace Swan.DependencyInjection {
|
||||
/// <param name="isTypeFactory">if set to <c>true</c> [is type factory].</param>
|
||||
public DependencyContainerRegistrationException(Type type, String method, Boolean isTypeFactory = false) : base(isTypeFactory ? String.Format(RegisterErrorText, type.FullName, method) : String.Format(ConvertErrorText, type.FullName, method)) {
|
||||
}
|
||||
|
||||
/*private static String GetTypesString(IEnumerable<Type> types) => String.Join(",", types.Select(type => type.FullName));*/
|
||||
}
|
||||
}
|
@ -82,25 +82,5 @@ namespace Swan.DependencyInjection {
|
||||
/// The fail
|
||||
/// </summary>
|
||||
Fail,
|
||||
}
|
||||
|
||||
/*/// <summary>
|
||||
/// Enumerates duplicate definition actions.
|
||||
/// </summary>
|
||||
public enum DependencyContainerDuplicateImplementationAction {
|
||||
/// <summary>
|
||||
/// The register single
|
||||
/// </summary>
|
||||
RegisterSingle,
|
||||
|
||||
/// <summary>
|
||||
/// The register multiple
|
||||
/// </summary>
|
||||
RegisterMultiple,
|
||||
|
||||
/// <summary>
|
||||
/// The fail
|
||||
/// </summary>
|
||||
Fail,
|
||||
}*/
|
||||
}
|
||||
}
|
@ -107,7 +107,7 @@ namespace Swan.DependencyInjection {
|
||||
|
||||
public override Type CreatesType => this._registerImplementation;
|
||||
|
||||
public override ObjectFactoryBase SingletonVariant => new SingletonFactory(this._registerType, this._registerImplementation);
|
||||
public override ObjectFactoryBase SingletonVariant => new SingletonFactory(this._registerType, this._registerImplementation);
|
||||
|
||||
public override ObjectFactoryBase MultiInstanceVariant => this;
|
||||
|
||||
@ -129,7 +129,7 @@ namespace Swan.DependencyInjection {
|
||||
|
||||
private readonly Func<DependencyContainer, Dictionary<String, Object>, Object> _factory;
|
||||
|
||||
public DelegateFactory( Type registerType, Func<DependencyContainer, Dictionary<String, Object>, Object> factory) {
|
||||
public DelegateFactory(Type registerType, Func<DependencyContainer, Dictionary<String, Object>, Object> factory) {
|
||||
this._factory = factory ?? throw new ArgumentNullException(nameof(factory));
|
||||
|
||||
this._registerType = registerType;
|
||||
@ -313,9 +313,9 @@ namespace Swan.DependencyInjection {
|
||||
|
||||
public override ObjectFactoryBase SingletonVariant => this;
|
||||
|
||||
public override ObjectFactoryBase MultiInstanceVariant => new MultiInstanceFactory(this._registerType, this._registerImplementation);
|
||||
public override ObjectFactoryBase MultiInstanceVariant => new MultiInstanceFactory(this._registerType, this._registerImplementation);
|
||||
|
||||
public override Object GetObject( Type requestedType, DependencyContainer container, DependencyContainerResolveOptions options) {
|
||||
public override Object GetObject(Type requestedType, DependencyContainer container, DependencyContainerResolveOptions options) {
|
||||
if(options.ConstructorParameters.Count != 0) {
|
||||
throw new ArgumentException("Cannot specify parameters for singleton types");
|
||||
}
|
||||
@ -329,7 +329,7 @@ namespace Swan.DependencyInjection {
|
||||
return this._current;
|
||||
}
|
||||
|
||||
public override ObjectFactoryBase GetFactoryForChildContainer( Type type, DependencyContainer parent, DependencyContainer child) {
|
||||
public override ObjectFactoryBase GetFactoryForChildContainer(Type type, DependencyContainer parent, DependencyContainer child) {
|
||||
// We make sure that the singleton is constructed before the child container takes the factory.
|
||||
// Otherwise the results would vary depending on whether or not the parent container had resolved
|
||||
// the type before the child container does.
|
||||
|
@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Swan.DependencyInjection {
|
||||
namespace Swan.DependencyInjection {
|
||||
/// <summary>
|
||||
/// Registration options for "fluent" API.
|
||||
/// </summary>
|
||||
@ -19,100 +15,5 @@ namespace Swan.DependencyInjection {
|
||||
this._registeredTypes = registeredTypes;
|
||||
this._registration = registration;
|
||||
}
|
||||
|
||||
/*/// <summary>
|
||||
/// Make registration a singleton (single instance) if possible.
|
||||
/// </summary>
|
||||
/// <returns>A registration options for fluent API.</returns>
|
||||
/// <exception cref="DependencyContainerRegistrationException">Generic constraint registration exception.</exception>
|
||||
public RegisterOptions AsSingleton() {
|
||||
ObjectFactoryBase currentFactory = this._registeredTypes.GetCurrentFactory(this._registration);
|
||||
|
||||
if(currentFactory == null) {
|
||||
throw new DependencyContainerRegistrationException(this._registration.Type, "singleton");
|
||||
}
|
||||
|
||||
return this._registeredTypes.AddUpdateRegistration(this._registration, currentFactory.SingletonVariant);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make registration multi-instance if possible.
|
||||
/// </summary>
|
||||
/// <returns>A registration options for fluent API.</returns>
|
||||
/// <exception cref="DependencyContainerRegistrationException">Generic constraint registration exception.</exception>
|
||||
public RegisterOptions AsMultiInstance() {
|
||||
ObjectFactoryBase currentFactory = this._registeredTypes.GetCurrentFactory(this._registration);
|
||||
|
||||
if(currentFactory == null) {
|
||||
throw new DependencyContainerRegistrationException(this._registration.Type, "multi-instance");
|
||||
}
|
||||
|
||||
return this._registeredTypes.AddUpdateRegistration(this._registration, currentFactory.MultiInstanceVariant);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make registration hold a weak reference if possible.
|
||||
/// </summary>
|
||||
/// <returns>A registration options for fluent API.</returns>
|
||||
/// <exception cref="DependencyContainerRegistrationException">Generic constraint registration exception.</exception>
|
||||
public RegisterOptions WithWeakReference() {
|
||||
ObjectFactoryBase currentFactory = this._registeredTypes.GetCurrentFactory(this._registration);
|
||||
|
||||
if(currentFactory == null) {
|
||||
throw new DependencyContainerRegistrationException(this._registration.Type, "weak reference");
|
||||
}
|
||||
|
||||
return this._registeredTypes.AddUpdateRegistration(this._registration, currentFactory.WeakReferenceVariant);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make registration hold a strong reference if possible.
|
||||
/// </summary>
|
||||
/// <returns>A registration options for fluent API.</returns>
|
||||
/// <exception cref="DependencyContainerRegistrationException">Generic constraint registration exception.</exception>
|
||||
public RegisterOptions WithStrongReference() {
|
||||
ObjectFactoryBase currentFactory = this._registeredTypes.GetCurrentFactory(this._registration);
|
||||
|
||||
if(currentFactory == null) {
|
||||
throw new DependencyContainerRegistrationException(this._registration.Type, "strong reference");
|
||||
}
|
||||
|
||||
return this._registeredTypes.AddUpdateRegistration(this._registration, currentFactory.StrongReferenceVariant);
|
||||
}*/
|
||||
}
|
||||
|
||||
/*/// <summary>
|
||||
/// Registration options for "fluent" API when registering multiple implementations.
|
||||
/// </summary>
|
||||
public sealed class MultiRegisterOptions {
|
||||
/*private IEnumerable<RegisterOptions> _registerOptions;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MultiRegisterOptions"/> class.
|
||||
/// </summary>
|
||||
/// <param name="registerOptions">The register options.</param>
|
||||
public MultiRegisterOptions(IEnumerable<RegisterOptions> registerOptions) => this._registerOptions = registerOptions;
|
||||
|
||||
/// <summary>
|
||||
/// Make registration a singleton (single instance) if possible.
|
||||
/// </summary>
|
||||
/// <returns>A registration multi-instance for fluent API.</returns>
|
||||
/// <exception cref="DependencyContainerRegistrationException">Generic Constraint Registration Exception.</exception>
|
||||
public MultiRegisterOptions AsSingleton() {
|
||||
this._registerOptions = this.ExecuteOnAllRegisterOptions(ro => ro.AsSingleton());
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make registration multi-instance if possible.
|
||||
/// </summary>
|
||||
/// <returns>A registration multi-instance for fluent API.</returns>
|
||||
/// <exception cref="DependencyContainerRegistrationException">Generic Constraint Registration Exception.</exception>
|
||||
public MultiRegisterOptions AsMultiInstance() {
|
||||
this._registerOptions = this.ExecuteOnAllRegisterOptions(ro => ro.AsMultiInstance());
|
||||
return this;
|
||||
}
|
||||
|
||||
private IEnumerable<RegisterOptions> ExecuteOnAllRegisterOptions( Func<RegisterOptions, RegisterOptions> action) => this._registerOptions.Select(action).ToList();
|
||||
}*/
|
||||
}
|
||||
}
|
@ -18,14 +18,9 @@ namespace Swan.Diagnostics {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/*/// <summary>
|
||||
/// Gets the number of microseconds per timer tick.
|
||||
/// </summary>
|
||||
public static Double MicrosecondsPerTick { get; } = 1000000d / Frequency;
|
||||
|
||||
/*/// <summary>
|
||||
/// Gets the elapsed microseconds.
|
||||
/// </summary>
|
||||
public Int64 ElapsedMicroseconds => (Int64)(this.ElapsedTicks * MicrosecondsPerTick);*/
|
||||
public static Double MicrosecondsPerTick { get; } = 1000000d / Frequency;*/
|
||||
}
|
||||
}
|
||||
|
@ -1,50 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Swan {
|
||||
/// <summary>
|
||||
/// Provides various extension methods for byte arrays and streams.
|
||||
/// </summary>
|
||||
public static class ByteArrayExtensions {
|
||||
/*/// <summary>
|
||||
/// Converts an array of bytes to its lower-case, hexadecimal representation.
|
||||
/// </summary>
|
||||
/// <param name="bytes">The bytes.</param>
|
||||
/// <param name="addPrefix">if set to <c>true</c> add the 0x prefix tot he output.</param>
|
||||
/// <returns>
|
||||
/// The specified string instance; no actual conversion is performed.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">bytes.</exception>
|
||||
public static String ToLowerHex(this Byte[] bytes, Boolean addPrefix = false) => ToHex(bytes, addPrefix, "x2");
|
||||
|
||||
/// <summary>
|
||||
/// Converts an array of bytes to its upper-case, hexadecimal representation.
|
||||
/// </summary>
|
||||
/// <param name="bytes">The bytes.</param>
|
||||
/// <param name="addPrefix">if set to <c>true</c> [add prefix].</param>
|
||||
/// <returns>
|
||||
/// The specified string instance; no actual conversion is performed.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">bytes.</exception>
|
||||
public static String ToUpperHex(this Byte[] bytes, Boolean addPrefix = false) => ToHex(bytes, addPrefix, "X2");
|
||||
|
||||
/// <summary>
|
||||
/// Converts an array of bytes to a sequence of dash-separated, hexadecimal,
|
||||
/// uppercase characters.
|
||||
/// </summary>
|
||||
/// <param name="bytes">The bytes.</param>
|
||||
/// <returns>
|
||||
/// A string of hexadecimal pairs separated by hyphens, where each pair represents
|
||||
/// the corresponding element in value; for example, "7F-2C-4A-00".
|
||||
/// </returns>
|
||||
public static String ToDashedHex(this Byte[] bytes) => BitConverter.ToString(bytes);*/
|
||||
|
||||
/// <summary>
|
||||
/// Converts an array of bytes to a base-64 encoded string.
|
||||
/// </summary>
|
||||
@ -69,430 +30,5 @@ namespace Swan {
|
||||
|
||||
return Enumerable.Range(0, @this.Length / 2).Select(x => Convert.ToByte(@this.Substring(x * 2, 2), 16)).ToArray();
|
||||
}
|
||||
|
||||
/*/// <summary>
|
||||
/// Gets the bit value at the given offset.
|
||||
/// </summary>
|
||||
/// <param name="this">The b.</param>
|
||||
/// <param name="offset">The offset.</param>
|
||||
/// <param name="length">The length.</param>
|
||||
/// <returns>
|
||||
/// Bit value at the given offset.
|
||||
/// </returns>
|
||||
public static Byte GetBitValueAt(this Byte @this, Byte offset, Byte length = 1) => (Byte)((@this >> offset) & ~(0xff << length));
|
||||
|
||||
/// <summary>
|
||||
/// Sets the bit value at the given offset.
|
||||
/// </summary>
|
||||
/// <param name="this">The b.</param>
|
||||
/// <param name="offset">The offset.</param>
|
||||
/// <param name="length">The length.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <returns>Bit value at the given offset.</returns>
|
||||
public static Byte SetBitValueAt(this Byte @this, Byte offset, Byte length, Byte value) {
|
||||
Int32 mask = ~(0xff << length);
|
||||
Byte valueAt = (Byte)(value & mask);
|
||||
|
||||
return (Byte)((valueAt << offset) | (@this & ~(mask << offset)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the bit value at the given offset.
|
||||
/// </summary>
|
||||
/// <param name="this">The b.</param>
|
||||
/// <param name="offset">The offset.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <returns>Bit value at the given offset.</returns>
|
||||
public static Byte SetBitValueAt(this Byte @this, Byte offset, Byte value) => @this.SetBitValueAt(offset, 1, value);
|
||||
|
||||
/// <summary>
|
||||
/// Splits a byte array delimited by the specified sequence of bytes.
|
||||
/// Each individual element in the result will contain the split sequence terminator if it is found to be delimited by it.
|
||||
/// For example if you split [1,2,3,4] by a sequence of [2,3] this method will return a list with 2 byte arrays, one containing [1,2,3] and the
|
||||
/// second one containing 4. Use the Trim extension methods to remove terminator sequences.
|
||||
/// </summary>
|
||||
/// <param name="this">The buffer.</param>
|
||||
/// <param name="offset">The offset at which to start splitting bytes. Any bytes before this will be discarded.</param>
|
||||
/// <param name="sequence">The sequence.</param>
|
||||
/// <returns>
|
||||
/// A byte array containing the results the specified sequence of bytes.
|
||||
/// </returns>
|
||||
/// <exception cref="System.ArgumentNullException">
|
||||
/// buffer
|
||||
/// or
|
||||
/// sequence.
|
||||
/// </exception>
|
||||
public static List<Byte[]> Split(this Byte[] @this, Int32 offset, params Byte[] sequence) {
|
||||
if(@this == null) {
|
||||
throw new ArgumentNullException(nameof(@this));
|
||||
}
|
||||
|
||||
if(sequence == null) {
|
||||
throw new ArgumentNullException(nameof(sequence));
|
||||
}
|
||||
|
||||
Int32 seqOffset = offset.Clamp(0, @this.Length - 1);
|
||||
|
||||
List<Byte[]> result = new List<Byte[]>();
|
||||
|
||||
while(seqOffset < @this.Length) {
|
||||
Int32 separatorStartIndex = @this.GetIndexOf(sequence, seqOffset);
|
||||
|
||||
if(separatorStartIndex >= 0) {
|
||||
Byte[] item = new Byte[separatorStartIndex - seqOffset + sequence.Length];
|
||||
Array.Copy(@this, seqOffset, item, 0, item.Length);
|
||||
result.Add(item);
|
||||
seqOffset += item.Length;
|
||||
} else {
|
||||
Byte[] item = new Byte[@this.Length - seqOffset];
|
||||
Array.Copy(@this, seqOffset, item, 0, item.Length);
|
||||
result.Add(item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clones the specified buffer, byte by byte.
|
||||
/// </summary>
|
||||
/// <param name="this">The buffer.</param>
|
||||
/// <returns>
|
||||
/// A byte array containing the results of encoding the specified set of characters.
|
||||
/// </returns>
|
||||
/// <exception cref="System.ArgumentNullException">this</exception>
|
||||
public static Byte[] DeepClone(this Byte[] @this) {
|
||||
if(@this == null) {
|
||||
throw new ArgumentNullException(nameof(@this));
|
||||
}
|
||||
|
||||
Byte[] result = new Byte[@this.Length];
|
||||
Array.Copy(@this, result, @this.Length);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the specified sequence from the start of the buffer if the buffer begins with such sequence.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
/// <param name="sequence">The sequence.</param>
|
||||
/// <returns>
|
||||
/// A new trimmed byte array.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">buffer.</exception>
|
||||
public static Byte[] TrimStart(this Byte[] buffer, params Byte[] sequence) {
|
||||
if(buffer == null) {
|
||||
throw new ArgumentNullException(nameof(buffer));
|
||||
}
|
||||
|
||||
if(buffer.StartsWith(sequence) == false) {
|
||||
return buffer.DeepClone();
|
||||
}
|
||||
|
||||
Byte[] result = new Byte[buffer.Length - sequence.Length];
|
||||
Array.Copy(buffer, sequence.Length, result, 0, result.Length);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the specified sequence from the end of the buffer if the buffer ends with such sequence.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
/// <param name="sequence">The sequence.</param>
|
||||
/// <returns>
|
||||
/// A byte array containing the results of encoding the specified set of characters.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">buffer.</exception>
|
||||
public static Byte[] TrimEnd(this Byte[] buffer, params Byte[] sequence) {
|
||||
if(buffer == null) {
|
||||
throw new ArgumentNullException(nameof(buffer));
|
||||
}
|
||||
|
||||
if(buffer.EndsWith(sequence) == false) {
|
||||
return buffer.DeepClone();
|
||||
}
|
||||
|
||||
Byte[] result = new Byte[buffer.Length - sequence.Length];
|
||||
Array.Copy(buffer, 0, result, 0, result.Length);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the specified sequence from the end and the start of the buffer
|
||||
/// if the buffer ends and/or starts with such sequence.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
/// <param name="sequence">The sequence.</param>
|
||||
/// <returns>A byte array containing the results of encoding the specified set of characters.</returns>
|
||||
public static Byte[] Trim(this Byte[] buffer, params Byte[] sequence) {
|
||||
Byte[] trimStart = buffer.TrimStart(sequence);
|
||||
return trimStart.TrimEnd(sequence);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the specified buffer ends with the given sequence of bytes.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
/// <param name="sequence">The sequence.</param>
|
||||
/// <returns>
|
||||
/// True if the specified buffer is ends; otherwise, false.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">buffer.</exception>
|
||||
public static Boolean EndsWith(this Byte[] buffer, params Byte[] sequence) {
|
||||
if(buffer == null) {
|
||||
throw new ArgumentNullException(nameof(buffer));
|
||||
}
|
||||
|
||||
Int32 startIndex = buffer.Length - sequence.Length;
|
||||
return buffer.GetIndexOf(sequence, startIndex) == startIndex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the specified buffer starts with the given sequence of bytes.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
/// <param name="sequence">The sequence.</param>
|
||||
/// <returns><c>true</c> if the specified buffer starts; otherwise, <c>false</c>.</returns>
|
||||
public static Boolean StartsWith(this Byte[] buffer, params Byte[] sequence) => buffer.GetIndexOf(sequence) == 0;
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the buffer contains the specified sequence.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
/// <param name="sequence">The sequence.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if [contains] [the specified sequence]; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public static Boolean Contains(this Byte[] buffer, params Byte[] sequence) => buffer.GetIndexOf(sequence) >= 0;
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the buffer exactly matches, byte by byte the specified sequence.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
/// <param name="sequence">The sequence.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if [is equal to] [the specified sequence]; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">buffer.</exception>
|
||||
public static Boolean IsEqualTo(this Byte[] buffer, params Byte[] sequence) {
|
||||
if(ReferenceEquals(buffer, sequence)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(buffer == null) {
|
||||
throw new ArgumentNullException(nameof(buffer));
|
||||
}
|
||||
|
||||
return buffer.Length == sequence.Length && buffer.GetIndexOf(sequence) == 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the first instance of the matched sequence based on the given offset.
|
||||
/// If no matches are found then this method returns -1.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
/// <param name="sequence">The sequence.</param>
|
||||
/// <param name="offset">The offset.</param>
|
||||
/// <returns>The index of the sequence.</returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// buffer
|
||||
/// or
|
||||
/// sequence.
|
||||
/// </exception>
|
||||
public static Int32 GetIndexOf(this Byte[] buffer, Byte[] sequence, Int32 offset = 0) {
|
||||
if(buffer == null) {
|
||||
throw new ArgumentNullException(nameof(buffer));
|
||||
}
|
||||
|
||||
if(sequence == null) {
|
||||
throw new ArgumentNullException(nameof(sequence));
|
||||
}
|
||||
|
||||
if(sequence.Length == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(sequence.Length > buffer.Length) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
Int32 seqOffset = offset < 0 ? 0 : offset;
|
||||
|
||||
Int32 matchedCount = 0;
|
||||
for(Int32 i = seqOffset; i < buffer.Length; i++) {
|
||||
if(buffer[i] == sequence[matchedCount]) {
|
||||
matchedCount++;
|
||||
} else {
|
||||
matchedCount = 0;
|
||||
}
|
||||
|
||||
if(matchedCount == sequence.Length) {
|
||||
return i - (matchedCount - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends the Memory Stream with the specified buffer.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream.</param>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
/// <returns>
|
||||
/// The same MemoryStream instance.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// stream
|
||||
/// or
|
||||
/// buffer.
|
||||
/// </exception>
|
||||
public static MemoryStream Append(this MemoryStream stream, Byte[] buffer) {
|
||||
if(stream == null) {
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
}
|
||||
|
||||
if(buffer == null) {
|
||||
throw new ArgumentNullException(nameof(buffer));
|
||||
}
|
||||
|
||||
stream.Write(buffer, 0, buffer.Length);
|
||||
return stream;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends the Memory Stream with the specified buffer.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream.</param>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
/// <returns>
|
||||
/// Block of bytes to the current stream using data read from a buffer.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">buffer.</exception>
|
||||
public static MemoryStream Append(this MemoryStream stream, IEnumerable<Byte> buffer) => Append(stream, buffer?.ToArray());
|
||||
|
||||
/// <summary>
|
||||
/// Appends the Memory Stream with the specified set of buffers.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream.</param>
|
||||
/// <param name="buffers">The buffers.</param>
|
||||
/// <returns>
|
||||
/// Block of bytes to the current stream using data read from a buffer.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">buffers.</exception>
|
||||
public static MemoryStream Append(this MemoryStream stream, IEnumerable<Byte[]> buffers) {
|
||||
if(buffers == null) {
|
||||
throw new ArgumentNullException(nameof(buffers));
|
||||
}
|
||||
|
||||
foreach(Byte[] buffer in buffers) {
|
||||
_ = Append(stream, buffer);
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts an array of bytes into text with the specified encoding.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
/// <param name="encoding">The encoding.</param>
|
||||
/// <returns>A <see cref="System.String" /> that contains the results of decoding the specified sequence of bytes.</returns>
|
||||
public static String ToText(this IEnumerable<Byte> buffer, Encoding encoding) => encoding.GetString(buffer.ToArray());
|
||||
|
||||
/// <summary>
|
||||
/// Converts an array of bytes into text with UTF8 encoding.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
/// <returns>A <see cref="System.String" /> that contains the results of decoding the specified sequence of bytes.</returns>
|
||||
public static String ToText(this IEnumerable<Byte> buffer) => buffer.ToText(Encoding.UTF8);
|
||||
|
||||
/// <summary>
|
||||
/// Reads the bytes asynchronous.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream.</param>
|
||||
/// <param name="length">The length.</param>
|
||||
/// <param name="bufferLength">Length of the buffer.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>
|
||||
/// A byte array containing the results of encoding the specified set of characters.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">stream.</exception>
|
||||
public static async Task<Byte[]> ReadBytesAsync(this Stream stream, Int64 length, Int32 bufferLength, CancellationToken cancellationToken = default) {
|
||||
if(stream == null) {
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
}
|
||||
|
||||
using MemoryStream dest = new MemoryStream();
|
||||
try {
|
||||
Byte[] buff = new Byte[bufferLength];
|
||||
while(length > 0) {
|
||||
if(length < bufferLength) {
|
||||
bufferLength = (Int32)length;
|
||||
}
|
||||
|
||||
Int32 nread = await stream.ReadAsync(buff, 0, bufferLength, cancellationToken).ConfigureAwait(false);
|
||||
if(nread == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
dest.Write(buff, 0, nread);
|
||||
length -= nread;
|
||||
}
|
||||
} catch {
|
||||
// ignored
|
||||
}
|
||||
|
||||
return dest.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the bytes asynchronous.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream.</param>
|
||||
/// <param name="length">The length.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>
|
||||
/// A byte array containing the results of encoding the specified set of characters.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">stream.</exception>
|
||||
public static async Task<Byte[]> ReadBytesAsync(this Stream stream, Int32 length, CancellationToken cancellationToken = default) {
|
||||
if(stream == null) {
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
}
|
||||
|
||||
Byte[] buff = new Byte[length];
|
||||
Int32 offset = 0;
|
||||
try {
|
||||
while(length > 0) {
|
||||
Int32 nread = await stream.ReadAsync(buff, offset, length, cancellationToken).ConfigureAwait(false);
|
||||
if(nread == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
offset += nread;
|
||||
length -= nread;
|
||||
}
|
||||
} catch {
|
||||
// ignored
|
||||
}
|
||||
|
||||
return new ArraySegment<Byte>(buff, 0, offset).ToArray();
|
||||
}
|
||||
|
||||
private static String ToHex(Byte[] bytes, Boolean addPrefix, String format) {
|
||||
if(bytes == null) {
|
||||
throw new ArgumentNullException(nameof(bytes));
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder(bytes.Length * 2);
|
||||
|
||||
foreach(Byte item in bytes) {
|
||||
_ = sb.Append(item.ToString(format, CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
return $"{(addPrefix ? "0x" : String.Empty)}{sb}";
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
@ -64,23 +64,5 @@ namespace Swan {
|
||||
|
||||
return dict[key];
|
||||
}
|
||||
|
||||
/*/// <summary>
|
||||
/// Executes the item action for each element in the Dictionary.
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">The type of the key.</typeparam>
|
||||
/// <typeparam name="TValue">The type of the value.</typeparam>
|
||||
/// <param name="dict">The dictionary.</param>
|
||||
/// <param name="itemAction">The item action.</param>
|
||||
/// <exception cref="ArgumentNullException">dict.</exception>
|
||||
public static void ForEach<TKey, TValue>(this IDictionary<TKey, TValue> dict, Action<TKey, TValue> itemAction) {
|
||||
if(dict == null) {
|
||||
throw new ArgumentNullException(nameof(dict));
|
||||
}
|
||||
|
||||
foreach(KeyValuePair<TKey, TValue> kvp in dict) {
|
||||
itemAction(kvp.Key, kvp.Value);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
@ -1,45 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Swan {
|
||||
/// <summary>
|
||||
/// Functional programming extension methods.
|
||||
/// </summary>
|
||||
public static class FunctionalExtensions {
|
||||
/*/// <summary>
|
||||
/// Whens the specified condition.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of IQueryable.</typeparam>
|
||||
/// <param name="list">The list.</param>
|
||||
/// <param name="condition">The condition.</param>
|
||||
/// <param name="fn">The function.</param>
|
||||
/// <returns>
|
||||
/// The IQueryable.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// this
|
||||
/// or
|
||||
/// condition
|
||||
/// or
|
||||
/// fn.
|
||||
/// </exception>
|
||||
public static IQueryable<T> When<T>(this IQueryable<T> list, Func<Boolean> condition, Func<IQueryable<T>, IQueryable<T>> fn) {
|
||||
if(list == null) {
|
||||
throw new ArgumentNullException(nameof(list));
|
||||
}
|
||||
|
||||
if(condition == null) {
|
||||
throw new ArgumentNullException(nameof(condition));
|
||||
}
|
||||
|
||||
if(fn == null) {
|
||||
throw new ArgumentNullException(nameof(fn));
|
||||
}
|
||||
|
||||
return condition() ? fn(list) : list;
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// Whens the specified condition.
|
||||
/// </summary>
|
||||
@ -72,102 +38,5 @@ namespace Swan {
|
||||
|
||||
return condition() ? fn(list) : list;
|
||||
}
|
||||
|
||||
/*/// <summary>
|
||||
/// Adds the value when the condition is true.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of IList element.</typeparam>
|
||||
/// <param name="list">The list.</param>
|
||||
/// <param name="condition">The condition.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <returns>
|
||||
/// The IList.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// this
|
||||
/// or
|
||||
/// condition
|
||||
/// or
|
||||
/// value.
|
||||
/// </exception>
|
||||
public static IList<T> AddWhen<T>(this IList<T> list, Func<Boolean> condition, Func<T> value) {
|
||||
if(list == null) {
|
||||
throw new ArgumentNullException(nameof(list));
|
||||
}
|
||||
|
||||
if(condition == null) {
|
||||
throw new ArgumentNullException(nameof(condition));
|
||||
}
|
||||
|
||||
if(value == null) {
|
||||
throw new ArgumentNullException(nameof(value));
|
||||
}
|
||||
|
||||
if(condition()) {
|
||||
list.Add(value());
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the value when the condition is true.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of IList element.</typeparam>
|
||||
/// <param name="list">The list.</param>
|
||||
/// <param name="condition">if set to <c>true</c> [condition].</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <returns>
|
||||
/// The IList.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">list.</exception>
|
||||
public static IList<T> AddWhen<T>(this IList<T> list, Boolean condition, T value) {
|
||||
if(list == null) {
|
||||
throw new ArgumentNullException(nameof(list));
|
||||
}
|
||||
|
||||
if(condition) {
|
||||
list.Add(value);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the range when the condition is true.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of List element.</typeparam>
|
||||
/// <param name="list">The list.</param>
|
||||
/// <param name="condition">The condition.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <returns>
|
||||
/// The List.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// this
|
||||
/// or
|
||||
/// condition
|
||||
/// or
|
||||
/// value.
|
||||
/// </exception>
|
||||
public static List<T> AddRangeWhen<T>(this List<T> list, Func<Boolean> condition, Func<IEnumerable<T>> value) {
|
||||
if(list == null) {
|
||||
throw new ArgumentNullException(nameof(list));
|
||||
}
|
||||
|
||||
if(condition == null) {
|
||||
throw new ArgumentNullException(nameof(condition));
|
||||
}
|
||||
|
||||
if(value == null) {
|
||||
throw new ArgumentNullException(nameof(value));
|
||||
}
|
||||
|
||||
if(condition()) {
|
||||
list.AddRange(value());
|
||||
}
|
||||
|
||||
return list;
|
||||
}*/
|
||||
}
|
||||
}
|
@ -1,14 +1,9 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
using Swan.Configuration;
|
||||
using Swan.Reflection;
|
||||
|
||||
namespace Swan {
|
||||
/// <summary>
|
||||
@ -19,30 +14,6 @@ namespace Swan {
|
||||
|
||||
private static readonly Lazy<ConcurrentDictionary<Tuple<Boolean, PropertyInfo>, Action<Object, Object[]>>> CacheSetMethods = new Lazy<ConcurrentDictionary<Tuple<Boolean, PropertyInfo>, Action<Object, Object[]>>>(() => new ConcurrentDictionary<Tuple<Boolean, PropertyInfo>, Action<Object, Object[]>>(), true);
|
||||
|
||||
#region Assembly Extensions
|
||||
|
||||
/*/// <summary>
|
||||
/// Gets all types within an assembly in a safe manner.
|
||||
/// </summary>
|
||||
/// <param name="assembly">The assembly.</param>
|
||||
/// <returns>
|
||||
/// Array of Type objects representing the types specified by an assembly.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">assembly.</exception>
|
||||
public static IEnumerable<Type> GetAllTypes(this Assembly assembly) {
|
||||
if(assembly == null) {
|
||||
throw new ArgumentNullException(nameof(assembly));
|
||||
}
|
||||
|
||||
try {
|
||||
return assembly.GetTypes();
|
||||
} catch(ReflectionTypeLoadException e) {
|
||||
return e.Types.Where(t => t != null);
|
||||
}
|
||||
}*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region Type Extensions
|
||||
|
||||
/// <summary>
|
||||
@ -61,64 +32,6 @@ namespace Swan {
|
||||
return type.IsValueType ? Activator.CreateInstance(type) : default;
|
||||
}
|
||||
|
||||
/*/// <summary>
|
||||
/// Determines whether this type is compatible with ICollection.
|
||||
/// </summary>
|
||||
/// <param name="sourceType">The type.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the specified source type is collection; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">sourceType.</exception>
|
||||
public static Boolean IsCollection(this Type sourceType) {
|
||||
if(sourceType == null) {
|
||||
throw new ArgumentNullException(nameof(sourceType));
|
||||
}
|
||||
|
||||
return sourceType != typeof(String) && typeof(IEnumerable).IsAssignableFrom(sourceType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a method from a type given the method name, binding flags, generic types and parameter types.
|
||||
/// </summary>
|
||||
/// <param name="type">Type of the source.</param>
|
||||
/// <param name="bindingFlags">The binding flags.</param>
|
||||
/// <param name="methodName">Name of the method.</param>
|
||||
/// <param name="genericTypes">The generic types.</param>
|
||||
/// <param name="parameterTypes">The parameter types.</param>
|
||||
/// <returns>
|
||||
/// An object that represents the method with the specified name.
|
||||
/// </returns>
|
||||
/// <exception cref="System.Reflection.AmbiguousMatchException">
|
||||
/// The exception that is thrown when binding to a member results in more than one member matching the
|
||||
/// binding criteria. This class cannot be inherited.
|
||||
/// </exception>
|
||||
public static MethodInfo GetMethod(this Type type, BindingFlags bindingFlags, String methodName, Type[] genericTypes, Type[] parameterTypes) {
|
||||
if(type == null) {
|
||||
throw new ArgumentNullException(nameof(type));
|
||||
}
|
||||
|
||||
if(methodName == null) {
|
||||
throw new ArgumentNullException(nameof(methodName));
|
||||
}
|
||||
|
||||
if(genericTypes == null) {
|
||||
throw new ArgumentNullException(nameof(genericTypes));
|
||||
}
|
||||
|
||||
if(parameterTypes == null) {
|
||||
throw new ArgumentNullException(nameof(parameterTypes));
|
||||
}
|
||||
|
||||
List<MethodInfo> methods = type.GetMethods(bindingFlags)
|
||||
.Where(mi => String.Equals(methodName, mi.Name, StringComparison.Ordinal))
|
||||
.Where(mi => mi.ContainsGenericParameters)
|
||||
.Where(mi => mi.GetGenericArguments().Length == genericTypes.Length)
|
||||
.Where(mi => mi.GetParameters().Length == parameterTypes.Length).Select(mi => mi.MakeGenericMethod(genericTypes))
|
||||
.Where(mi => mi.GetParameters().Select(pi => pi.ParameterType).SequenceEqual(parameterTypes)).ToList();
|
||||
|
||||
return methods.Count > 1 ? throw new AmbiguousMatchException() : methods.FirstOrDefault();
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether [is i enumerable request].
|
||||
/// </summary>
|
||||
@ -281,39 +194,6 @@ namespace Swan {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*/// <summary>
|
||||
/// Gets property actual value or <c>PropertyDisplayAttribute.DefaultValue</c> if presented.
|
||||
///
|
||||
/// If the <c>PropertyDisplayAttribute.Format</c> value is presented, the property value
|
||||
/// will be formatted accordingly.
|
||||
///
|
||||
/// If the object contains a null value, a empty string will be returned.
|
||||
/// </summary>
|
||||
/// <param name="propertyInfo">The property information.</param>
|
||||
/// <param name="target">The object.</param>
|
||||
/// <returns>The property value or null.</returns>
|
||||
/// <exception cref="ArgumentNullException">propertyInfo.</exception>
|
||||
public static String? ToFormattedString(this PropertyInfo propertyInfo, Object target) {
|
||||
if(propertyInfo == null) {
|
||||
throw new ArgumentNullException(nameof(propertyInfo));
|
||||
}
|
||||
|
||||
try {
|
||||
Object? value = propertyInfo.GetValue(target);
|
||||
PropertyDisplayAttribute attr = AttributeCache.DefaultCache.Value.RetrieveOne<PropertyDisplayAttribute>(propertyInfo);
|
||||
|
||||
if(attr == null) {
|
||||
return value?.ToString() ?? String.Empty;
|
||||
}
|
||||
|
||||
Object valueToFormat = value ?? attr.DefaultValue;
|
||||
|
||||
return String.IsNullOrEmpty(attr.Format) ? (valueToFormat?.ToString() ?? String.Empty) : ConvertObjectAndFormat(propertyInfo.PropertyType, valueToFormat, attr.Format);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// Gets a MethodInfo from a Property Get method.
|
||||
/// </summary>
|
||||
@ -368,24 +248,6 @@ namespace Swan {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*/// <summary>
|
||||
/// Creates a property proxy that stores getter and setter delegates.
|
||||
/// </summary>
|
||||
/// <param name="this">The property information.</param>
|
||||
/// <returns>
|
||||
/// The property proxy.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">this.</exception>
|
||||
public static IPropertyProxy? CreatePropertyProxy(this PropertyInfo @this) {
|
||||
if(@this == null) {
|
||||
throw new ArgumentNullException(nameof(@this));
|
||||
}
|
||||
|
||||
Type genericType = typeof(PropertyProxy<,>).MakeGenericType(@this.DeclaringType!, @this.PropertyType);
|
||||
|
||||
return Activator.CreateInstance(genericType, @this) as IPropertyProxy;
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// Convert a object to a boolean.
|
||||
/// </summary>
|
||||
@ -394,18 +256,5 @@ namespace Swan {
|
||||
/// <c>true</c> if the string represents a valid truly value, otherwise <c>false</c>.
|
||||
/// </returns>
|
||||
public static Boolean ToBoolean(this Object value) => value.ToStringInvariant().ToBoolean();
|
||||
|
||||
/*private static String ConvertObjectAndFormat(Type propertyType, Object value, String format) =>
|
||||
propertyType == typeof(DateTime) || propertyType == typeof(DateTime?)
|
||||
? Convert.ToDateTime(value, CultureInfo.InvariantCulture).ToString(format)
|
||||
: propertyType == typeof(Int32) || propertyType == typeof(Int32?)
|
||||
? Convert.ToInt32(value, CultureInfo.InvariantCulture).ToString(format)
|
||||
: propertyType == typeof(Decimal) || propertyType == typeof(Decimal?)
|
||||
? Convert.ToDecimal(value, CultureInfo.InvariantCulture).ToString(format)
|
||||
: propertyType == typeof(Double) || propertyType == typeof(Double?)
|
||||
? Convert.ToDouble(value, CultureInfo.InvariantCulture).ToString(format)
|
||||
: propertyType == typeof(Byte) || propertyType == typeof(Byte?)
|
||||
? Convert.ToByte(value, CultureInfo.InvariantCulture).ToString(format)
|
||||
: value?.ToString() ?? String.Empty;*/
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
@ -16,21 +15,8 @@ namespace Swan {
|
||||
|
||||
private const RegexOptions StandardRegexOptions = RegexOptions.Multiline | RegexOptions.Compiled | RegexOptions.CultureInvariant;
|
||||
|
||||
/*private static readonly String[] ByteSuffixes = { "B", "KB", "MB", "GB", "TB" };*/
|
||||
|
||||
private static readonly Lazy<Regex> SplitLinesRegex = new Lazy<Regex>(() => new Regex("\r\n|\r|\n", StandardRegexOptions));
|
||||
|
||||
/*private static readonly Lazy<Regex> UnderscoreRegex = new Lazy<Regex>(() => new Regex(@"_", StandardRegexOptions));
|
||||
|
||||
private static readonly Lazy<Regex> CamelCaseRegEx = new Lazy<Regex>(() => new Regex(@"[a-z][A-Z]", StandardRegexOptions));
|
||||
|
||||
private static readonly Lazy<MatchEvaluator> SplitCamelCaseString = new Lazy<MatchEvaluator>(() => m => {
|
||||
String x = m.ToString();
|
||||
return x[0] + " " + x[1..];
|
||||
});
|
||||
|
||||
private static readonly Lazy<String[]> InvalidFilenameChars = new Lazy<String[]>(() => Path.GetInvalidFileNameChars().Select(c => c.ToString()).ToArray());*/
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
@ -82,22 +68,6 @@ namespace Swan {
|
||||
return new String(value.Where(c => Char.IsControl(c) == false || excludeChars.Contains(c)).ToArray());
|
||||
}
|
||||
|
||||
/*/// <summary>
|
||||
/// Removes all control characters from a string, including new line sequences.
|
||||
/// </summary>
|
||||
/// <param name="value">The input.</param>
|
||||
/// <returns>A <see cref="String" /> that represents the current object.</returns>
|
||||
/// <exception cref="ArgumentNullException">input.</exception>
|
||||
public static String RemoveControlChars(this String value) => value.RemoveControlCharsExcept(null);
|
||||
|
||||
/// <summary>
|
||||
/// Outputs JSON string representing this object.
|
||||
/// </summary>
|
||||
/// <param name="this">The object.</param>
|
||||
/// <param name="format">if set to <c>true</c> format the output.</param>
|
||||
/// <returns>A <see cref="String" /> that represents the current object.</returns>
|
||||
public static String ToJson(this Object @this, Boolean format = true) => @this == null ? String.Empty : Json.Serialize(@this, format);*/
|
||||
|
||||
/// <summary>
|
||||
/// Returns text representing the properties of the specified object in a human-readable format.
|
||||
/// While this method is fairly expensive computationally speaking, it provides an easy way to
|
||||
@ -171,43 +141,6 @@ namespace Swan {
|
||||
/// </returns>
|
||||
public static String[] ToLines(this String @this) => @this == null ? Array.Empty<String>() : SplitLinesRegex.Value.Split(@this);
|
||||
|
||||
/*/// <summary>
|
||||
/// Humanizes (make more human-readable) an identifier-style string
|
||||
/// in either camel case or snake case. For example, CamelCase will be converted to
|
||||
/// Camel Case and Snake_Case will be converted to Snake Case.
|
||||
/// </summary>
|
||||
/// <param name="value">The identifier-style string.</param>
|
||||
/// <returns>A <see cref="String" /> humanized.</returns>
|
||||
public static String Humanize(this String value) {
|
||||
if(value == null) {
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
String returnValue = UnderscoreRegex.Value.Replace(value, " ");
|
||||
returnValue = CamelCaseRegEx.Value.Replace(returnValue, SplitCamelCaseString.Value);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Humanizes (make more human-readable) an boolean.
|
||||
/// </summary>
|
||||
/// <param name="value">if set to <c>true</c> [value].</param>
|
||||
/// <returns>A <see cref="String" /> that represents the current boolean.</returns>
|
||||
public static String Humanize(this Boolean value) => value ? "Yes" : "No";
|
||||
|
||||
/// <summary>
|
||||
/// Humanizes (make more human-readable) the specified value.
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <returns>A <see cref="String" /> that represents the current object.</returns>
|
||||
public static String Humanize(this Object value) =>
|
||||
value switch
|
||||
{
|
||||
String stringValue => stringValue.Humanize(),
|
||||
Boolean boolValue => boolValue.Humanize(),
|
||||
_ => value.Stringify()
|
||||
};*/
|
||||
|
||||
/// <summary>
|
||||
/// Indents the specified multi-line text with the given amount of leading spaces
|
||||
/// per line.
|
||||
@ -270,99 +203,5 @@ namespace Swan {
|
||||
|
||||
return Tuple.Create(lineIndex + 1, colNumber);
|
||||
}
|
||||
|
||||
/*/// <summary>
|
||||
/// Makes the file name system safe.
|
||||
/// </summary>
|
||||
/// <param name="value">The s.</param>
|
||||
/// <returns>
|
||||
/// A string with a safe file name.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">s.</exception>
|
||||
public static String ToSafeFilename(this String value) => value == null ? throw new ArgumentNullException(nameof(value)) : InvalidFilenameChars.Value.Aggregate(value, (current, c) => current.Replace(c, String.Empty)).Slice(0, 220);
|
||||
|
||||
/// <summary>
|
||||
/// Formats a long into the closest bytes string.
|
||||
/// </summary>
|
||||
/// <param name="bytes">The bytes length.</param>
|
||||
/// <returns>
|
||||
/// The string representation of the current Byte object, formatted as specified by the format parameter.
|
||||
/// </returns>
|
||||
public static String FormatBytes(this Int64 bytes) => ((UInt64)bytes).FormatBytes();
|
||||
|
||||
/// <summary>
|
||||
/// Formats a long into the closest bytes string.
|
||||
/// </summary>
|
||||
/// <param name="bytes">The bytes length.</param>
|
||||
/// <returns>
|
||||
/// A copy of format in which the format items have been replaced by the string
|
||||
/// representations of the corresponding arguments.
|
||||
/// </returns>
|
||||
public static String FormatBytes(this UInt64 bytes) {
|
||||
Int32 i;
|
||||
Double dblSByte = bytes;
|
||||
|
||||
for(i = 0; i < ByteSuffixes.Length && bytes >= 1024; i++, bytes /= 1024) {
|
||||
dblSByte = bytes / 1024.0;
|
||||
}
|
||||
|
||||
return $"{dblSByte:0.##} {ByteSuffixes[i]}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Truncates the specified value.
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="maximumLength">The maximum length.</param>
|
||||
/// <returns>
|
||||
/// Retrieves a substring from this instance.
|
||||
/// The substring starts at a specified character position and has a specified length.
|
||||
/// </returns>
|
||||
public static String? Truncate(this String value, Int32 maximumLength) => Truncate(value, maximumLength, String.Empty);
|
||||
|
||||
/// <summary>
|
||||
/// Truncates the specified value and append the omission last.
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="maximumLength">The maximum length.</param>
|
||||
/// <param name="omission">The omission.</param>
|
||||
/// <returns>
|
||||
/// Retrieves a substring from this instance.
|
||||
/// The substring starts at a specified character position and has a specified length.
|
||||
/// </returns>
|
||||
public static String? Truncate(this String value, Int32 maximumLength, String omission) => value == null ? null : value.Length > maximumLength ? value.Substring(0, maximumLength) + (omission ?? String.Empty) : value;
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified <see cref="String"/> contains any of characters in
|
||||
/// the specified array of <see cref="Char"/>.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// <c>true</c> if <paramref name="value"/> contains any of <paramref name="chars"/>;
|
||||
/// otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
/// <param name="value">
|
||||
/// A <see cref="String"/> to test.
|
||||
/// </param>
|
||||
/// <param name="chars">
|
||||
/// An array of <see cref="Char"/> that contains characters to find.
|
||||
/// </param>
|
||||
public static Boolean Contains(this String value, params Char[] chars) => chars?.Length == 0 || !String.IsNullOrEmpty(value) && chars != null && value.IndexOfAny(chars) > -1;
|
||||
|
||||
/// <summary>
|
||||
/// Replaces all chars in a string.
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="replaceValue">The replace value.</param>
|
||||
/// <param name="chars">The chars.</param>
|
||||
/// <returns>The string with the characters replaced.</returns>
|
||||
public static String ReplaceAll(this String value, String replaceValue, params Char[] chars) => chars.Aggregate(value, (current, c) => current.Replace(new String(new[] { c }), replaceValue));
|
||||
|
||||
/// <summary>
|
||||
/// Convert hex character to an integer. Return -1 if char is something
|
||||
/// other than a hex char.
|
||||
/// </summary>
|
||||
/// <param name="value">The c.</param>
|
||||
/// <returns>Converted integer.</returns>
|
||||
public static Int32 Hex2Int(this Char value) => value >= '0' && value <= '9' ? value - '0' : value >= 'A' && value <= 'F' ? value - 'A' + 10 : value >= 'a' && value <= 'f' ? value - 'a' + 10 : -1;*/
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using Swan.Reflection;
|
||||
|
||||
namespace Swan {
|
||||
/// <summary>
|
||||
@ -30,110 +26,5 @@ namespace Swan {
|
||||
/// <returns>A value that indicates the relative order of the objects being compared.</returns>
|
||||
// [Obsolete("NEED",false)]
|
||||
public static Int32 Clamp(this Int32 @this, Int32 min, Int32 max) => @this < min ? min : (@this > max ? max : @this);
|
||||
/*
|
||||
/// <summary>
|
||||
/// Determines whether the specified value is between a minimum and a maximum value.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of value to check.</typeparam>
|
||||
/// <param name="this">The value.</param>
|
||||
/// <param name="min">The minimum.</param>
|
||||
/// <param name="max">The maximum.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the specified minimum is between; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public static Boolean IsBetween<T>(this T @this, T min, T max) where T : struct, IComparable => @this.CompareTo(min) >= 0 && @this.CompareTo(max) <= 0;
|
||||
|
||||
/// <summary>
|
||||
/// Converts an array of bytes into the given struct type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of structure to convert.</typeparam>
|
||||
/// <param name="this">The data.</param>
|
||||
/// <returns>a struct type derived from convert an array of bytes ref=ToStruct".</returns>
|
||||
public static T ToStruct<T>(this Byte[] @this) where T : struct => @this == null ? throw new ArgumentNullException(nameof(@this)) : ToStruct<T>(@this, 0, @this.Length);
|
||||
|
||||
/// <summary>
|
||||
/// Converts an array of bytes into the given struct type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of structure to convert.</typeparam>
|
||||
/// <param name="this">The data.</param>
|
||||
/// <param name="offset">The offset.</param>
|
||||
/// <param name="length">The length.</param>
|
||||
/// <returns>
|
||||
/// A managed object containing the data pointed to by the ptr parameter.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">data.</exception>
|
||||
public static T ToStruct<T>(this Byte[] @this, Int32 offset, Int32 length) where T : struct {
|
||||
if(@this == null) {
|
||||
throw new ArgumentNullException(nameof(@this));
|
||||
}
|
||||
|
||||
Byte[] buffer = new Byte[length];
|
||||
Array.Copy(@this, offset, buffer, 0, buffer.Length);
|
||||
GCHandle handle = GCHandle.Alloc(GetStructBytes<T>(buffer), GCHandleType.Pinned);
|
||||
|
||||
try {
|
||||
return Marshal.PtrToStructure<T>(handle.AddrOfPinnedObject());
|
||||
} finally {
|
||||
handle.Free();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a struct to an array of bytes.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of structure to convert.</typeparam>
|
||||
/// <param name="this">The object.</param>
|
||||
/// <returns>A byte array containing the results of encoding the specified set of characters.</returns>
|
||||
public static Byte[] ToBytes<T>(this T @this) where T : struct {
|
||||
Byte[] data = new Byte[Marshal.SizeOf(@this)];
|
||||
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
|
||||
|
||||
try {
|
||||
Marshal.StructureToPtr(@this, handle.AddrOfPinnedObject(), false);
|
||||
return GetStructBytes<T>(data);
|
||||
} finally {
|
||||
handle.Free();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Swaps the endianness of an unsigned long to an unsigned integer.
|
||||
/// </summary>
|
||||
/// <param name="this">The bytes contained in a long.</param>
|
||||
/// <returns>
|
||||
/// A 32-bit unsigned integer equivalent to the ulong
|
||||
/// contained in longBytes.
|
||||
/// </returns>
|
||||
public static UInt32 SwapEndianness(this UInt64 @this) => (UInt32)(((@this & 0x000000ff) << 24) + ((@this & 0x0000ff00) << 8) + ((@this & 0x00ff0000) >> 8) + ((@this & 0xff000000) >> 24));
|
||||
|
||||
private static Byte[] GetStructBytes<T>(Byte[] data) {
|
||||
if(data == null) {
|
||||
throw new ArgumentNullException(nameof(data));
|
||||
}
|
||||
|
||||
FieldInfo[] fields = typeof(T).GetTypeInfo()
|
||||
.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
StructEndiannessAttribute endian = AttributeCache.DefaultCache.Value.RetrieveOne<StructEndiannessAttribute, T>();
|
||||
|
||||
foreach(FieldInfo field in fields) {
|
||||
if(endian == null && !field.IsDefined(typeof(StructEndiannessAttribute), false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Int32 offset = Marshal.OffsetOf<T>(field.Name).ToInt32();
|
||||
Int32 length = Marshal.SizeOf(field.FieldType);
|
||||
|
||||
endian ??= AttributeCache.DefaultCache.Value.RetrieveOne<StructEndiannessAttribute>(field);
|
||||
|
||||
if(endian != null && (endian.Endianness == Endianness.Big && BitConverter.IsLittleEndian ||
|
||||
endian.Endianness == Endianness.Little && !BitConverter.IsLittleEndian)) {
|
||||
Array.Reverse(data, offset, length);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
@ -3,7 +3,6 @@ using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Swan.Lite.Reflection;
|
||||
using Swan.Mappers;
|
||||
@ -27,18 +26,6 @@ namespace Swan {
|
||||
/// </returns>
|
||||
public static Int32 CopyPropertiesTo<T>(this T source, Object? target, params String[]? ignoreProperties) where T : class => ObjectMapper.Copy(source, target, GetCopyableProperties(target), ignoreProperties);
|
||||
|
||||
/*/// <summary>
|
||||
/// Iterates over the public, instance, readable properties of the source and
|
||||
/// tries to write a compatible value to a public, instance, writable property in the destination.
|
||||
/// </summary>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="target">The destination.</param>
|
||||
/// <param name="propertiesToCopy">Properties to copy.</param>
|
||||
/// <returns>
|
||||
/// Number of properties that were successfully copied.
|
||||
/// </returns>
|
||||
public static Int32 CopyOnlyPropertiesTo(this Object source, Object target, params String[]? propertiesToCopy) => ObjectMapper.Copy(source, target, propertiesToCopy);*/
|
||||
|
||||
/// <summary>
|
||||
/// Copies the properties to new instance of T.
|
||||
/// </summary>
|
||||
@ -60,109 +47,6 @@ namespace Swan {
|
||||
return target;
|
||||
}
|
||||
|
||||
/*/// <summary>
|
||||
/// Copies the only properties to new instance of T.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Object Type.</typeparam>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="propertiesToCopy">The properties to copy.</param>
|
||||
/// <returns>
|
||||
/// The specified type with properties copied.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">source.</exception>
|
||||
public static T CopyOnlyPropertiesToNew<T>(this Object source, params String[] propertiesToCopy) where T : class {
|
||||
if(source == null) {
|
||||
throw new ArgumentNullException(nameof(source));
|
||||
}
|
||||
|
||||
T target = Activator.CreateInstance<T>();
|
||||
_ = ObjectMapper.Copy(source, target, propertiesToCopy);
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Iterates over the keys of the source and tries to write a compatible value to a public,
|
||||
/// instance, writable property in the destination.
|
||||
/// </summary>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="target">The target.</param>
|
||||
/// <param name="ignoreKeys">The ignore keys.</param>
|
||||
/// <returns>Number of properties that was copied successful.</returns>
|
||||
public static Int32 CopyKeyValuePairTo(this IDictionary<String, Object> source, Object? target, params String[] ignoreKeys) => source == null ? throw new ArgumentNullException(nameof(source)) : ObjectMapper.Copy(source, target, null, ignoreKeys);
|
||||
|
||||
/// <summary>
|
||||
/// Iterates over the keys of the source and tries to write a compatible value to a public,
|
||||
/// instance, writable property in the destination.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Object Type.</typeparam>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="ignoreKeys">The ignore keys.</param>
|
||||
/// <returns>
|
||||
/// The specified type with properties copied.
|
||||
/// </returns>
|
||||
public static T CopyKeyValuePairToNew<T>(this IDictionary<String, Object> source, params String[] ignoreKeys) {
|
||||
if(source == null) {
|
||||
throw new ArgumentNullException(nameof(source));
|
||||
}
|
||||
|
||||
T target = Activator.CreateInstance<T>();
|
||||
_ = source.CopyKeyValuePairTo(target, ignoreKeys);
|
||||
return target;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does the specified action.
|
||||
/// </summary>
|
||||
/// <param name="action">The action.</param>
|
||||
/// <param name="retryInterval">The retry interval.</param>
|
||||
/// <param name="retryCount">The retry count.</param>
|
||||
public static void Retry(this Action action, TimeSpan retryInterval = default, Int32 retryCount = 3) {
|
||||
if(action == null) {
|
||||
throw new ArgumentNullException(nameof(action));
|
||||
}
|
||||
|
||||
_ = Retry<Object?>(() => { action(); return null; }, retryInterval, retryCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does the specified action.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the source.</typeparam>
|
||||
/// <param name="action">The action.</param>
|
||||
/// <param name="retryInterval">The retry interval.</param>
|
||||
/// <param name="retryCount">The retry count.</param>
|
||||
/// <returns>
|
||||
/// The return value of the method that this delegate encapsulates.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">action.</exception>
|
||||
/// <exception cref="AggregateException">Represents one or many errors that occur during application execution.</exception>
|
||||
public static T Retry<T>(this Func<T> action, TimeSpan retryInterval = default, Int32 retryCount = 3) {
|
||||
if(action == null) {
|
||||
throw new ArgumentNullException(nameof(action));
|
||||
}
|
||||
|
||||
if(retryInterval == default) {
|
||||
retryInterval = TimeSpan.FromSeconds(1);
|
||||
}
|
||||
|
||||
global::System.Collections.Generic.List<global::System.Exception> exceptions = new List<Exception>();
|
||||
|
||||
for(Int32 retry = 0; retry < retryCount; retry++) {
|
||||
try {
|
||||
if(retry > 0) {
|
||||
Task.Delay(retryInterval).Wait();
|
||||
}
|
||||
|
||||
return action();
|
||||
} catch(Exception ex) {
|
||||
exceptions.Add(ex);
|
||||
}
|
||||
}
|
||||
|
||||
throw new AggregateException(exceptions);
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// Gets the copyable properties.
|
||||
///
|
||||
|
@ -124,7 +124,7 @@ namespace Swan.Formatters {
|
||||
|
||||
Dictionary<Tuple<String, String>, MemberInfo> value = fields.ToDictionary(x => Tuple.Create(x.Name, x.GetCustomAttribute<JsonPropertyAttribute>()?.PropertyName ?? x.Name.GetNameWithCase(this.JsonSerializerCase)), x => x);
|
||||
|
||||
TypeCache.TryAdd(targetType, value);
|
||||
_ = TypeCache.TryAdd(targetType, value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
@ -99,18 +99,6 @@ namespace Swan.Formatters {
|
||||
/// </example>
|
||||
public static String Serialize(Object? obj, Boolean format = false, String? typeSpecifier = null, Boolean includeNonPublic = false, String[]? includedNames = null, params String[] excludedNames) => Serialize(obj, format, typeSpecifier, includeNonPublic, includedNames, excludedNames, null, JsonSerializerCase.None);
|
||||
|
||||
/*/// <summary>
|
||||
/// Serializes the specified object into a JSON string.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object.</param>
|
||||
/// <param name="jsonSerializerCase">The json serializer case.</param>
|
||||
/// <param name="format">if set to <c>true</c> [format].</param>
|
||||
/// <param name="typeSpecifier">The type specifier.</param>
|
||||
/// <returns>
|
||||
/// A <see cref="System.String" /> that represents the current object.
|
||||
/// </returns>
|
||||
public static String Serialize(Object? obj, JsonSerializerCase jsonSerializerCase, Boolean format = false, String? typeSpecifier = null) => Serialize(obj, format, typeSpecifier, false, null, null, null, jsonSerializerCase);*/
|
||||
|
||||
/// <summary>
|
||||
/// Serializes the specified object into a JSON string.
|
||||
/// </summary>
|
||||
@ -145,68 +133,6 @@ namespace Swan.Formatters {
|
||||
/// </returns>
|
||||
public static String Serialize(Object? obj, SerializerOptions options) => Serializer.Serialize(obj, 0, options);
|
||||
|
||||
/*/// <summary>
|
||||
/// Serializes the specified object only including the specified property names.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object.</param>
|
||||
/// <param name="format">if set to <c>true</c> it formats and indents the output.</param>
|
||||
/// <param name="includeNames">The include names.</param>
|
||||
/// <returns>A <see cref="String" /> that represents the current object.</returns>
|
||||
/// <example>
|
||||
/// The following example shows how to serialize a simple object including the specified properties.
|
||||
/// <code>
|
||||
/// using Swan.Formatters;
|
||||
///
|
||||
/// class Example
|
||||
/// {
|
||||
/// static void Main()
|
||||
/// {
|
||||
/// // object to serialize
|
||||
/// var obj = new { One = "One", Two = "Two", Three = "Three" };
|
||||
///
|
||||
/// // the included names
|
||||
/// var includedNames = new[] { "Two", "Three" };
|
||||
///
|
||||
/// // serialize only the included names
|
||||
/// var data = Json.SerializeOnly(basicObject, true, includedNames);
|
||||
/// // {"Two": "Two","Three": "Three" }
|
||||
/// }
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
public static String SerializeOnly(Object? obj, Boolean format, params String[] includeNames) => Serialize(obj, new SerializerOptions(format, null, includeNames));
|
||||
|
||||
/// <summary>
|
||||
/// Serializes the specified object excluding the specified property names.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object.</param>
|
||||
/// <param name="format">if set to <c>true</c> it formats and indents the output.</param>
|
||||
/// <param name="excludeNames">The exclude names.</param>
|
||||
/// <returns>A <see cref="String" /> that represents the current object.</returns>
|
||||
/// <example>
|
||||
/// The following code shows how to serialize a simple object excluding the specified properties.
|
||||
/// <code>
|
||||
/// using Swan.Formatters;
|
||||
///
|
||||
/// class Example
|
||||
/// {
|
||||
/// static void Main()
|
||||
/// {
|
||||
/// // object to serialize
|
||||
/// var obj = new { One = "One", Two = "Two", Three = "Three" };
|
||||
///
|
||||
/// // the excluded names
|
||||
/// var excludeNames = new[] { "Two", "Three" };
|
||||
///
|
||||
/// // serialize excluding
|
||||
/// var data = Json.SerializeExcluding(basicObject, false, includedNames);
|
||||
/// // {"One": "One"}
|
||||
/// }
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
public static String SerializeExcluding(Object? obj, Boolean format, params String[] excludeNames) => Serialize(obj, new SerializerOptions(format, null, null, excludeNames));*/
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes the specified json string as either a Dictionary[string, object] or as a List[object]
|
||||
/// depending on the syntax of the JSON string.
|
||||
@ -258,54 +184,6 @@ namespace Swan.Formatters {
|
||||
/// </code></example>
|
||||
public static Object? Deserialize(String? json) => Deserialize(json, JsonSerializerCase.None);
|
||||
|
||||
/*/// <summary>
|
||||
/// Deserializes the specified JSON string and converts it to the specified object type.
|
||||
/// Non-public constructors and property setters are ignored.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of object to deserialize.</typeparam>
|
||||
/// <param name="json">The JSON string.</param>
|
||||
/// <param name="jsonSerializerCase">The JSON serializer case.</param>
|
||||
/// <returns>
|
||||
/// The deserialized specified type object.
|
||||
/// </returns>
|
||||
/// <example>
|
||||
/// The following code describes how to deserialize a JSON string into an object of type T.
|
||||
/// <code>
|
||||
/// using Swan.Formatters;
|
||||
/// class Example
|
||||
/// {
|
||||
/// static void Main()
|
||||
/// {
|
||||
/// // json type BasicJson to serialize
|
||||
/// var basicJson = "{\"One\":\"One\",\"Two\":\"Two\",\"Three\":\"Three\"}";
|
||||
/// // deserializes the specified string in a new instance of the type BasicJson.
|
||||
/// var data = Json.Deserialize<BasicJson>(basicJson);
|
||||
/// }
|
||||
/// }
|
||||
/// </code></example>
|
||||
public static T Deserialize<T>(String json, JsonSerializerCase jsonSerializerCase = JsonSerializerCase.None) where T : notnull => (T)Deserialize(json, typeof(T), jsonSerializerCase: jsonSerializerCase)!;
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes the specified JSON string and converts it to the specified object type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of object to deserialize.</typeparam>
|
||||
/// <param name="json">The JSON string.</param>
|
||||
/// <param name="includeNonPublic">if set to true, it also uses the non-public constructors and property setters.</param>
|
||||
/// <returns>The deserialized specified type object.</returns>
|
||||
public static T Deserialize<T>(String json, Boolean includeNonPublic) where T : notnull => (T)Deserialize(json, typeof(T), includeNonPublic)!;
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes the specified JSON string and converts it to the specified object type.
|
||||
/// </summary>
|
||||
/// <param name="json">The JSON string.</param>
|
||||
/// <param name="resultType">Type of the result.</param>
|
||||
/// <param name="includeNonPublic">if set to true, it also uses the non-public constructors and property setters.</param>
|
||||
/// <param name="jsonSerializerCase">The json serializer case.</param>
|
||||
/// <returns>
|
||||
/// Type of the current conversion from json result.
|
||||
/// </returns>
|
||||
public static Object? Deserialize(String json, Type resultType, Boolean includeNonPublic = false, JsonSerializerCase jsonSerializerCase = JsonSerializerCase.None) => Converter.FromJsonResult(Deserializer.DeserializeInternal(json), jsonSerializerCase, resultType, includeNonPublic);*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private API
|
||||
@ -315,17 +193,9 @@ namespace Swan.Formatters {
|
||||
return excludedNames;
|
||||
}
|
||||
|
||||
global::System.Collections.Generic.IEnumerable<global::System.String> excludedByAttr = IgnoredPropertiesCache.Retrieve(type, t => t.GetProperties()
|
||||
.Where(x => AttributeCache.DefaultCache.Value.RetrieveOne<JsonPropertyAttribute>(x)?.Ignored == true)
|
||||
.Select(x => x.Name));
|
||||
IEnumerable<global::System.String> excludedByAttr = IgnoredPropertiesCache.Retrieve(type, t => t.GetProperties().Where(x => AttributeCache.DefaultCache.Value.RetrieveOne<JsonPropertyAttribute>(x)?.Ignored == true).Select(x => x.Name));
|
||||
|
||||
if(excludedByAttr?.Any() != true) {
|
||||
return excludedNames;
|
||||
}
|
||||
|
||||
return excludedNames?.Any(String.IsNullOrWhiteSpace) == true
|
||||
? excludedByAttr.Intersect(excludedNames.Where(y => !String.IsNullOrWhiteSpace(y))).ToArray()
|
||||
: excludedByAttr.ToArray();
|
||||
return excludedByAttr?.Any() != true ? excludedNames : excludedNames?.Any(String.IsNullOrWhiteSpace) == true ? excludedByAttr.Intersect(excludedNames.Where(y => !String.IsNullOrWhiteSpace(y))).ToArray() : excludedByAttr.ToArray();
|
||||
}
|
||||
|
||||
private static String SerializePrimitiveValue(Object obj) => obj switch
|
||||
|
@ -7,16 +7,6 @@ namespace Swan.Formatters {
|
||||
/// <seealso cref="Attribute" />
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public sealed class JsonPropertyAttribute : Attribute {
|
||||
/*/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonPropertyAttribute" /> class.
|
||||
/// </summary>
|
||||
/// <param name="propertyName">Name of the property.</param>
|
||||
/// <param name="ignored">if set to <c>true</c> [ignored].</param>
|
||||
public JsonPropertyAttribute(String propertyName, Boolean ignored = false) {
|
||||
this.PropertyName = propertyName ?? throw new ArgumentNullException(nameof(propertyName));
|
||||
this.Ignored = ignored;
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the property.
|
||||
/// </summary>
|
||||
|
@ -22,16 +22,7 @@ namespace Swan {
|
||||
/// <param name="callerMemberName">Name of the caller member.</param>
|
||||
/// <param name="callerFilePath">The caller file path.</param>
|
||||
/// <param name="callerLineNumber">The caller line number.</param>
|
||||
public LogMessageReceivedEventArgs(
|
||||
UInt64 sequence,
|
||||
LogLevel messageType,
|
||||
DateTime utcDate,
|
||||
String source,
|
||||
String message,
|
||||
Object? extendedData,
|
||||
String callerMemberName,
|
||||
String callerFilePath,
|
||||
Int32 callerLineNumber) {
|
||||
public LogMessageReceivedEventArgs(UInt64 sequence, LogLevel messageType, DateTime utcDate, String source, String message, Object? extendedData, String callerMemberName, String callerFilePath, Int32 callerLineNumber) {
|
||||
this.Sequence = sequence;
|
||||
this.MessageType = messageType;
|
||||
this.UtcDate = utcDate;
|
||||
|
@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@ -28,306 +27,7 @@ namespace Swan.Logging {
|
||||
}
|
||||
}
|
||||
|
||||
/*#region Standard Public API
|
||||
|
||||
/// <summary>
|
||||
/// Registers the logger.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of logger to register.</typeparam>
|
||||
/// <exception cref="InvalidOperationException">There is already a logger with that class registered.</exception>
|
||||
public static void RegisterLogger<T>() where T : ILogger {
|
||||
lock(SyncLock) {
|
||||
ILogger loggerInstance = Loggers.FirstOrDefault(x => x.GetType() == typeof(T));
|
||||
|
||||
if(loggerInstance != null) {
|
||||
throw new InvalidOperationException("There is already a logger with that class registered.");
|
||||
}
|
||||
|
||||
Loggers.Add(Activator.CreateInstance<T>());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers the logger.
|
||||
/// </summary>
|
||||
/// <param name="logger">The logger.</param>
|
||||
public static void RegisterLogger(ILogger logger) {
|
||||
lock(SyncLock) {
|
||||
Loggers.Add(logger);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters the logger.
|
||||
/// </summary>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">logger.</exception>
|
||||
public static void UnregisterLogger(ILogger logger) => RemoveLogger(x => x == logger);
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters the logger.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of logger to unregister.</typeparam>
|
||||
public static void UnregisterLogger<T>() => RemoveLogger(x => x.GetType() == typeof(T));
|
||||
|
||||
/// <summary>
|
||||
/// Remove all the loggers.
|
||||
/// </summary>
|
||||
public static void NoLogging() {
|
||||
lock(SyncLock) {
|
||||
Loggers.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
#region Debug
|
||||
|
||||
/// <summary>
|
||||
/// Logs a debug message to the console.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="extendedData">The extended data.</param>
|
||||
/// <param name="callerMemberName">Name of the caller member. This is automatically populated.</param>
|
||||
/// <param name="callerFilePath">The caller file path. This is automatically populated.</param>
|
||||
/// <param name="callerLineNumber">The caller line number. This is automatically populated.</param>
|
||||
public static void Debug(this String message, String source = null, Object extendedData = null, [CallerMemberName] String callerMemberName = "", [CallerFilePath] String callerFilePath = "", [CallerLineNumber] Int32 callerLineNumber = 0) => LogMessage(LogLevel.Debug, message, source, extendedData, callerMemberName, callerFilePath, callerLineNumber);
|
||||
|
||||
/// <summary>
|
||||
/// Logs a debug message to the console.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="extendedData">The extended data.</param>
|
||||
/// <param name="callerMemberName">Name of the caller member.</param>
|
||||
/// <param name="callerFilePath">The caller file path.</param>
|
||||
/// <param name="callerLineNumber">The caller line number.</param>
|
||||
public static void Debug(this String message, Type source, Object extendedData = null, [CallerMemberName] String callerMemberName = "", [CallerFilePath] String callerFilePath = "", [CallerLineNumber] Int32 callerLineNumber = 0) => LogMessage(LogLevel.Debug, message, source?.FullName, extendedData, callerMemberName, callerFilePath, callerLineNumber);
|
||||
|
||||
/// <summary>
|
||||
/// Logs a debug message to the console.
|
||||
/// </summary>
|
||||
/// <param name="extendedData">The exception.</param>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <param name="callerMemberName">Name of the caller member. This is automatically populated.</param>
|
||||
/// <param name="callerFilePath">The caller file path. This is automatically populated.</param>
|
||||
/// <param name="callerLineNumber">The caller line number. This is automatically populated.</param>
|
||||
public static void Debug(this Exception extendedData, String source, String message, [CallerMemberName] String callerMemberName = "", [CallerFilePath] String callerFilePath = "", [CallerLineNumber] Int32 callerLineNumber = 0) => LogMessage(LogLevel.Debug, message, source, extendedData, callerMemberName, callerFilePath, callerLineNumber);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Trace
|
||||
|
||||
/// <summary>
|
||||
/// Logs a trace message to the console.
|
||||
/// </summary>
|
||||
/// <param name="message">The text.</param>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="extendedData">The extended data.</param>
|
||||
/// <param name="callerMemberName">Name of the caller member. This is automatically populated.</param>
|
||||
/// <param name="callerFilePath">The caller file path. This is automatically populated.</param>
|
||||
/// <param name="callerLineNumber">The caller line number. This is automatically populated.</param>
|
||||
public static void Trace(this String message, String source = null, Object extendedData = null, [CallerMemberName] String callerMemberName = "", [CallerFilePath] String callerFilePath = "", [CallerLineNumber] Int32 callerLineNumber = 0) => LogMessage(LogLevel.Trace, message, source, extendedData, callerMemberName, callerFilePath, callerLineNumber);
|
||||
|
||||
/// <summary>
|
||||
/// Logs a trace message to the console.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="extendedData">The extended data.</param>
|
||||
/// <param name="callerMemberName">Name of the caller member.</param>
|
||||
/// <param name="callerFilePath">The caller file path.</param>
|
||||
/// <param name="callerLineNumber">The caller line number.</param>
|
||||
public static void Trace(this String message, Type source, Object extendedData = null, [CallerMemberName] String callerMemberName = "", [CallerFilePath] String callerFilePath = "", [CallerLineNumber] Int32 callerLineNumber = 0) => LogMessage(LogLevel.Trace, message, source?.FullName, extendedData, callerMemberName, callerFilePath, callerLineNumber);
|
||||
|
||||
/// <summary>
|
||||
/// Logs a trace message to the console.
|
||||
/// </summary>
|
||||
/// <param name="extendedData">The extended data.</param>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <param name="callerMemberName">Name of the caller member. This is automatically populated.</param>
|
||||
/// <param name="callerFilePath">The caller file path. This is automatically populated.</param>
|
||||
/// <param name="callerLineNumber">The caller line number. This is automatically populated.</param>
|
||||
public static void Trace(this Exception extendedData, String source, String message, [CallerMemberName] String callerMemberName = "", [CallerFilePath] String callerFilePath = "", [CallerLineNumber] Int32 callerLineNumber = 0) => LogMessage(LogLevel.Trace, message, source, extendedData, callerMemberName, callerFilePath, callerLineNumber);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Warn
|
||||
|
||||
/// <summary>
|
||||
/// Logs a warning message to the console.
|
||||
/// </summary>
|
||||
/// <param name="message">The text.</param>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="extendedData">The extended data.</param>
|
||||
/// <param name="callerMemberName">Name of the caller member. This is automatically populated.</param>
|
||||
/// <param name="callerFilePath">The caller file path. This is automatically populated.</param>
|
||||
/// <param name="callerLineNumber">The caller line number. This is automatically populated.</param>
|
||||
public static void Warn(this String message, String source = null, Object extendedData = null, [CallerMemberName] String callerMemberName = "", [CallerFilePath] String callerFilePath = "", [CallerLineNumber] Int32 callerLineNumber = 0) => LogMessage(LogLevel.Warning, message, source, extendedData, callerMemberName, callerFilePath, callerLineNumber);
|
||||
|
||||
/// <summary>
|
||||
/// Logs a warning message to the console.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="extendedData">The extended data.</param>
|
||||
/// <param name="callerMemberName">Name of the caller member.</param>
|
||||
/// <param name="callerFilePath">The caller file path.</param>
|
||||
/// <param name="callerLineNumber">The caller line number.</param>
|
||||
public static void Warn(this String message, Type source, Object extendedData = null, [CallerMemberName] String callerMemberName = "", [CallerFilePath] String callerFilePath = "", [CallerLineNumber] Int32 callerLineNumber = 0) => LogMessage(LogLevel.Warning, message, source?.FullName, extendedData, callerMemberName, callerFilePath, callerLineNumber);
|
||||
|
||||
/// <summary>
|
||||
/// Logs a warning message to the console.
|
||||
/// </summary>
|
||||
/// <param name="extendedData">The extended data.</param>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <param name="callerMemberName">Name of the caller member. This is automatically populated.</param>
|
||||
/// <param name="callerFilePath">The caller file path. This is automatically populated.</param>
|
||||
/// <param name="callerLineNumber">The caller line number. This is automatically populated.</param>
|
||||
public static void Warn(this Exception extendedData, String source, String message, [CallerMemberName] String callerMemberName = "", [CallerFilePath] String callerFilePath = "", [CallerLineNumber] Int32 callerLineNumber = 0) => LogMessage(LogLevel.Warning, message, source, extendedData, callerMemberName, callerFilePath, callerLineNumber);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Fatal
|
||||
|
||||
/// <summary>
|
||||
/// Logs a warning message to the console.
|
||||
/// </summary>
|
||||
/// <param name="message">The text.</param>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="extendedData">The extended data.</param>
|
||||
/// <param name="callerMemberName">Name of the caller member. This is automatically populated.</param>
|
||||
/// <param name="callerFilePath">The caller file path. This is automatically populated.</param>
|
||||
/// <param name="callerLineNumber">The caller line number. This is automatically populated.</param>
|
||||
public static void Fatal(this String message, String source = null, Object extendedData = null, [CallerMemberName] String callerMemberName = "", [CallerFilePath] String callerFilePath = "", [CallerLineNumber] Int32 callerLineNumber = 0) => LogMessage(LogLevel.Fatal, message, source, extendedData, callerMemberName, callerFilePath, callerLineNumber);
|
||||
|
||||
/// <summary>
|
||||
/// Logs a warning message to the console.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="extendedData">The extended data.</param>
|
||||
/// <param name="callerMemberName">Name of the caller member.</param>
|
||||
/// <param name="callerFilePath">The caller file path.</param>
|
||||
/// <param name="callerLineNumber">The caller line number.</param>
|
||||
public static void Fatal(this String message, Type source, Object extendedData = null, [CallerMemberName] String callerMemberName = "", [CallerFilePath] String callerFilePath = "", [CallerLineNumber] Int32 callerLineNumber = 0) => LogMessage(LogLevel.Fatal, message, source?.FullName, extendedData, callerMemberName, callerFilePath, callerLineNumber);
|
||||
|
||||
/// <summary>
|
||||
/// Logs a warning message to the console.
|
||||
/// </summary>
|
||||
/// <param name="extendedData">The extended data.</param>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <param name="callerMemberName">Name of the caller member. This is automatically populated.</param>
|
||||
/// <param name="callerFilePath">The caller file path. This is automatically populated.</param>
|
||||
/// <param name="callerLineNumber">The caller line number. This is automatically populated.</param>
|
||||
public static void Fatal(this Exception extendedData, String source, String message, [CallerMemberName] String callerMemberName = "", [CallerFilePath] String callerFilePath = "", [CallerLineNumber] Int32 callerLineNumber = 0) => LogMessage(LogLevel.Fatal, message, source, extendedData, callerMemberName, callerFilePath, callerLineNumber);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Info
|
||||
|
||||
/// <summary>
|
||||
/// Logs an info message to the console.
|
||||
/// </summary>
|
||||
/// <param name="message">The text.</param>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="extendedData">The extended data.</param>
|
||||
/// <param name="callerMemberName">Name of the caller member. This is automatically populated.</param>
|
||||
/// <param name="callerFilePath">The caller file path. This is automatically populated.</param>
|
||||
/// <param name="callerLineNumber">The caller line number. This is automatically populated.</param>
|
||||
public static void Info(this String message, String source = null, Object extendedData = null, [CallerMemberName] String callerMemberName = "", [CallerFilePath] String callerFilePath = "", [CallerLineNumber] Int32 callerLineNumber = 0) => LogMessage(LogLevel.Info, message, source, extendedData, callerMemberName, callerFilePath, callerLineNumber);
|
||||
|
||||
/// <summary>
|
||||
/// Logs an info message to the console.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="extendedData">The extended data.</param>
|
||||
/// <param name="callerMemberName">Name of the caller member.</param>
|
||||
/// <param name="callerFilePath">The caller file path.</param>
|
||||
/// <param name="callerLineNumber">The caller line number.</param>
|
||||
public static void Info(this String message, Type source, Object extendedData = null, [CallerMemberName] String callerMemberName = "", [CallerFilePath] String callerFilePath = "", [CallerLineNumber] Int32 callerLineNumber = 0) => LogMessage(LogLevel.Info, message, source?.FullName, extendedData, callerMemberName, callerFilePath, callerLineNumber);
|
||||
|
||||
/// <summary>
|
||||
/// Logs an info message to the console.
|
||||
/// </summary>
|
||||
/// <param name="extendedData">The extended data.</param>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <param name="callerMemberName">Name of the caller member. This is automatically populated.</param>
|
||||
/// <param name="callerFilePath">The caller file path. This is automatically populated.</param>
|
||||
/// <param name="callerLineNumber">The caller line number. This is automatically populated.</param>
|
||||
public static void Info(this Exception extendedData, String source, String message, [CallerMemberName] String callerMemberName = "", [CallerFilePath] String callerFilePath = "", [CallerLineNumber] Int32 callerLineNumber = 0) => LogMessage(LogLevel.Info, message, source, extendedData, callerMemberName, callerFilePath, callerLineNumber);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Error
|
||||
|
||||
/// <summary>
|
||||
/// Logs an error message to the console's standard error.
|
||||
/// </summary>
|
||||
/// <param name="message">The text.</param>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="extendedData">The extended data.</param>
|
||||
/// <param name="callerMemberName">Name of the caller member. This is automatically populated.</param>
|
||||
/// <param name="callerFilePath">The caller file path. This is automatically populated.</param>
|
||||
/// <param name="callerLineNumber">The caller line number. This is automatically populated.</param>
|
||||
public static void Error(this String message, String source = null, Object extendedData = null, [CallerMemberName] String callerMemberName = "", [CallerFilePath] String callerFilePath = "", [CallerLineNumber] Int32 callerLineNumber = 0) => LogMessage(LogLevel.Error, message, source, extendedData, callerMemberName, callerFilePath, callerLineNumber);
|
||||
|
||||
/// <summary>
|
||||
/// Logs an error message to the console's standard error.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="extendedData">The extended data.</param>
|
||||
/// <param name="callerMemberName">Name of the caller member.</param>
|
||||
/// <param name="callerFilePath">The caller file path.</param>
|
||||
/// <param name="callerLineNumber">The caller line number.</param>
|
||||
public static void Error(this String message, Type source, Object extendedData = null, [CallerMemberName] String callerMemberName = "", [CallerFilePath] String callerFilePath = "", [CallerLineNumber] Int32 callerLineNumber = 0) => LogMessage(LogLevel.Error, message, source?.FullName, extendedData, callerMemberName, callerFilePath, callerLineNumber);
|
||||
|
||||
/// <summary>
|
||||
/// Logs an error message to the console's standard error.
|
||||
/// </summary>
|
||||
/// <param name="ex">The exception.</param>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <param name="callerMemberName">Name of the caller member. This is automatically populated.</param>
|
||||
/// <param name="callerFilePath">The caller file path. This is automatically populated.</param>
|
||||
/// <param name="callerLineNumber">The caller line number. This is automatically populated.</param>
|
||||
public static void Error(this Exception ex, String source, String message, [CallerMemberName] String callerMemberName = "", [CallerFilePath] String callerFilePath = "", [CallerLineNumber] Int32 callerLineNumber = 0) => LogMessage(LogLevel.Error, message, source, ex, callerMemberName, callerFilePath, callerLineNumber);
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion*/
|
||||
|
||||
#region Extended Public API
|
||||
|
||||
/*/// <summary>
|
||||
/// Logs the specified message.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="messageType">Type of the message.</param>
|
||||
/// <param name="extendedData">The extended data.</param>
|
||||
/// <param name="callerMemberName">Name of the caller member. This is automatically populated.</param>
|
||||
/// <param name="callerFilePath">The caller file path. This is automatically populated.</param>
|
||||
/// <param name="callerLineNumber">The caller line number. This is automatically populated.</param>
|
||||
public static void Log(this String message, String source, LogLevel messageType, Object extendedData = null, [CallerMemberName] String callerMemberName = "", [CallerFilePath] String callerFilePath = "", [CallerLineNumber] Int32 callerLineNumber = 0) => LogMessage(messageType, message, source, extendedData, callerMemberName, callerFilePath, callerLineNumber);
|
||||
|
||||
/// <summary>
|
||||
/// Logs the specified message.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="messageType">Type of the message.</param>
|
||||
/// <param name="extendedData">The extended data.</param>
|
||||
/// <param name="callerMemberName">Name of the caller member.</param>
|
||||
/// <param name="callerFilePath">The caller file path.</param>
|
||||
/// <param name="callerLineNumber">The caller line number.</param>
|
||||
public static void Log(this String message, Type source, LogLevel messageType, Object extendedData = null, [CallerMemberName] String callerMemberName = "", [CallerFilePath] String callerFilePath = "", [CallerLineNumber] Int32 callerLineNumber = 0) => LogMessage(messageType, message, source?.FullName, extendedData, callerMemberName, callerFilePath, callerLineNumber);*/
|
||||
#region Extended Public API
|
||||
|
||||
/// <summary>
|
||||
/// Logs an error message to the console's standard error.
|
||||
@ -341,70 +41,7 @@ namespace Swan.Logging {
|
||||
// [Obsolete("NEED", false)]
|
||||
public static void Log(this Exception ex, String source = null, String message = null, [CallerMemberName] String callerMemberName = "", [CallerFilePath] String callerFilePath = "", [CallerLineNumber] Int32 callerLineNumber = 0) => LogMessage(LogLevel.Error, message ?? ex.Message, source ?? ex.Source, ex, callerMemberName, callerFilePath, callerLineNumber);
|
||||
|
||||
/*/// <summary>
|
||||
/// Logs an error message to the console's standard error.
|
||||
/// </summary>
|
||||
/// <param name="ex">The ex.</param>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <param name="callerMemberName">Name of the caller member. This is automatically populated.</param>
|
||||
/// <param name="callerFilePath">The caller file path. This is automatically populated.</param>
|
||||
/// <param name="callerLineNumber">The caller line number. This is automatically populated.</param>
|
||||
public static void Log(this Exception ex, Type source = null, String message = null, [CallerMemberName] String callerMemberName = "", [CallerFilePath] String callerFilePath = "", [CallerLineNumber] Int32 callerLineNumber = 0) => LogMessage(LogLevel.Error, message ?? ex.Message, source?.FullName ?? ex.Source, ex, callerMemberName, callerFilePath, callerLineNumber);
|
||||
|
||||
/// <summary>
|
||||
/// Logs a trace message showing all possible non-null properties of the given object
|
||||
/// This method is expensive as it uses Stringify internally.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object.</param>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="text">The title.</param>
|
||||
/// <param name="callerMemberName">Name of the caller member. This is automatically populated.</param>
|
||||
/// <param name="callerFilePath">The caller file path. This is automatically populated.</param>
|
||||
/// <param name="callerLineNumber">The caller line number. This is automatically populated.</param>
|
||||
public static void Dump(this Object obj, String source, String text = "Object Dump", [CallerMemberName] String callerMemberName = "", [CallerFilePath] String callerFilePath = "", [CallerLineNumber] Int32 callerLineNumber = 0) {
|
||||
if(obj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String message = $"{text} ({obj.GetType()}): {Environment.NewLine}{obj.Stringify().Indent(5)}";
|
||||
LogMessage(LogLevel.Trace, message, source, obj, callerMemberName, callerFilePath, callerLineNumber);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs a trace message showing all possible non-null properties of the given object
|
||||
/// This method is expensive as it uses Stringify internally.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object.</param>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="text">The text.</param>
|
||||
/// <param name="callerMemberName">Name of the caller member.</param>
|
||||
/// <param name="callerFilePath">The caller file path.</param>
|
||||
/// <param name="callerLineNumber">The caller line number.</param>
|
||||
public static void Dump(this Object obj, Type source, String text = "Object Dump", [CallerMemberName] String callerMemberName = "", [CallerFilePath] String callerFilePath = "", [CallerLineNumber] Int32 callerLineNumber = 0) {
|
||||
if(obj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String message = $"{text} ({obj.GetType()}): {Environment.NewLine}{obj.Stringify().Indent(5)}";
|
||||
LogMessage(LogLevel.Trace, message, source?.FullName, obj, callerMemberName, callerFilePath, callerLineNumber);
|
||||
}*/
|
||||
|
||||
#endregion
|
||||
|
||||
/*private static void RemoveLogger(Func<ILogger, Boolean> criteria) {
|
||||
lock(SyncLock) {
|
||||
ILogger loggerInstance = Loggers.FirstOrDefault(criteria);
|
||||
|
||||
if(loggerInstance == null) {
|
||||
throw new InvalidOperationException("The logger is not registered.");
|
||||
}
|
||||
|
||||
loggerInstance.Dispose();
|
||||
|
||||
_ = Loggers.Remove(loggerInstance);
|
||||
}
|
||||
}*/
|
||||
#endregion
|
||||
|
||||
// [Obsolete("NEED", false)]
|
||||
private static void LogMessage(LogLevel logLevel, String message, String sourceName, Object extendedData, String callerMemberName, String callerFilePath, Int32 callerLineNumber) {
|
||||
|
@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Swan.Mappers {
|
||||
@ -32,78 +31,5 @@ namespace Swan.Mappers {
|
||||
public Type DestinationType {
|
||||
get;
|
||||
}
|
||||
|
||||
/*/// <summary>
|
||||
/// Maps the property.
|
||||
/// </summary>
|
||||
/// <typeparam name="TDestinationProperty">The type of the destination property.</typeparam>
|
||||
/// <typeparam name="TSourceProperty">The type of the source property.</typeparam>
|
||||
/// <param name="destinationProperty">The destination property.</param>
|
||||
/// <param name="sourceProperty">The source property.</param>
|
||||
/// <returns>
|
||||
/// An object map representation of type of the destination property
|
||||
/// and type of the source property.
|
||||
/// </returns>
|
||||
public ObjectMap<TSource, TDestination> MapProperty<TDestinationProperty, TSourceProperty>(Expression<Func<TDestination, TDestinationProperty>> destinationProperty, Expression<Func<TSource, TSourceProperty>> sourceProperty) {
|
||||
PropertyInfo propertyDestinationInfo = (destinationProperty.Body as MemberExpression)?.Member as PropertyInfo;
|
||||
|
||||
if(propertyDestinationInfo == null) {
|
||||
throw new ArgumentException("Invalid destination expression", nameof(destinationProperty));
|
||||
}
|
||||
|
||||
List<PropertyInfo> sourceMembers = GetSourceMembers(sourceProperty);
|
||||
|
||||
if(sourceMembers.Any() == false) {
|
||||
throw new ArgumentException("Invalid source expression", nameof(sourceProperty));
|
||||
}
|
||||
|
||||
// reverse order
|
||||
sourceMembers.Reverse();
|
||||
this.Map[propertyDestinationInfo] = sourceMembers;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the map property.
|
||||
/// </summary>
|
||||
/// <typeparam name="TDestinationProperty">The type of the destination property.</typeparam>
|
||||
/// <param name="destinationProperty">The destination property.</param>
|
||||
/// <returns>
|
||||
/// An object map representation of type of the destination property
|
||||
/// and type of the source property.
|
||||
/// </returns>
|
||||
/// <exception cref="System.Exception">Invalid destination expression.</exception>
|
||||
public ObjectMap<TSource, TDestination> RemoveMapProperty<TDestinationProperty>(Expression<Func<TDestination, TDestinationProperty>> destinationProperty) {
|
||||
PropertyInfo propertyDestinationInfo = (destinationProperty.Body as MemberExpression)?.Member as PropertyInfo;
|
||||
|
||||
if(propertyDestinationInfo == null) {
|
||||
throw new ArgumentException("Invalid destination expression", nameof(destinationProperty));
|
||||
}
|
||||
|
||||
if(this.Map.ContainsKey(propertyDestinationInfo)) {
|
||||
_ = this.Map.Remove(propertyDestinationInfo);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private static List<PropertyInfo> GetSourceMembers<TSourceProperty>(Expression<Func<TSource, TSourceProperty>> sourceProperty) {
|
||||
List<PropertyInfo> sourceMembers = new List<PropertyInfo>();
|
||||
MemberExpression initialExpression = sourceProperty.Body as MemberExpression;
|
||||
|
||||
while(true) {
|
||||
PropertyInfo propertySourceInfo = initialExpression?.Member as PropertyInfo;
|
||||
|
||||
if(propertySourceInfo == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
sourceMembers.Add(propertySourceInfo);
|
||||
initialExpression = initialExpression.Expression as MemberExpression;
|
||||
}
|
||||
|
||||
return sourceMembers;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
@ -1,20 +0,0 @@
|
||||
/*using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Swan.Mappers {
|
||||
/// <summary>
|
||||
/// Represents an AutoMapper-like object to map from one object type
|
||||
/// to another using defined properties map or using the default behaviour
|
||||
/// to copy same named properties from one object to another.
|
||||
///
|
||||
/// The extension methods like CopyPropertiesTo use the default behaviour.
|
||||
/// </summary>
|
||||
public partial class ObjectMapper {
|
||||
internal class PropertyInfoComparer : IEqualityComparer<PropertyInfo> {
|
||||
public Boolean Equals(PropertyInfo x, PropertyInfo y) => x != null && y != null && x.Name == y.Name && x.PropertyType == y.PropertyType;
|
||||
|
||||
public Int32 GetHashCode(PropertyInfo obj) => obj.Name.GetHashCode() + obj.PropertyType.Name.GetHashCode();
|
||||
}
|
||||
}
|
||||
}*/
|
@ -79,18 +79,6 @@ namespace Swan.Mappers {
|
||||
/// </code>
|
||||
/// </example>
|
||||
public partial class ObjectMapper {
|
||||
/*private static readonly Lazy<ObjectMapper> LazyInstance = new Lazy<ObjectMapper>(() => new ObjectMapper());
|
||||
|
||||
private readonly List<IObjectMap> _maps = new List<IObjectMap>();*/
|
||||
|
||||
/*/// <summary>
|
||||
/// Gets the current.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The current.
|
||||
/// </value>
|
||||
public static ObjectMapper Current => LazyInstance.Value;*/
|
||||
|
||||
/// <summary>
|
||||
/// Copies the specified source.
|
||||
/// </summary>
|
||||
@ -145,78 +133,6 @@ namespace Swan.Mappers {
|
||||
return CopyInternal(target, source.ToDictionary(x => x.Key.ToLowerInvariant(), x => Tuple.Create(typeof(Object), x.Value)), propertiesToCopy, ignoreProperties);
|
||||
}
|
||||
|
||||
/*/// <summary>
|
||||
/// Creates the map.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The type of the source.</typeparam>
|
||||
/// <typeparam name="TDestination">The type of the destination.</typeparam>
|
||||
/// <returns>
|
||||
/// An object map representation of type of the destination property
|
||||
/// and type of the source property.
|
||||
/// </returns>
|
||||
/// <exception cref="InvalidOperationException">
|
||||
/// You can't create an existing map
|
||||
/// or
|
||||
/// Types doesn't match.
|
||||
/// </exception>
|
||||
public ObjectMap<TSource, TDestination> CreateMap<TSource, TDestination>() {
|
||||
if(this._maps.Any(x => x.SourceType == typeof(TSource) && x.DestinationType == typeof(TDestination))) {
|
||||
throw new InvalidOperationException("You can't create an existing map");
|
||||
}
|
||||
|
||||
IEnumerable<PropertyInfo> sourceType = PropertyTypeCache.DefaultCache.Value.RetrieveAllProperties<TSource>(true);
|
||||
IEnumerable<PropertyInfo> destinationType = PropertyTypeCache.DefaultCache.Value.RetrieveAllProperties<TDestination>(true);
|
||||
|
||||
PropertyInfo[] intersect = sourceType.Intersect(destinationType, new PropertyInfoComparer()).ToArray();
|
||||
|
||||
if(!intersect.Any()) {
|
||||
throw new InvalidOperationException("Types doesn't match");
|
||||
}
|
||||
|
||||
ObjectMap<TSource, TDestination> map = new ObjectMap<TSource, TDestination>(intersect);
|
||||
|
||||
this._maps.Add(map);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps the specified source.
|
||||
/// </summary>
|
||||
/// <typeparam name="TDestination">The type of the destination.</typeparam>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="autoResolve">if set to <c>true</c> [automatic resolve].</param>
|
||||
/// <returns>
|
||||
/// A new instance of the map.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">source.</exception>
|
||||
/// <exception cref="InvalidOperationException">You can't map from type {source.GetType().Name} to {typeof(TDestination).Name}.</exception>
|
||||
public TDestination Map<TDestination>(Object source, Boolean autoResolve = true) {
|
||||
if(source == null) {
|
||||
throw new ArgumentNullException(nameof(source));
|
||||
}
|
||||
|
||||
TDestination destination = Activator.CreateInstance<TDestination>();
|
||||
IObjectMap map = this._maps.FirstOrDefault(x => x.SourceType == source.GetType() && x.DestinationType == typeof(TDestination));
|
||||
|
||||
if(map != null) {
|
||||
foreach(KeyValuePair<PropertyInfo, List<PropertyInfo>> property in map.Map) {
|
||||
Object finalSource = property.Value.Aggregate(source, (current, sourceProperty) => sourceProperty.GetValue(current)!);
|
||||
|
||||
property.Key.SetValue(destination, finalSource);
|
||||
}
|
||||
} else {
|
||||
if(!autoResolve) {
|
||||
throw new InvalidOperationException($"You can't map from type {source.GetType().Name} to {typeof(TDestination).Name}");
|
||||
}
|
||||
|
||||
// Missing mapping, try to use default behavior
|
||||
_ = Copy(source, destination);
|
||||
}
|
||||
|
||||
return destination;
|
||||
}*/
|
||||
|
||||
private static Int32 CopyInternal(Object target, Dictionary<String, Tuple<Type, Object>> sourceProperties, IEnumerable<String>? propertiesToCopy, IEnumerable<String>? ignoreProperties) {
|
||||
// Filter properties
|
||||
IEnumerable<String>? requiredProperties = propertiesToCopy?.Where(p => !String.IsNullOrWhiteSpace(p)).Select(p => p.ToLowerInvariant());
|
||||
|
@ -1,96 +0,0 @@
|
||||
/*using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Swan.Net.Dns {
|
||||
/// <summary>
|
||||
/// DnsClient public interfaces.
|
||||
/// </summary>
|
||||
internal partial class DnsClient {
|
||||
public interface IDnsMessage {
|
||||
IList<DnsQuestion> Questions {
|
||||
get;
|
||||
}
|
||||
|
||||
Int32 Size {
|
||||
get;
|
||||
}
|
||||
Byte[] ToArray();
|
||||
}
|
||||
|
||||
public interface IDnsMessageEntry {
|
||||
DnsDomain Name {
|
||||
get;
|
||||
}
|
||||
DnsRecordType Type {
|
||||
get;
|
||||
}
|
||||
DnsRecordClass Class {
|
||||
get;
|
||||
}
|
||||
|
||||
Int32 Size {
|
||||
get;
|
||||
}
|
||||
Byte[] ToArray();
|
||||
}
|
||||
|
||||
public interface IDnsResourceRecord : IDnsMessageEntry {
|
||||
TimeSpan TimeToLive {
|
||||
get;
|
||||
}
|
||||
Int32 DataLength {
|
||||
get;
|
||||
}
|
||||
Byte[] Data {
|
||||
get;
|
||||
}
|
||||
}
|
||||
|
||||
public interface IDnsRequest : IDnsMessage {
|
||||
Int32 Id {
|
||||
get; set;
|
||||
}
|
||||
DnsOperationCode OperationCode {
|
||||
get; set;
|
||||
}
|
||||
Boolean RecursionDesired {
|
||||
get; set;
|
||||
}
|
||||
}
|
||||
|
||||
public interface IDnsResponse : IDnsMessage {
|
||||
Int32 Id {
|
||||
get; set;
|
||||
}
|
||||
IList<IDnsResourceRecord> AnswerRecords {
|
||||
get;
|
||||
}
|
||||
IList<IDnsResourceRecord> AuthorityRecords {
|
||||
get;
|
||||
}
|
||||
IList<IDnsResourceRecord> AdditionalRecords {
|
||||
get;
|
||||
}
|
||||
Boolean IsRecursionAvailable {
|
||||
get; set;
|
||||
}
|
||||
Boolean IsAuthorativeServer {
|
||||
get; set;
|
||||
}
|
||||
Boolean IsTruncated {
|
||||
get; set;
|
||||
}
|
||||
DnsOperationCode OperationCode {
|
||||
get; set;
|
||||
}
|
||||
DnsResponseCode ResponseCode {
|
||||
get; set;
|
||||
}
|
||||
}
|
||||
|
||||
public interface IDnsRequestResolver {
|
||||
Task<DnsClientResponse> Request(DnsClientRequest request);
|
||||
}
|
||||
}
|
||||
}*/
|
@ -1,559 +0,0 @@
|
||||
/*
|
||||
#nullable enable
|
||||
using Swan.Formatters;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Swan.Net.Dns {
|
||||
/// <summary>
|
||||
/// DnsClient Request inner class.
|
||||
/// </summary>
|
||||
internal partial class DnsClient {
|
||||
public class DnsClientRequest : IDnsRequest {
|
||||
private readonly IDnsRequestResolver _resolver;
|
||||
private readonly IDnsRequest _request;
|
||||
|
||||
public DnsClientRequest(IPEndPoint dns, IDnsRequest? request = null, IDnsRequestResolver? resolver = null) {
|
||||
this.Dns = dns;
|
||||
this._request = request == null ? new DnsRequest() : new DnsRequest(request);
|
||||
this._resolver = resolver ?? new DnsUdpRequestResolver();
|
||||
}
|
||||
|
||||
public Int32 Id {
|
||||
get => this._request.Id;
|
||||
set => this._request.Id = value;
|
||||
}
|
||||
|
||||
public DnsOperationCode OperationCode {
|
||||
get => this._request.OperationCode;
|
||||
set => this._request.OperationCode = value;
|
||||
}
|
||||
|
||||
public Boolean RecursionDesired {
|
||||
get => this._request.RecursionDesired;
|
||||
set => this._request.RecursionDesired = value;
|
||||
}
|
||||
|
||||
public IList<DnsQuestion> Questions => this._request.Questions;
|
||||
|
||||
public Int32 Size => this._request.Size;
|
||||
|
||||
public IPEndPoint Dns {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public Byte[] ToArray() => this._request.ToArray();
|
||||
|
||||
public override String ToString() => this._request.ToString()!;
|
||||
|
||||
/// <summary>
|
||||
/// Resolves this request into a response using the provided DNS information. The given
|
||||
/// request strategy is used to retrieve the response.
|
||||
/// </summary>
|
||||
/// <exception cref="DnsQueryException">Throw if a malformed response is received from the server.</exception>
|
||||
/// <exception cref="IOException">Thrown if a IO error occurs.</exception>
|
||||
/// <exception cref="SocketException">Thrown if a the reading or writing to the socket fails.</exception>
|
||||
/// <returns>The response received from server.</returns>
|
||||
public async Task<DnsClientResponse> Resolve() {
|
||||
try {
|
||||
DnsClientResponse response = await this._resolver.Request(this).ConfigureAwait(false);
|
||||
|
||||
if(response.Id != this.Id) {
|
||||
throw new DnsQueryException(response, "Mismatching request/response IDs");
|
||||
}
|
||||
|
||||
if(response.ResponseCode != DnsResponseCode.NoError) {
|
||||
throw new DnsQueryException(response);
|
||||
}
|
||||
|
||||
return response;
|
||||
} catch(Exception e) {
|
||||
if(e is ArgumentException || e is SocketException) {
|
||||
throw new DnsQueryException("Invalid response", e);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class DnsRequest : IDnsRequest {
|
||||
private static readonly Random Random = new Random();
|
||||
|
||||
private DnsHeader header;
|
||||
|
||||
public DnsRequest() {
|
||||
this.Questions = new List<DnsQuestion>();
|
||||
this.header = new DnsHeader {
|
||||
OperationCode = DnsOperationCode.Query,
|
||||
Response = false,
|
||||
Id = Random.Next(UInt16.MaxValue),
|
||||
};
|
||||
}
|
||||
|
||||
public DnsRequest(IDnsRequest request) {
|
||||
this.header = new DnsHeader();
|
||||
this.Questions = new List<DnsQuestion>(request.Questions);
|
||||
|
||||
this.header.Response = false;
|
||||
|
||||
this.Id = request.Id;
|
||||
this.OperationCode = request.OperationCode;
|
||||
this.RecursionDesired = request.RecursionDesired;
|
||||
}
|
||||
|
||||
public IList<DnsQuestion> Questions {
|
||||
get;
|
||||
}
|
||||
|
||||
public Int32 Size => this.header.Size + this.Questions.Sum(q => q.Size);
|
||||
|
||||
public Int32 Id {
|
||||
get => this.header.Id;
|
||||
set => this.header.Id = value;
|
||||
}
|
||||
|
||||
public DnsOperationCode OperationCode {
|
||||
get => this.header.OperationCode;
|
||||
set => this.header.OperationCode = value;
|
||||
}
|
||||
|
||||
public Boolean RecursionDesired {
|
||||
get => this.header.RecursionDesired;
|
||||
set => this.header.RecursionDesired = value;
|
||||
}
|
||||
|
||||
public Byte[] ToArray() {
|
||||
this.UpdateHeader();
|
||||
using MemoryStream result = new MemoryStream(this.Size);
|
||||
|
||||
return result.Append(this.header.ToArray()).Append(this.Questions.Select(q => q.ToArray())).ToArray();
|
||||
}
|
||||
|
||||
public override String ToString() {
|
||||
this.UpdateHeader();
|
||||
|
||||
return Json.Serialize(this, true);
|
||||
}
|
||||
|
||||
private void UpdateHeader() => this.header.QuestionCount = this.Questions.Count;
|
||||
}
|
||||
|
||||
public class DnsTcpRequestResolver : IDnsRequestResolver {
|
||||
public async Task<DnsClientResponse> Request(DnsClientRequest request) {
|
||||
TcpClient tcp = new TcpClient();
|
||||
|
||||
try {
|
||||
await tcp.Client.ConnectAsync(request.Dns).ConfigureAwait(false);
|
||||
|
||||
NetworkStream stream = tcp.GetStream();
|
||||
Byte[] buffer = request.ToArray();
|
||||
Byte[] length = BitConverter.GetBytes((UInt16)buffer.Length);
|
||||
|
||||
if(BitConverter.IsLittleEndian) {
|
||||
Array.Reverse(length);
|
||||
}
|
||||
|
||||
await stream.WriteAsync(length, 0, length.Length).ConfigureAwait(false);
|
||||
await stream.WriteAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
|
||||
|
||||
buffer = new Byte[2];
|
||||
await Read(stream, buffer).ConfigureAwait(false);
|
||||
|
||||
if(BitConverter.IsLittleEndian) {
|
||||
Array.Reverse(buffer);
|
||||
}
|
||||
|
||||
buffer = new Byte[BitConverter.ToUInt16(buffer, 0)];
|
||||
await Read(stream, buffer).ConfigureAwait(false);
|
||||
|
||||
DnsResponse response = DnsResponse.FromArray(buffer);
|
||||
|
||||
return new DnsClientResponse(request, response, buffer);
|
||||
} finally {
|
||||
tcp.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task Read(Stream stream, Byte[] buffer) {
|
||||
Int32 length = buffer.Length;
|
||||
Int32 offset = 0;
|
||||
Int32 size;
|
||||
|
||||
while(length > 0 && (size = await stream.ReadAsync(buffer, offset, length).ConfigureAwait(false)) > 0) {
|
||||
offset += size;
|
||||
length -= size;
|
||||
}
|
||||
|
||||
if(length > 0) {
|
||||
throw new IOException("Unexpected end of stream");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class DnsUdpRequestResolver : IDnsRequestResolver {
|
||||
private readonly IDnsRequestResolver _fallback;
|
||||
|
||||
public DnsUdpRequestResolver(IDnsRequestResolver fallback) => this._fallback = fallback;
|
||||
|
||||
public DnsUdpRequestResolver() => this._fallback = new DnsNullRequestResolver();
|
||||
|
||||
public async Task<DnsClientResponse> Request(DnsClientRequest request) {
|
||||
UdpClient udp = new UdpClient();
|
||||
IPEndPoint dns = request.Dns;
|
||||
|
||||
try {
|
||||
udp.Client.SendTimeout = 7000;
|
||||
udp.Client.ReceiveTimeout = 7000;
|
||||
|
||||
await udp.Client.ConnectAsync(dns).ConfigureAwait(false);
|
||||
|
||||
|
||||
_ = await udp.SendAsync(request.ToArray(), request.Size).ConfigureAwait(false);
|
||||
|
||||
List<Byte> bufferList = new List<Byte>();
|
||||
|
||||
do {
|
||||
Byte[] tempBuffer = new Byte[1024];
|
||||
Int32 receiveCount = udp.Client.Receive(tempBuffer);
|
||||
bufferList.AddRange(tempBuffer.Skip(0).Take(receiveCount));
|
||||
}
|
||||
while(udp.Client.Available > 0 || bufferList.Count == 0);
|
||||
|
||||
Byte[] buffer = bufferList.ToArray();
|
||||
DnsResponse response = DnsResponse.FromArray(buffer);
|
||||
|
||||
return response.IsTruncated
|
||||
? await this._fallback.Request(request).ConfigureAwait(false)
|
||||
: new DnsClientResponse(request, response, buffer);
|
||||
} finally {
|
||||
udp.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class DnsNullRequestResolver : IDnsRequestResolver {
|
||||
public Task<DnsClientResponse> Request(DnsClientRequest request) => throw new DnsQueryException("Request failed");
|
||||
}
|
||||
|
||||
// 12 bytes message header
|
||||
[StructEndianness(Endianness.Big)]
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct DnsHeader {
|
||||
public const Int32 SIZE = 12;
|
||||
|
||||
private UInt16 id;
|
||||
|
||||
// Question count: number of questions in the Question section
|
||||
private UInt16 questionCount;
|
||||
|
||||
// Answer record count: number of records in the Answer section
|
||||
private UInt16 answerCount;
|
||||
|
||||
// Authority record count: number of records in the Authority section
|
||||
private UInt16 authorityCount;
|
||||
|
||||
// Additional record count: number of records in the Additional section
|
||||
private UInt16 addtionalCount;
|
||||
|
||||
public Int32 Id {
|
||||
get => this.id;
|
||||
set => this.id = (UInt16)value;
|
||||
}
|
||||
|
||||
public Int32 QuestionCount {
|
||||
get => this.questionCount;
|
||||
set => this.questionCount = (UInt16)value;
|
||||
}
|
||||
|
||||
public Int32 AnswerRecordCount {
|
||||
get => this.answerCount;
|
||||
set => this.answerCount = (UInt16)value;
|
||||
}
|
||||
|
||||
public Int32 AuthorityRecordCount {
|
||||
get => this.authorityCount;
|
||||
set => this.authorityCount = (UInt16)value;
|
||||
}
|
||||
|
||||
public Int32 AdditionalRecordCount {
|
||||
get => this.addtionalCount;
|
||||
set => this.addtionalCount = (UInt16)value;
|
||||
}
|
||||
|
||||
public Boolean Response {
|
||||
get => this.Qr == 1;
|
||||
set => this.Qr = Convert.ToByte(value);
|
||||
}
|
||||
|
||||
public DnsOperationCode OperationCode {
|
||||
get => (DnsOperationCode)this.Opcode;
|
||||
set => this.Opcode = (Byte)value;
|
||||
}
|
||||
|
||||
public Boolean AuthorativeServer {
|
||||
get => this.Aa == 1;
|
||||
set => this.Aa = Convert.ToByte(value);
|
||||
}
|
||||
|
||||
public Boolean Truncated {
|
||||
get => this.Tc == 1;
|
||||
set => this.Tc = Convert.ToByte(value);
|
||||
}
|
||||
|
||||
public Boolean RecursionDesired {
|
||||
get => this.Rd == 1;
|
||||
set => this.Rd = Convert.ToByte(value);
|
||||
}
|
||||
|
||||
public Boolean RecursionAvailable {
|
||||
get => this.Ra == 1;
|
||||
set => this.Ra = Convert.ToByte(value);
|
||||
}
|
||||
|
||||
public DnsResponseCode ResponseCode {
|
||||
get => (DnsResponseCode)this.RCode;
|
||||
set => this.RCode = (Byte)value;
|
||||
}
|
||||
|
||||
public Int32 Size => SIZE;
|
||||
|
||||
// Query/Response Flag
|
||||
private Byte Qr {
|
||||
get => this.Flag0.GetBitValueAt(7);
|
||||
set => this.Flag0 = this.Flag0.SetBitValueAt(7, 1, value);
|
||||
}
|
||||
|
||||
// Operation Code
|
||||
private Byte Opcode {
|
||||
get => this.Flag0.GetBitValueAt(3, 4);
|
||||
set => this.Flag0 = this.Flag0.SetBitValueAt(3, 4, value);
|
||||
}
|
||||
|
||||
// Authorative Answer Flag
|
||||
private Byte Aa {
|
||||
get => this.Flag0.GetBitValueAt(2);
|
||||
set => this.Flag0 = this.Flag0.SetBitValueAt(2, 1, value);
|
||||
}
|
||||
|
||||
// Truncation Flag
|
||||
private Byte Tc {
|
||||
get => this.Flag0.GetBitValueAt(1);
|
||||
set => this.Flag0 = this.Flag0.SetBitValueAt(1, 1, value);
|
||||
}
|
||||
|
||||
// Recursion Desired
|
||||
private Byte Rd {
|
||||
get => this.Flag0.GetBitValueAt(0);
|
||||
set => this.Flag0 = this.Flag0.SetBitValueAt(0, 1, value);
|
||||
}
|
||||
|
||||
// Recursion Available
|
||||
private Byte Ra {
|
||||
get => this.Flag1.GetBitValueAt(7);
|
||||
set => this.Flag1 = this.Flag1.SetBitValueAt(7, 1, value);
|
||||
}
|
||||
|
||||
// Zero (Reserved)
|
||||
private Byte Z {
|
||||
get => this.Flag1.GetBitValueAt(4, 3);
|
||||
set {
|
||||
}
|
||||
}
|
||||
|
||||
// Response Code
|
||||
private Byte RCode {
|
||||
get => this.Flag1.GetBitValueAt(0, 4);
|
||||
set => this.Flag1 = this.Flag1.SetBitValueAt(0, 4, value);
|
||||
}
|
||||
|
||||
private Byte Flag0 {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
private Byte Flag1 {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public static DnsHeader FromArray(Byte[] header) => header.Length < SIZE ? throw new ArgumentException("Header length too small") : header.ToStruct<DnsHeader>(0, SIZE);
|
||||
|
||||
public Byte[] ToArray() => this.ToBytes();
|
||||
|
||||
public override String ToString() => Json.SerializeExcluding(this, true, nameof(this.Size));
|
||||
}
|
||||
|
||||
public class DnsDomain : IComparable<DnsDomain> {
|
||||
private readonly String[] _labels;
|
||||
|
||||
public DnsDomain(String domain) : this(domain.Split('.')) {
|
||||
}
|
||||
|
||||
public DnsDomain(String[] labels) => this._labels = labels;
|
||||
|
||||
public Int32 Size => this._labels.Sum(l => l.Length) + this._labels.Length + 1;
|
||||
|
||||
public static DnsDomain FromArray(Byte[] message, Int32 offset) => FromArray(message, offset, out _);
|
||||
|
||||
public static DnsDomain FromArray(Byte[] message, Int32 offset, out Int32 endOffset) {
|
||||
List<Byte[]> labels = new List<Byte[]>();
|
||||
Boolean endOffsetAssigned = false;
|
||||
endOffset = 0;
|
||||
Byte lengthOrPointer;
|
||||
|
||||
while((lengthOrPointer = message[offset++]) > 0) {
|
||||
// Two heighest bits are set (pointer)
|
||||
if(lengthOrPointer.GetBitValueAt(6, 2) == 3) {
|
||||
if(!endOffsetAssigned) {
|
||||
endOffsetAssigned = true;
|
||||
endOffset = offset + 1;
|
||||
}
|
||||
|
||||
UInt16 pointer = lengthOrPointer.GetBitValueAt(0, 6);
|
||||
offset = (pointer << 8) | message[offset];
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if(lengthOrPointer.GetBitValueAt(6, 2) != 0) {
|
||||
throw new ArgumentException("Unexpected bit pattern in label length");
|
||||
}
|
||||
|
||||
Byte length = lengthOrPointer;
|
||||
Byte[] label = new Byte[length];
|
||||
Array.Copy(message, offset, label, 0, length);
|
||||
|
||||
labels.Add(label);
|
||||
|
||||
offset += length;
|
||||
}
|
||||
|
||||
if(!endOffsetAssigned) {
|
||||
endOffset = offset;
|
||||
}
|
||||
|
||||
return new DnsDomain(labels.Select(l => l.ToText(Encoding.ASCII)).ToArray());
|
||||
}
|
||||
|
||||
public static DnsDomain PointerName(IPAddress ip) => new DnsDomain(FormatReverseIP(ip));
|
||||
|
||||
public Byte[] ToArray() {
|
||||
Byte[] result = new Byte[this.Size];
|
||||
Int32 offset = 0;
|
||||
|
||||
foreach(Byte[] l in this._labels.Select(label => Encoding.ASCII.GetBytes(label))) {
|
||||
result[offset++] = (Byte)l.Length;
|
||||
l.CopyTo(result, offset);
|
||||
|
||||
offset += l.Length;
|
||||
}
|
||||
|
||||
result[offset] = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override String ToString() => String.Join(".", this._labels);
|
||||
|
||||
public Int32 CompareTo(DnsDomain other) => String.Compare(this.ToString(), other.ToString(), StringComparison.Ordinal);
|
||||
|
||||
public override Boolean Equals(Object? obj) => obj is DnsDomain domain && this.CompareTo(domain) == 0;
|
||||
|
||||
public override Int32 GetHashCode() => this.ToString().GetHashCode();
|
||||
|
||||
private static String FormatReverseIP(IPAddress ip) {
|
||||
Byte[] address = ip.GetAddressBytes();
|
||||
|
||||
if(address.Length == 4) {
|
||||
return String.Join(".", address.Reverse().Select(b => b.ToString())) + ".in-addr.arpa";
|
||||
}
|
||||
|
||||
Byte[] nibbles = new Byte[address.Length * 2];
|
||||
|
||||
for(Int32 i = 0, j = 0; i < address.Length; i++, j = 2 * i) {
|
||||
Byte b = address[i];
|
||||
|
||||
nibbles[j] = b.GetBitValueAt(4, 4);
|
||||
nibbles[j + 1] = b.GetBitValueAt(0, 4);
|
||||
}
|
||||
|
||||
return String.Join(".", nibbles.Reverse().Select(b => b.ToString("x"))) + ".ip6.arpa";
|
||||
}
|
||||
}
|
||||
|
||||
public class DnsQuestion : IDnsMessageEntry {
|
||||
public static IList<DnsQuestion> GetAllFromArray(Byte[] message, Int32 offset, Int32 questionCount) => GetAllFromArray(message, offset, questionCount, out _);
|
||||
|
||||
public static IList<DnsQuestion> GetAllFromArray(Byte[] message, Int32 offset, Int32 questionCount, out Int32 endOffset) {
|
||||
IList<DnsQuestion> questions = new List<DnsQuestion>(questionCount);
|
||||
|
||||
for(Int32 i = 0; i < questionCount; i++) {
|
||||
questions.Add(FromArray(message, offset, out offset));
|
||||
}
|
||||
|
||||
endOffset = offset;
|
||||
return questions;
|
||||
}
|
||||
|
||||
public static DnsQuestion FromArray(Byte[] message, Int32 offset, out Int32 endOffset) {
|
||||
DnsDomain domain = DnsDomain.FromArray(message, offset, out offset);
|
||||
Tail tail = message.ToStruct<Tail>(offset, Tail.SIZE);
|
||||
|
||||
endOffset = offset + Tail.SIZE;
|
||||
|
||||
return new DnsQuestion(domain, tail.Type, tail.Class);
|
||||
}
|
||||
|
||||
public DnsQuestion(DnsDomain domain, DnsRecordType type = DnsRecordType.A, DnsRecordClass klass = DnsRecordClass.IN) {
|
||||
this.Name = domain;
|
||||
this.Type = type;
|
||||
this.Class = klass;
|
||||
}
|
||||
|
||||
public DnsDomain Name {
|
||||
get;
|
||||
}
|
||||
|
||||
public DnsRecordType Type {
|
||||
get;
|
||||
}
|
||||
|
||||
public DnsRecordClass Class {
|
||||
get;
|
||||
}
|
||||
|
||||
public Int32 Size => this.Name.Size + Tail.SIZE;
|
||||
|
||||
public Byte[] ToArray() => new MemoryStream(this.Size).Append(this.Name.ToArray()).Append(new Tail { Type = Type, Class = Class }.ToBytes()).ToArray();
|
||||
|
||||
public override String ToString() => Json.SerializeOnly(this, true, nameof(this.Name), nameof(this.Type), nameof(this.Class));
|
||||
|
||||
[StructEndianness(Endianness.Big)]
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 2)]
|
||||
private struct Tail {
|
||||
public const Int32 SIZE = 4;
|
||||
|
||||
private UInt16 type;
|
||||
private UInt16 klass;
|
||||
|
||||
public DnsRecordType Type {
|
||||
get => (DnsRecordType)this.type;
|
||||
set => this.type = (UInt16)value;
|
||||
}
|
||||
|
||||
public DnsRecordClass Class {
|
||||
get => (DnsRecordClass)this.klass;
|
||||
set => this.klass = (UInt16)value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
@ -1,344 +0,0 @@
|
||||
/*using Swan.Formatters;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Swan.Net.Dns {
|
||||
/// <summary>
|
||||
/// DnsClient public methods.
|
||||
/// </summary>
|
||||
internal partial class DnsClient {
|
||||
public abstract class DnsResourceRecordBase : IDnsResourceRecord {
|
||||
private readonly IDnsResourceRecord _record;
|
||||
|
||||
protected DnsResourceRecordBase(IDnsResourceRecord record) => this._record = record;
|
||||
|
||||
public DnsDomain Name => this._record.Name;
|
||||
|
||||
public DnsRecordType Type => this._record.Type;
|
||||
|
||||
public DnsRecordClass Class => this._record.Class;
|
||||
|
||||
public TimeSpan TimeToLive => this._record.TimeToLive;
|
||||
|
||||
public Int32 DataLength => this._record.DataLength;
|
||||
|
||||
public Byte[] Data => this._record.Data;
|
||||
|
||||
public Int32 Size => this._record.Size;
|
||||
|
||||
protected virtual String[] IncludedProperties => new[] { nameof(this.Name), nameof(this.Type), nameof(this.Class), nameof(this.TimeToLive), nameof(this.DataLength) };
|
||||
|
||||
public Byte[] ToArray() => this._record.ToArray();
|
||||
|
||||
public override String ToString() => Json.SerializeOnly(this, true, this.IncludedProperties);
|
||||
}
|
||||
|
||||
public class DnsResourceRecord : IDnsResourceRecord {
|
||||
public DnsResourceRecord(DnsDomain domain, Byte[] data, DnsRecordType type, DnsRecordClass klass = DnsRecordClass.IN, TimeSpan ttl = default) {
|
||||
this.Name = domain;
|
||||
this.Type = type;
|
||||
this.Class = klass;
|
||||
this.TimeToLive = ttl;
|
||||
this.Data = data;
|
||||
}
|
||||
|
||||
public DnsDomain Name {
|
||||
get;
|
||||
}
|
||||
|
||||
public DnsRecordType Type {
|
||||
get;
|
||||
}
|
||||
|
||||
public DnsRecordClass Class {
|
||||
get;
|
||||
}
|
||||
|
||||
public TimeSpan TimeToLive {
|
||||
get;
|
||||
}
|
||||
|
||||
public Int32 DataLength => this.Data.Length;
|
||||
|
||||
public Byte[] Data {
|
||||
get;
|
||||
}
|
||||
|
||||
public Int32 Size => this.Name.Size + Tail.SIZE + this.Data.Length;
|
||||
|
||||
public static DnsResourceRecord FromArray(Byte[] message, Int32 offset, out Int32 endOffset) {
|
||||
DnsDomain domain = DnsDomain.FromArray(message, offset, out offset);
|
||||
Tail tail = message.ToStruct<Tail>(offset, Tail.SIZE);
|
||||
|
||||
Byte[] data = new Byte[tail.DataLength];
|
||||
|
||||
offset += Tail.SIZE;
|
||||
Array.Copy(message, offset, data, 0, data.Length);
|
||||
|
||||
endOffset = offset + data.Length;
|
||||
|
||||
return new DnsResourceRecord(domain, data, tail.Type, tail.Class, tail.TimeToLive);
|
||||
}
|
||||
|
||||
public Byte[] ToArray() => new MemoryStream(this.Size).Append(this.Name.ToArray()).Append(new Tail() { Type = Type, Class = Class, TimeToLive = TimeToLive, DataLength = this.Data.Length, }.ToBytes()).Append(this.Data).ToArray();
|
||||
|
||||
public override String ToString() => Json.SerializeOnly(this, true, nameof(this.Name), nameof(this.Type), nameof(this.Class), nameof(this.TimeToLive), nameof(this.DataLength));
|
||||
|
||||
[StructEndianness(Endianness.Big)]
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 2)]
|
||||
private struct Tail {
|
||||
public const Int32 SIZE = 10;
|
||||
|
||||
private UInt16 type;
|
||||
private UInt16 klass;
|
||||
private UInt32 ttl;
|
||||
private UInt16 dataLength;
|
||||
|
||||
public DnsRecordType Type {
|
||||
get => (DnsRecordType)this.type;
|
||||
set => this.type = (UInt16)value;
|
||||
}
|
||||
|
||||
public DnsRecordClass Class {
|
||||
get => (DnsRecordClass)this.klass;
|
||||
set => this.klass = (UInt16)value;
|
||||
}
|
||||
|
||||
public TimeSpan TimeToLive {
|
||||
get => TimeSpan.FromSeconds(this.ttl);
|
||||
set => this.ttl = (UInt32)value.TotalSeconds;
|
||||
}
|
||||
|
||||
public Int32 DataLength {
|
||||
get => this.dataLength;
|
||||
set => this.dataLength = (UInt16)value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class DnsPointerResourceRecord : DnsResourceRecordBase {
|
||||
public DnsPointerResourceRecord(IDnsResourceRecord record, Byte[] message, Int32 dataOffset) : base(record) => this.PointerDomainName = DnsDomain.FromArray(message, dataOffset);
|
||||
|
||||
public DnsDomain PointerDomainName {
|
||||
get;
|
||||
}
|
||||
|
||||
protected override String[] IncludedProperties {
|
||||
get {
|
||||
List<String> temp = new List<String>(base.IncludedProperties) { nameof(this.PointerDomainName) };
|
||||
return temp.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class DnsIPAddressResourceRecord : DnsResourceRecordBase {
|
||||
public DnsIPAddressResourceRecord(IDnsResourceRecord record) : base(record) => this.IPAddress = new IPAddress(this.Data);
|
||||
|
||||
public IPAddress IPAddress {
|
||||
get;
|
||||
}
|
||||
|
||||
protected override String[] IncludedProperties => new List<String>(base.IncludedProperties) { nameof(this.IPAddress) }.ToArray();
|
||||
}
|
||||
|
||||
public class DnsNameServerResourceRecord : DnsResourceRecordBase {
|
||||
public DnsNameServerResourceRecord(IDnsResourceRecord record, Byte[] message, Int32 dataOffset) : base(record) => this.NSDomainName = DnsDomain.FromArray(message, dataOffset);
|
||||
|
||||
public DnsDomain NSDomainName {
|
||||
get;
|
||||
}
|
||||
|
||||
protected override String[] IncludedProperties => new List<String>(base.IncludedProperties) { nameof(this.NSDomainName) }.ToArray();
|
||||
}
|
||||
|
||||
public class DnsCanonicalNameResourceRecord : DnsResourceRecordBase {
|
||||
public DnsCanonicalNameResourceRecord(IDnsResourceRecord record, Byte[] message, Int32 dataOffset) : base(record) => this.CanonicalDomainName = DnsDomain.FromArray(message, dataOffset);
|
||||
|
||||
public DnsDomain CanonicalDomainName {
|
||||
get;
|
||||
}
|
||||
|
||||
protected override String[] IncludedProperties => new List<String>(base.IncludedProperties) { nameof(this.CanonicalDomainName) }.ToArray();
|
||||
}
|
||||
|
||||
public class DnsMailExchangeResourceRecord : DnsResourceRecordBase {
|
||||
private const Int32 PreferenceSize = 2;
|
||||
|
||||
public DnsMailExchangeResourceRecord(IDnsResourceRecord record, Byte[] message, Int32 dataOffset)
|
||||
: base(record) {
|
||||
Byte[] preference = new Byte[PreferenceSize];
|
||||
Array.Copy(message, dataOffset, preference, 0, preference.Length);
|
||||
|
||||
if(BitConverter.IsLittleEndian) {
|
||||
Array.Reverse(preference);
|
||||
}
|
||||
|
||||
dataOffset += PreferenceSize;
|
||||
|
||||
this.Preference = BitConverter.ToUInt16(preference, 0);
|
||||
this.ExchangeDomainName = DnsDomain.FromArray(message, dataOffset);
|
||||
}
|
||||
|
||||
public Int32 Preference {
|
||||
get;
|
||||
}
|
||||
|
||||
public DnsDomain ExchangeDomainName {
|
||||
get;
|
||||
}
|
||||
|
||||
protected override String[] IncludedProperties => new List<String>(base.IncludedProperties)
|
||||
{
|
||||
nameof(this.Preference),
|
||||
nameof(this.ExchangeDomainName),
|
||||
}.ToArray();
|
||||
}
|
||||
|
||||
public class DnsStartOfAuthorityResourceRecord : DnsResourceRecordBase {
|
||||
public DnsStartOfAuthorityResourceRecord(IDnsResourceRecord record, Byte[] message, Int32 dataOffset) : base(record) {
|
||||
this.MasterDomainName = DnsDomain.FromArray(message, dataOffset, out dataOffset);
|
||||
this.ResponsibleDomainName = DnsDomain.FromArray(message, dataOffset, out dataOffset);
|
||||
|
||||
Options tail = message.ToStruct<Options>(dataOffset, Options.SIZE);
|
||||
|
||||
this.SerialNumber = tail.SerialNumber;
|
||||
this.RefreshInterval = tail.RefreshInterval;
|
||||
this.RetryInterval = tail.RetryInterval;
|
||||
this.ExpireInterval = tail.ExpireInterval;
|
||||
this.MinimumTimeToLive = tail.MinimumTimeToLive;
|
||||
}
|
||||
|
||||
public DnsStartOfAuthorityResourceRecord(DnsDomain domain, DnsDomain master, DnsDomain responsible, Int64 serial, TimeSpan refresh, TimeSpan retry, TimeSpan expire, TimeSpan minTtl, TimeSpan ttl = default)
|
||||
: base(Create(domain, master, responsible, serial, refresh, retry, expire, minTtl, ttl)) {
|
||||
this.MasterDomainName = master;
|
||||
this.ResponsibleDomainName = responsible;
|
||||
|
||||
this.SerialNumber = serial;
|
||||
this.RefreshInterval = refresh;
|
||||
this.RetryInterval = retry;
|
||||
this.ExpireInterval = expire;
|
||||
this.MinimumTimeToLive = minTtl;
|
||||
}
|
||||
|
||||
public DnsDomain MasterDomainName {
|
||||
get;
|
||||
}
|
||||
|
||||
public DnsDomain ResponsibleDomainName {
|
||||
get;
|
||||
}
|
||||
|
||||
public Int64 SerialNumber {
|
||||
get;
|
||||
}
|
||||
|
||||
public TimeSpan RefreshInterval {
|
||||
get;
|
||||
}
|
||||
|
||||
public TimeSpan RetryInterval {
|
||||
get;
|
||||
}
|
||||
|
||||
public TimeSpan ExpireInterval {
|
||||
get;
|
||||
}
|
||||
|
||||
public TimeSpan MinimumTimeToLive {
|
||||
get;
|
||||
}
|
||||
|
||||
protected override String[] IncludedProperties => new List<String>(base.IncludedProperties)
|
||||
{
|
||||
nameof(this.MasterDomainName),
|
||||
nameof(this.ResponsibleDomainName),
|
||||
nameof(this.SerialNumber),
|
||||
}.ToArray();
|
||||
|
||||
private static IDnsResourceRecord Create(DnsDomain domain, DnsDomain master, DnsDomain responsible, Int64 serial, TimeSpan refresh, TimeSpan retry, TimeSpan expire, TimeSpan minTtl, TimeSpan ttl) {
|
||||
MemoryStream data = new MemoryStream(Options.SIZE + master.Size + responsible.Size);
|
||||
Options tail = new Options {
|
||||
SerialNumber = serial,
|
||||
RefreshInterval = refresh,
|
||||
RetryInterval = retry,
|
||||
ExpireInterval = expire,
|
||||
MinimumTimeToLive = minTtl,
|
||||
};
|
||||
|
||||
_ = data.Append(master.ToArray()).Append(responsible.ToArray()).Append(tail.ToBytes());
|
||||
|
||||
return new DnsResourceRecord(domain, data.ToArray(), DnsRecordType.SOA, DnsRecordClass.IN, ttl);
|
||||
}
|
||||
|
||||
[StructEndianness(Endianness.Big)]
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
||||
public struct Options {
|
||||
public const Int32 SIZE = 20;
|
||||
|
||||
private UInt32 serialNumber;
|
||||
private UInt32 refreshInterval;
|
||||
private UInt32 retryInterval;
|
||||
private UInt32 expireInterval;
|
||||
private UInt32 ttl;
|
||||
|
||||
public Int64 SerialNumber {
|
||||
get => this.serialNumber;
|
||||
set => this.serialNumber = (UInt32)value;
|
||||
}
|
||||
|
||||
public TimeSpan RefreshInterval {
|
||||
get => TimeSpan.FromSeconds(this.refreshInterval);
|
||||
set => this.refreshInterval = (UInt32)value.TotalSeconds;
|
||||
}
|
||||
|
||||
public TimeSpan RetryInterval {
|
||||
get => TimeSpan.FromSeconds(this.retryInterval);
|
||||
set => this.retryInterval = (UInt32)value.TotalSeconds;
|
||||
}
|
||||
|
||||
public TimeSpan ExpireInterval {
|
||||
get => TimeSpan.FromSeconds(this.expireInterval);
|
||||
set => this.expireInterval = (UInt32)value.TotalSeconds;
|
||||
}
|
||||
|
||||
public TimeSpan MinimumTimeToLive {
|
||||
get => TimeSpan.FromSeconds(this.ttl);
|
||||
set => this.ttl = (UInt32)value.TotalSeconds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class DnsResourceRecordFactory {
|
||||
public static IList<IDnsResourceRecord> GetAllFromArray(Byte[] message, Int32 offset, Int32 count, out Int32 endOffset) {
|
||||
List<IDnsResourceRecord> result = new List<IDnsResourceRecord>(count);
|
||||
|
||||
for(Int32 i = 0; i < count; i++) {
|
||||
result.Add(GetFromArray(message, offset, out offset));
|
||||
}
|
||||
|
||||
endOffset = offset;
|
||||
return result;
|
||||
}
|
||||
|
||||
private static IDnsResourceRecord GetFromArray(Byte[] message, Int32 offset, out Int32 endOffset) {
|
||||
DnsResourceRecord record = DnsResourceRecord.FromArray(message, offset, out endOffset);
|
||||
Int32 dataOffset = endOffset - record.DataLength;
|
||||
|
||||
return record.Type switch
|
||||
{
|
||||
DnsRecordType.A => (new DnsIPAddressResourceRecord(record)),
|
||||
DnsRecordType.AAAA => new DnsIPAddressResourceRecord(record),
|
||||
DnsRecordType.NS => new DnsNameServerResourceRecord(record, message, dataOffset),
|
||||
DnsRecordType.CNAME => new DnsCanonicalNameResourceRecord(record, message, dataOffset),
|
||||
DnsRecordType.SOA => new DnsStartOfAuthorityResourceRecord(record, message, dataOffset),
|
||||
DnsRecordType.PTR => new DnsPointerResourceRecord(record, message, dataOffset),
|
||||
DnsRecordType.MX => new DnsMailExchangeResourceRecord(record, message, dataOffset),
|
||||
_ => record
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
@ -1,174 +0,0 @@
|
||||
/*using Swan.Formatters;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Swan.Net.Dns {
|
||||
/// <summary>
|
||||
/// DnsClient Response inner class.
|
||||
/// </summary>
|
||||
internal partial class DnsClient {
|
||||
public class DnsClientResponse : IDnsResponse {
|
||||
private readonly DnsResponse _response;
|
||||
private readonly Byte[] _message;
|
||||
|
||||
internal DnsClientResponse(DnsClientRequest request, DnsResponse response, Byte[] message) {
|
||||
this.Request = request;
|
||||
|
||||
this._message = message;
|
||||
this._response = response;
|
||||
}
|
||||
|
||||
public DnsClientRequest Request {
|
||||
get;
|
||||
}
|
||||
|
||||
public Int32 Id {
|
||||
get => this._response.Id;
|
||||
set {
|
||||
}
|
||||
}
|
||||
|
||||
public IList<IDnsResourceRecord> AnswerRecords => this._response.AnswerRecords;
|
||||
|
||||
public IList<IDnsResourceRecord> AuthorityRecords => new ReadOnlyCollection<IDnsResourceRecord>(this._response.AuthorityRecords);
|
||||
|
||||
public IList<IDnsResourceRecord> AdditionalRecords => new ReadOnlyCollection<IDnsResourceRecord>(this._response.AdditionalRecords);
|
||||
|
||||
public Boolean IsRecursionAvailable {
|
||||
get => this._response.IsRecursionAvailable;
|
||||
set {
|
||||
}
|
||||
}
|
||||
|
||||
public Boolean IsAuthorativeServer {
|
||||
get => this._response.IsAuthorativeServer;
|
||||
set {
|
||||
}
|
||||
}
|
||||
|
||||
public Boolean IsTruncated {
|
||||
get => this._response.IsTruncated;
|
||||
set {
|
||||
}
|
||||
}
|
||||
|
||||
public DnsOperationCode OperationCode {
|
||||
get => this._response.OperationCode;
|
||||
set {
|
||||
}
|
||||
}
|
||||
|
||||
public DnsResponseCode ResponseCode {
|
||||
get => this._response.ResponseCode;
|
||||
set {
|
||||
}
|
||||
}
|
||||
|
||||
public IList<DnsQuestion> Questions => new ReadOnlyCollection<DnsQuestion>(this._response.Questions);
|
||||
|
||||
public Int32 Size => this._message.Length;
|
||||
|
||||
public Byte[] ToArray() => this._message;
|
||||
|
||||
public override String ToString() => this._response.ToString();
|
||||
}
|
||||
|
||||
public class DnsResponse : IDnsResponse {
|
||||
private DnsHeader _header;
|
||||
|
||||
public DnsResponse(DnsHeader header, IList<DnsQuestion> questions, IList<IDnsResourceRecord> answers, IList<IDnsResourceRecord> authority, IList<IDnsResourceRecord> additional) {
|
||||
this._header = header;
|
||||
this.Questions = questions;
|
||||
this.AnswerRecords = answers;
|
||||
this.AuthorityRecords = authority;
|
||||
this.AdditionalRecords = additional;
|
||||
}
|
||||
|
||||
public IList<DnsQuestion> Questions {
|
||||
get;
|
||||
}
|
||||
|
||||
public IList<IDnsResourceRecord> AnswerRecords {
|
||||
get;
|
||||
}
|
||||
|
||||
public IList<IDnsResourceRecord> AuthorityRecords {
|
||||
get;
|
||||
}
|
||||
|
||||
public IList<IDnsResourceRecord> AdditionalRecords {
|
||||
get;
|
||||
}
|
||||
|
||||
public Int32 Id {
|
||||
get => this._header.Id;
|
||||
set => this._header.Id = value;
|
||||
}
|
||||
|
||||
public Boolean IsRecursionAvailable {
|
||||
get => this._header.RecursionAvailable;
|
||||
set => this._header.RecursionAvailable = value;
|
||||
}
|
||||
|
||||
public Boolean IsAuthorativeServer {
|
||||
get => this._header.AuthorativeServer;
|
||||
set => this._header.AuthorativeServer = value;
|
||||
}
|
||||
|
||||
public Boolean IsTruncated {
|
||||
get => this._header.Truncated;
|
||||
set => this._header.Truncated = value;
|
||||
}
|
||||
|
||||
public DnsOperationCode OperationCode {
|
||||
get => this._header.OperationCode;
|
||||
set => this._header.OperationCode = value;
|
||||
}
|
||||
|
||||
public DnsResponseCode ResponseCode {
|
||||
get => this._header.ResponseCode;
|
||||
set => this._header.ResponseCode = value;
|
||||
}
|
||||
|
||||
public Int32 Size => this._header.Size + this.Questions.Sum(q => q.Size) + this.AnswerRecords.Sum(a => a.Size) + this.AuthorityRecords.Sum(a => a.Size) + this.AdditionalRecords.Sum(a => a.Size);
|
||||
|
||||
public static DnsResponse FromArray(Byte[] message) {
|
||||
DnsHeader header = DnsHeader.FromArray(message);
|
||||
Int32 offset = header.Size;
|
||||
|
||||
if(!header.Response || header.QuestionCount == 0) {
|
||||
throw new ArgumentException("Invalid response message");
|
||||
}
|
||||
|
||||
return header.Truncated
|
||||
? new DnsResponse(header, DnsQuestion.GetAllFromArray(message, offset, header.QuestionCount), new List<IDnsResourceRecord>(), new List<IDnsResourceRecord>(), new List<IDnsResourceRecord>())
|
||||
: new DnsResponse(header, DnsQuestion.GetAllFromArray(message, offset, header.QuestionCount, out offset), DnsResourceRecordFactory.GetAllFromArray(message, offset, header.AnswerRecordCount, out offset), DnsResourceRecordFactory.GetAllFromArray(message, offset, header.AuthorityRecordCount, out offset), DnsResourceRecordFactory.GetAllFromArray(message, offset, header.AdditionalRecordCount, out _));
|
||||
}
|
||||
|
||||
public Byte[] ToArray() {
|
||||
this.UpdateHeader();
|
||||
MemoryStream result = new MemoryStream(this.Size);
|
||||
|
||||
_ = result.Append(this._header.ToArray()).Append(this.Questions.Select(q => q.ToArray())).Append(this.AnswerRecords.Select(a => a.ToArray())).Append(this.AuthorityRecords.Select(a => a.ToArray())).Append(this.AdditionalRecords.Select(a => a.ToArray()));
|
||||
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
public override String ToString() {
|
||||
this.UpdateHeader();
|
||||
|
||||
return Json.SerializeOnly(this, true, nameof(this.Questions), nameof(this.AnswerRecords), nameof(this.AuthorityRecords), nameof(this.AdditionalRecords));
|
||||
}
|
||||
|
||||
private void UpdateHeader() {
|
||||
this._header.QuestionCount = this.Questions.Count;
|
||||
this._header.AnswerRecordCount = this.AnswerRecords.Count;
|
||||
this._header.AuthorityRecordCount = this.AuthorityRecords.Count;
|
||||
this._header.AdditionalRecordCount = this.AdditionalRecords.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
@ -1,65 +0,0 @@
|
||||
/*using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
#nullable enable
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Swan.Net.Dns {
|
||||
/// <summary>
|
||||
/// DnsClient public methods.
|
||||
/// </summary>
|
||||
internal partial class DnsClient {
|
||||
private readonly IPEndPoint _dns;
|
||||
private readonly IDnsRequestResolver _resolver;
|
||||
|
||||
public DnsClient(IPEndPoint dns, IDnsRequestResolver? resolver = null) {
|
||||
this._dns = dns;
|
||||
this._resolver = resolver ?? new DnsUdpRequestResolver(new DnsTcpRequestResolver());
|
||||
}
|
||||
|
||||
public DnsClient(IPAddress ip, Int32 port = Network.DnsDefaultPort, IDnsRequestResolver? resolver = null) : this(new IPEndPoint(ip, port), resolver) {
|
||||
}
|
||||
|
||||
public DnsClientRequest Create(IDnsRequest? request = null) => new DnsClientRequest(this._dns, request, this._resolver);
|
||||
|
||||
public async Task<IList<IPAddress>> Lookup(String domain, DnsRecordType type = DnsRecordType.A) {
|
||||
if(String.IsNullOrWhiteSpace(domain)) {
|
||||
throw new ArgumentNullException(nameof(domain));
|
||||
}
|
||||
|
||||
if(type != DnsRecordType.A && type != DnsRecordType.AAAA) {
|
||||
throw new ArgumentException("Invalid record type " + type);
|
||||
}
|
||||
|
||||
DnsClientResponse response = await this.Resolve(domain, type).ConfigureAwait(false);
|
||||
List<IPAddress> ips = response.AnswerRecords.Where(r => r.Type == type).Cast<DnsIPAddressResourceRecord>().Select(r => r.IPAddress).ToList();
|
||||
|
||||
return ips.Count == 0 ? throw new DnsQueryException(response, "No matching records") : ips;
|
||||
}
|
||||
|
||||
public async Task<String> Reverse(IPAddress ip) {
|
||||
if(ip == null) {
|
||||
throw new ArgumentNullException(nameof(ip));
|
||||
}
|
||||
|
||||
DnsClientResponse response = await this.Resolve(DnsDomain.PointerName(ip), DnsRecordType.PTR);
|
||||
IDnsResourceRecord ptr = response.AnswerRecords.FirstOrDefault(r => r.Type == DnsRecordType.PTR);
|
||||
|
||||
return ptr == null ? throw new DnsQueryException(response, "No matching records") : ((DnsPointerResourceRecord)ptr).PointerDomainName.ToString();
|
||||
}
|
||||
|
||||
public Task<DnsClientResponse> Resolve(String domain, DnsRecordType type) => this.Resolve(new DnsDomain(domain), type);
|
||||
|
||||
public Task<DnsClientResponse> Resolve(DnsDomain domain, DnsRecordType type) {
|
||||
DnsClientRequest request = this.Create();
|
||||
DnsQuestion question = new DnsQuestion(domain, type);
|
||||
|
||||
request.Questions.Add(question);
|
||||
request.OperationCode = DnsOperationCode.Query;
|
||||
request.RecursionDesired = true;
|
||||
|
||||
return request.Resolve();
|
||||
}
|
||||
}
|
||||
}*/
|
@ -1,29 +0,0 @@
|
||||
/*#nullable enable
|
||||
using System;
|
||||
|
||||
namespace Swan.Net.Dns {
|
||||
/// <summary>
|
||||
/// An exception thrown when the DNS query fails.
|
||||
/// </summary>
|
||||
/// <seealso cref="Exception" />
|
||||
[Serializable]
|
||||
public class DnsQueryException : Exception {
|
||||
internal DnsQueryException(String message) : base(message) {
|
||||
}
|
||||
|
||||
internal DnsQueryException(String message, Exception e) : base(message, e) {
|
||||
}
|
||||
|
||||
internal DnsQueryException(DnsClient.IDnsResponse response) : this(response, Format(response)) {
|
||||
}
|
||||
|
||||
internal DnsQueryException(DnsClient.IDnsResponse response, String message) : base(message) => this.Response = response;
|
||||
|
||||
internal DnsClient.IDnsResponse? Response {
|
||||
get;
|
||||
}
|
||||
|
||||
private static String Format(DnsClient.IDnsResponse response) => $"Invalid response received with code {response.ResponseCode}";
|
||||
}
|
||||
}
|
||||
*/
|
@ -1,131 +0,0 @@
|
||||
/*namespace Swan.Net.Dns {
|
||||
using System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a response from a DNS server.
|
||||
/// </summary>
|
||||
public class DnsQueryResult {
|
||||
private readonly List<DnsRecord> _mAnswerRecords = new List<DnsRecord>();
|
||||
private readonly List<DnsRecord> _mAdditionalRecords = new List<DnsRecord>();
|
||||
private readonly List<DnsRecord> _mAuthorityRecords = new List<DnsRecord>();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DnsQueryResult"/> class.
|
||||
/// </summary>
|
||||
/// <param name="response">The response.</param>
|
||||
internal DnsQueryResult(DnsClient.IDnsResponse response) : this() {
|
||||
this.Id = response.Id;
|
||||
this.IsAuthoritativeServer = response.IsAuthorativeServer;
|
||||
this.IsRecursionAvailable = response.IsRecursionAvailable;
|
||||
this.IsTruncated = response.IsTruncated;
|
||||
this.OperationCode = response.OperationCode;
|
||||
this.ResponseCode = response.ResponseCode;
|
||||
|
||||
if(response.AnswerRecords != null) {
|
||||
foreach(DnsClient.IDnsResourceRecord record in response.AnswerRecords) {
|
||||
this.AnswerRecords.Add(new DnsRecord(record));
|
||||
}
|
||||
}
|
||||
|
||||
if(response.AuthorityRecords != null) {
|
||||
foreach(DnsClient.IDnsResourceRecord record in response.AuthorityRecords) {
|
||||
this.AuthorityRecords.Add(new DnsRecord(record));
|
||||
}
|
||||
}
|
||||
|
||||
if(response.AdditionalRecords != null) {
|
||||
foreach(DnsClient.IDnsResourceRecord record in response.AdditionalRecords) {
|
||||
this.AdditionalRecords.Add(new DnsRecord(record));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private DnsQueryResult() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the identifier.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The identifier.
|
||||
/// </value>
|
||||
public System.Int32 Id {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance is authoritative server.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance is authoritative server; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public System.Boolean IsAuthoritativeServer {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance is truncated.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance is truncated; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public System.Boolean IsTruncated {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance is recursion available.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance is recursion available; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public System.Boolean IsRecursionAvailable {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the operation code.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The operation code.
|
||||
/// </value>
|
||||
public DnsOperationCode OperationCode {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the response code.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The response code.
|
||||
/// </value>
|
||||
public DnsResponseCode ResponseCode {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the answer records.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The answer records.
|
||||
/// </value>
|
||||
public IList<DnsRecord> AnswerRecords => this._mAnswerRecords;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the additional records.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The additional records.
|
||||
/// </value>
|
||||
public IList<DnsRecord> AdditionalRecords => this._mAdditionalRecords;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the authority records.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The authority records.
|
||||
/// </value>
|
||||
public IList<DnsRecord> AuthorityRecords => this._mAuthorityRecords;
|
||||
}
|
||||
}
|
||||
*/
|
@ -1,240 +0,0 @@
|
||||
/*using System;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
namespace Swan.Net.Dns {
|
||||
/// <summary>
|
||||
/// Represents a DNS record entry.
|
||||
/// </summary>
|
||||
public class DnsRecord {
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DnsRecord"/> class.
|
||||
/// </summary>
|
||||
/// <param name="record">The record.</param>
|
||||
internal DnsRecord(DnsClient.IDnsResourceRecord record) : this() {
|
||||
this.Name = record.Name.ToString();
|
||||
this.Type = record.Type;
|
||||
this.Class = record.Class;
|
||||
this.TimeToLive = record.TimeToLive;
|
||||
this.Data = record.Data;
|
||||
|
||||
// PTR
|
||||
this.PointerDomainName = (record as DnsClient.DnsPointerResourceRecord)?.PointerDomainName?.ToString();
|
||||
|
||||
// A
|
||||
this.IPAddress = (record as DnsClient.DnsIPAddressResourceRecord)?.IPAddress;
|
||||
|
||||
// NS
|
||||
this.NameServerDomainName = (record as DnsClient.DnsNameServerResourceRecord)?.NSDomainName?.ToString();
|
||||
|
||||
// CNAME
|
||||
this.CanonicalDomainName = (record as DnsClient.DnsCanonicalNameResourceRecord)?.CanonicalDomainName.ToString();
|
||||
|
||||
// MX
|
||||
this.MailExchangerDomainName = (record as DnsClient.DnsMailExchangeResourceRecord)?.ExchangeDomainName.ToString();
|
||||
this.MailExchangerPreference = (record as DnsClient.DnsMailExchangeResourceRecord)?.Preference;
|
||||
|
||||
// SOA
|
||||
this.SoaMasterDomainName = (record as DnsClient.DnsStartOfAuthorityResourceRecord)?.MasterDomainName.ToString();
|
||||
this.SoaResponsibleDomainName = (record as DnsClient.DnsStartOfAuthorityResourceRecord)?.ResponsibleDomainName.ToString();
|
||||
this.SoaSerialNumber = (record as DnsClient.DnsStartOfAuthorityResourceRecord)?.SerialNumber;
|
||||
this.SoaRefreshInterval = (record as DnsClient.DnsStartOfAuthorityResourceRecord)?.RefreshInterval;
|
||||
this.SoaRetryInterval = (record as DnsClient.DnsStartOfAuthorityResourceRecord)?.RetryInterval;
|
||||
this.SoaExpireInterval = (record as DnsClient.DnsStartOfAuthorityResourceRecord)?.ExpireInterval;
|
||||
this.SoaMinimumTimeToLive = (record as DnsClient.DnsStartOfAuthorityResourceRecord)?.MinimumTimeToLive;
|
||||
}
|
||||
|
||||
private DnsRecord() {
|
||||
// placeholder
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The name.
|
||||
/// </value>
|
||||
public String Name {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The type.
|
||||
/// </value>
|
||||
public DnsRecordType Type {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the class.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The class.
|
||||
/// </value>
|
||||
public DnsRecordClass Class {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the time to live.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The time to live.
|
||||
/// </value>
|
||||
public TimeSpan TimeToLive {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the raw data of the record.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The data.
|
||||
/// </value>
|
||||
public Byte[] Data {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the data text bytes in ASCII encoding.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The data text.
|
||||
/// </value>
|
||||
public String DataText => this.Data == null ? String.Empty : Encoding.ASCII.GetString(this.Data);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the pointer domain.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The name of the pointer domain.
|
||||
/// </value>
|
||||
public String PointerDomainName {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ip address.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The ip address.
|
||||
/// </value>
|
||||
public IPAddress IPAddress {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the name server domain.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The name of the name server domain.
|
||||
/// </value>
|
||||
public String NameServerDomainName {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the canonical domain.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The name of the canonical domain.
|
||||
/// </value>
|
||||
public String CanonicalDomainName {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the mail exchanger preference.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The mail exchanger preference.
|
||||
/// </value>
|
||||
public Int32? MailExchangerPreference {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the mail exchanger domain.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The name of the mail exchanger domain.
|
||||
/// </value>
|
||||
public String MailExchangerDomainName {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the soa master domain.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The name of the soa master domain.
|
||||
/// </value>
|
||||
public String SoaMasterDomainName {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the soa responsible domain.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The name of the soa responsible domain.
|
||||
/// </value>
|
||||
public String SoaResponsibleDomainName {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the soa serial number.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The soa serial number.
|
||||
/// </value>
|
||||
public Int64? SoaSerialNumber {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the soa refresh interval.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The soa refresh interval.
|
||||
/// </value>
|
||||
public TimeSpan? SoaRefreshInterval {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the soa retry interval.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The soa retry interval.
|
||||
/// </value>
|
||||
public TimeSpan? SoaRetryInterval {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the soa expire interval.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The soa expire interval.
|
||||
/// </value>
|
||||
public TimeSpan? SoaExpireInterval {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the soa minimum time to live.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The soa minimum time to live.
|
||||
/// </value>
|
||||
public TimeSpan? SoaMinimumTimeToLive {
|
||||
get;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
@ -1,168 +0,0 @@
|
||||
/*// ReSharper disable InconsistentNaming
|
||||
namespace Swan.Net.Dns {
|
||||
/// <summary>
|
||||
/// Enumerates the different DNS record types.
|
||||
/// </summary>
|
||||
public enum DnsRecordType {
|
||||
/// <summary>
|
||||
/// A records
|
||||
/// </summary>
|
||||
A = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Nameserver records
|
||||
/// </summary>
|
||||
NS = 2,
|
||||
|
||||
/// <summary>
|
||||
/// CNAME records
|
||||
/// </summary>
|
||||
CNAME = 5,
|
||||
|
||||
/// <summary>
|
||||
/// SOA records
|
||||
/// </summary>
|
||||
SOA = 6,
|
||||
|
||||
/// <summary>
|
||||
/// WKS records
|
||||
/// </summary>
|
||||
WKS = 11,
|
||||
|
||||
/// <summary>
|
||||
/// PTR records
|
||||
/// </summary>
|
||||
PTR = 12,
|
||||
|
||||
/// <summary>
|
||||
/// MX records
|
||||
/// </summary>
|
||||
MX = 15,
|
||||
|
||||
/// <summary>
|
||||
/// TXT records
|
||||
/// </summary>
|
||||
TXT = 16,
|
||||
|
||||
/// <summary>
|
||||
/// A records fot IPv6
|
||||
/// </summary>
|
||||
AAAA = 28,
|
||||
|
||||
/// <summary>
|
||||
/// SRV records
|
||||
/// </summary>
|
||||
SRV = 33,
|
||||
|
||||
/// <summary>
|
||||
/// ANY records
|
||||
/// </summary>
|
||||
ANY = 255,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enumerates the different DNS record classes.
|
||||
/// </summary>
|
||||
public enum DnsRecordClass {
|
||||
/// <summary>
|
||||
/// IN records
|
||||
/// </summary>
|
||||
IN = 1,
|
||||
|
||||
/// <summary>
|
||||
/// ANY records
|
||||
/// </summary>
|
||||
ANY = 255,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enumerates the different DNS operation codes.
|
||||
/// </summary>
|
||||
public enum DnsOperationCode {
|
||||
/// <summary>
|
||||
/// Query operation
|
||||
/// </summary>
|
||||
Query = 0,
|
||||
|
||||
/// <summary>
|
||||
/// IQuery operation
|
||||
/// </summary>
|
||||
IQuery,
|
||||
|
||||
/// <summary>
|
||||
/// Status operation
|
||||
/// </summary>
|
||||
Status,
|
||||
|
||||
/// <summary>
|
||||
/// Notify operation
|
||||
/// </summary>
|
||||
Notify = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Update operation
|
||||
/// </summary>
|
||||
Update,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enumerates the different DNS query response codes.
|
||||
/// </summary>
|
||||
public enum DnsResponseCode {
|
||||
/// <summary>
|
||||
/// No error
|
||||
/// </summary>
|
||||
NoError = 0,
|
||||
|
||||
/// <summary>
|
||||
/// No error
|
||||
/// </summary>
|
||||
FormatError,
|
||||
|
||||
/// <summary>
|
||||
/// Format error
|
||||
/// </summary>
|
||||
ServerFailure,
|
||||
|
||||
/// <summary>
|
||||
/// Server failure error
|
||||
/// </summary>
|
||||
NameError,
|
||||
|
||||
/// <summary>
|
||||
/// Name error
|
||||
/// </summary>
|
||||
NotImplemented,
|
||||
|
||||
/// <summary>
|
||||
/// Not implemented error
|
||||
/// </summary>
|
||||
Refused,
|
||||
|
||||
/// <summary>
|
||||
/// Refused error
|
||||
/// </summary>
|
||||
YXDomain,
|
||||
|
||||
/// <summary>
|
||||
/// YXRR error
|
||||
/// </summary>
|
||||
YXRRSet,
|
||||
|
||||
/// <summary>
|
||||
/// NXRR Set error
|
||||
/// </summary>
|
||||
NXRRSet,
|
||||
|
||||
/// <summary>
|
||||
/// Not authorized error
|
||||
/// </summary>
|
||||
NotAuth,
|
||||
|
||||
/// <summary>
|
||||
/// Not zone error
|
||||
/// </summary>
|
||||
NotZone,
|
||||
}
|
||||
}
|
||||
*/
|
@ -1,13 +1,5 @@
|
||||
//using Swan.Net.Dns;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Swan.Net {
|
||||
/// <summary>
|
||||
@ -15,16 +7,6 @@ namespace Swan.Net {
|
||||
/// a DNS client to query DNS records of any kind, and an NTP client.
|
||||
/// </summary>
|
||||
public static class Network {
|
||||
/*/// <summary>
|
||||
/// The DNS default port.
|
||||
/// </summary>
|
||||
public const Int32 DnsDefaultPort = 53;
|
||||
|
||||
/// <summary>
|
||||
/// The NTP default port.
|
||||
/// </summary>
|
||||
public const Int32 NtpDefaultPort = 123;*/
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the host.
|
||||
/// </summary>
|
||||
@ -32,259 +14,6 @@ namespace Swan.Net {
|
||||
/// The name of the host.
|
||||
/// </value>
|
||||
// [Obsolete("NEED", false)]
|
||||
public static String HostName => IPGlobalProperties.GetIPGlobalProperties().HostName;
|
||||
|
||||
/*/// <summary>
|
||||
/// Gets the name of the network domain.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The name of the network domain.
|
||||
/// </value>
|
||||
public static String DomainName => IPGlobalProperties.GetIPGlobalProperties().DomainName;
|
||||
|
||||
#region IP Addresses and Adapters Information Methods
|
||||
|
||||
/// <summary>
|
||||
/// Gets the active IPv4 interfaces.
|
||||
/// Only those interfaces with a valid unicast address and a valid gateway will be returned in the collection.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A collection of NetworkInterface/IPInterfaceProperties pairs
|
||||
/// that represents the active IPv4 interfaces.
|
||||
/// </returns>
|
||||
public static Dictionary<NetworkInterface, IPInterfaceProperties> GetIPv4Interfaces() {
|
||||
// zero conf ip address
|
||||
IPAddress zeroConf = new IPAddress(0);
|
||||
|
||||
NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces().Where(network => network.OperationalStatus == OperationalStatus.Up && network.NetworkInterfaceType != NetworkInterfaceType.Unknown && network.NetworkInterfaceType != NetworkInterfaceType.Loopback).ToArray();
|
||||
|
||||
Dictionary<NetworkInterface, IPInterfaceProperties> result = new Dictionary<NetworkInterface, IPInterfaceProperties>();
|
||||
|
||||
foreach(NetworkInterface adapter in adapters) {
|
||||
IPInterfaceProperties properties = adapter.GetIPProperties();
|
||||
if(properties == null || properties.GatewayAddresses.Count == 0 || properties.GatewayAddresses.All(gateway => Equals(gateway.Address, zeroConf)) || properties.UnicastAddresses.Count == 0 || properties.GatewayAddresses.All(address => Equals(address.Address, zeroConf)) || properties.UnicastAddresses.Any(a => a.Address.AddressFamily == AddressFamily.InterNetwork) == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
result[adapter] = properties;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the local ip addresses.
|
||||
/// </summary>
|
||||
/// <param name="includeLoopback">if set to <c>true</c> [include loopback].</param>
|
||||
/// <returns>An array of local ip addresses.</returns>
|
||||
public static IPAddress[] GetIPv4Addresses(Boolean includeLoopback = true) => GetIPv4Addresses(NetworkInterfaceType.Unknown, true, includeLoopback);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the local ip addresses.
|
||||
/// </summary>
|
||||
/// <param name="interfaceType">Type of the interface.</param>
|
||||
/// <param name="skipTypeFilter">if set to <c>true</c> [skip type filter].</param>
|
||||
/// <param name="includeLoopback">if set to <c>true</c> [include loopback].</param>
|
||||
/// <returns>An array of local ip addresses.</returns>
|
||||
public static IPAddress[] GetIPv4Addresses(NetworkInterfaceType interfaceType, Boolean skipTypeFilter = false, Boolean includeLoopback = false) {
|
||||
List<IPAddress> addressList = new List<IPAddress>();
|
||||
NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces()
|
||||
.Where(ni => (skipTypeFilter || ni.NetworkInterfaceType == interfaceType) && ni.OperationalStatus == OperationalStatus.Up).ToArray();
|
||||
|
||||
foreach(NetworkInterface networkInterface in interfaces) {
|
||||
IPInterfaceProperties properties = networkInterface.GetIPProperties();
|
||||
|
||||
if(properties.GatewayAddresses.All(g => g.Address.AddressFamily != AddressFamily.InterNetwork)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
addressList.AddRange(properties.UnicastAddresses.Where(i => i.Address.AddressFamily == AddressFamily.InterNetwork).Select(i => i.Address));
|
||||
}
|
||||
|
||||
if(includeLoopback || interfaceType == NetworkInterfaceType.Loopback) {
|
||||
addressList.Add(IPAddress.Loopback);
|
||||
}
|
||||
|
||||
return addressList.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the public IP address using ipify.org.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>A public IP address of the result produced by this Task.</returns>
|
||||
public static async Task<IPAddress> GetPublicIPAddressAsync(CancellationToken cancellationToken = default) {
|
||||
using HttpClient client = new HttpClient();
|
||||
HttpResponseMessage response = await client.GetAsync("https://api.ipify.org", cancellationToken).ConfigureAwait(false);
|
||||
return IPAddress.Parse(await response.Content.ReadAsStringAsync().ConfigureAwait(false));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the configured IPv4 DNS servers for the active network interfaces.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A collection of NetworkInterface/IPInterfaceProperties pairs
|
||||
/// that represents the active IPv4 interfaces.
|
||||
/// </returns>
|
||||
public static IPAddress[] GetIPv4DnsServers() => GetIPv4Interfaces().Select(a => a.Value.DnsAddresses.Where(d => d.AddressFamily == AddressFamily.InterNetwork)).SelectMany(d => d).ToArray();
|
||||
|
||||
#endregion
|
||||
|
||||
#region DNS and NTP Clients
|
||||
|
||||
/// <summary>
|
||||
/// Gets the DNS host entry (a list of IP addresses) for the domain name.
|
||||
/// </summary>
|
||||
/// <param name="fqdn">The FQDN.</param>
|
||||
/// <returns>An array of local ip addresses of the result produced by this task.</returns>
|
||||
public static Task<IPAddress[]> GetDnsHostEntryAsync(String fqdn) {
|
||||
IPAddress dnsServer = GetIPv4DnsServers().FirstOrDefault() ?? IPAddress.Parse("8.8.8.8");
|
||||
return GetDnsHostEntryAsync(fqdn, dnsServer, DnsDefaultPort);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the DNS host entry (a list of IP addresses) for the domain name.
|
||||
/// </summary>
|
||||
/// <param name="fqdn">The FQDN.</param>
|
||||
/// <param name="dnsServer">The DNS server.</param>
|
||||
/// <param name="port">The port.</param>
|
||||
/// <returns>
|
||||
/// An array of local ip addresses of the result produced by this task.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">fqdn.</exception>
|
||||
public static async Task<IPAddress[]> GetDnsHostEntryAsync(String fqdn, IPAddress dnsServer, Int32 port) {
|
||||
if(fqdn == null) {
|
||||
throw new ArgumentNullException(nameof(fqdn));
|
||||
}
|
||||
|
||||
if(fqdn.IndexOf(".", StringComparison.Ordinal) == -1) {
|
||||
fqdn += "." + IPGlobalProperties.GetIPGlobalProperties().DomainName;
|
||||
}
|
||||
|
||||
while(true) {
|
||||
if(!fqdn.EndsWith(".", StringComparison.OrdinalIgnoreCase)) {
|
||||
break;
|
||||
}
|
||||
|
||||
fqdn = fqdn[0..^1];
|
||||
}
|
||||
|
||||
DnsClient client = new DnsClient(dnsServer, port);
|
||||
IList<IPAddress> result = await client.Lookup(fqdn).ConfigureAwait(false);
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the reverse lookup FQDN of the given IP Address.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <param name="dnsServer">The DNS server.</param>
|
||||
/// <param name="port">The port.</param>
|
||||
/// <returns>A <see cref="System.String" /> that represents the current object.</returns>
|
||||
public static Task<String> GetDnsPointerEntryAsync(IPAddress query, IPAddress dnsServer, Int32 port) {
|
||||
DnsClient client = new DnsClient(dnsServer, port);
|
||||
return client.Reverse(query);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the reverse lookup FQDN of the given IP Address.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <returns>A <see cref="System.String" /> that represents the current object.</returns>
|
||||
public static Task<String> GetDnsPointerEntryAsync(IPAddress query) {
|
||||
DnsClient client = new DnsClient(GetIPv4DnsServers().FirstOrDefault());
|
||||
return client.Reverse(query);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queries the DNS server for the specified record type.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <param name="recordType">Type of the record.</param>
|
||||
/// <param name="dnsServer">The DNS server.</param>
|
||||
/// <param name="port">The port.</param>
|
||||
/// <returns>Queries the DNS server for the specified record type of the result produced by this Task.</returns>
|
||||
public static async Task<DnsQueryResult> QueryDnsAsync(String query, DnsRecordType recordType, IPAddress dnsServer, Int32 port) {
|
||||
if(query == null) {
|
||||
throw new ArgumentNullException(nameof(query));
|
||||
}
|
||||
|
||||
DnsClient client = new DnsClient(dnsServer, port);
|
||||
DnsClient.DnsClientResponse response = await client.Resolve(query, recordType).ConfigureAwait(false);
|
||||
return new DnsQueryResult(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queries the DNS server for the specified record type.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <param name="recordType">Type of the record.</param>
|
||||
/// <returns>Queries the DNS server for the specified record type of the result produced by this Task.</returns>
|
||||
public static Task<DnsQueryResult> QueryDnsAsync(String query, DnsRecordType recordType) => QueryDnsAsync(query, recordType, GetIPv4DnsServers().FirstOrDefault(), DnsDefaultPort);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the UTC time by querying from an NTP server.
|
||||
/// </summary>
|
||||
/// <param name="ntpServerAddress">The NTP server address.</param>
|
||||
/// <param name="port">The port.</param>
|
||||
/// <returns>The UTC time by querying from an NTP server of the result produced by this Task.</returns>
|
||||
public static async Task<DateTime> GetNetworkTimeUtcAsync(IPAddress ntpServerAddress, Int32 port = NtpDefaultPort) {
|
||||
if(ntpServerAddress == null) {
|
||||
throw new ArgumentNullException(nameof(ntpServerAddress));
|
||||
}
|
||||
|
||||
// NTP message size - 16 bytes of the digest (RFC 2030)
|
||||
Byte[] ntpData = new Byte[48];
|
||||
|
||||
// Setting the Leap Indicator, Version Number and Mode values
|
||||
ntpData[0] = 0x1B; // LI = 0 (no warning), VN = 3 (IPv4 only), Mode = 3 (Client Mode)
|
||||
|
||||
// The UDP port number assigned to NTP is 123
|
||||
IPEndPoint endPoint = new IPEndPoint(ntpServerAddress, port);
|
||||
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
||||
|
||||
|
||||
await socket.ConnectAsync(endPoint).ConfigureAwait(false);
|
||||
|
||||
|
||||
socket.ReceiveTimeout = 3000; // Stops code hang if NTP is blocked
|
||||
_ = socket.Send(ntpData);
|
||||
_ = socket.Receive(ntpData);
|
||||
socket.Dispose();
|
||||
|
||||
// Offset to get to the "Transmit Timestamp" field (time at which the reply
|
||||
// departed the server for the client, in 64-bit timestamp format."
|
||||
const Byte serverReplyTime = 40;
|
||||
|
||||
// Get the seconds part
|
||||
UInt64 intPart = BitConverter.ToUInt32(ntpData, serverReplyTime);
|
||||
|
||||
// Get the seconds fraction
|
||||
UInt64 fractPart = BitConverter.ToUInt32(ntpData, serverReplyTime + 4);
|
||||
|
||||
// Convert From big-endian to little-endian to match the platform
|
||||
if(BitConverter.IsLittleEndian) {
|
||||
intPart = intPart.SwapEndianness();
|
||||
fractPart = intPart.SwapEndianness();
|
||||
}
|
||||
|
||||
UInt64 milliseconds = intPart * 1000 + fractPart * 1000 / 0x100000000L;
|
||||
|
||||
// The time is given in UTC
|
||||
return new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds((Int64)milliseconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the UTC time by querying from an NTP server.
|
||||
/// </summary>
|
||||
/// <param name="ntpServerName">The NTP server, by default pool.ntp.org.</param>
|
||||
/// <param name="port">The port, by default NTP 123.</param>
|
||||
/// <returns>The UTC time by querying from an NTP server of the result produced by this Task.</returns>
|
||||
public static async Task<DateTime> GetNetworkTimeUtcAsync(String ntpServerName = "pool.ntp.org", Int32 port = NtpDefaultPort) {
|
||||
IPAddress[] addresses = await GetDnsHostEntryAsync(ntpServerName).ConfigureAwait(false);
|
||||
return await GetNetworkTimeUtcAsync(addresses.First(), port).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
#endregion*/
|
||||
public static String HostName => IPGlobalProperties.GetIPGlobalProperties().HostName;
|
||||
}
|
||||
}
|
||||
|
@ -60,25 +60,6 @@ namespace Swan {
|
||||
return result.ExitCode == 0 ? result.StandardOutput : result.StandardError;
|
||||
}
|
||||
|
||||
/*/// <summary>
|
||||
/// Runs the process asynchronously and if the exit code is 0,
|
||||
/// returns all of the standard output text. If the exit code is something other than 0
|
||||
/// it returns the contents of standard error.
|
||||
/// This method is meant to be used for programs that output a relatively small amount
|
||||
/// of text using a different encoder.
|
||||
/// </summary>
|
||||
/// <param name="filename">The filename.</param>
|
||||
/// <param name="arguments">The arguments.</param>
|
||||
/// <param name="encoding">The encoding.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>
|
||||
/// The type of the result produced by this Task.
|
||||
/// </returns>
|
||||
public static async Task<String> GetProcessEncodedOutputAsync(String filename, String arguments = "", Encoding? encoding = null, CancellationToken cancellationToken = default) {
|
||||
ProcessResult result = await GetProcessResultAsync(filename, arguments, null, encoding, cancellationToken).ConfigureAwait(false);
|
||||
return result.ExitCode == 0 ? result.StandardOutput : result.StandardError;
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// Executes a process asynchronously and returns the text of the standard output and standard error streams
|
||||
/// along with the exit code. This method is meant to be used for programs that output a relatively small
|
||||
|
@ -37,50 +37,6 @@ namespace Swan.Reflection {
|
||||
get;
|
||||
}
|
||||
|
||||
/*/// <summary>
|
||||
/// Determines whether [contains] [the specified member].
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the attribute to be retrieved.</typeparam>
|
||||
/// <param name="member">The member.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if [contains] [the specified member]; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public Boolean Contains<T>(MemberInfo member) => this._data.Value.ContainsKey(new Tuple<Object, Type>(member, typeof(T)));
|
||||
|
||||
/// <summary>
|
||||
/// Gets specific attributes from a member constrained to an attribute.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the attribute to be retrieved.</typeparam>
|
||||
/// <param name="member">The member.</param>
|
||||
/// <param name="inherit"><c>true</c> to inspect the ancestors of element; otherwise, <c>false</c>.</param>
|
||||
/// <returns>An array of the attributes stored for the specified type.</returns>
|
||||
public IEnumerable<Object> Retrieve<T>(MemberInfo member, Boolean inherit = false) where T : Attribute {
|
||||
if(member == null) {
|
||||
throw new ArgumentNullException(nameof(member));
|
||||
}
|
||||
|
||||
return this.Retrieve(new Tuple<Object, Type>(member, typeof(T)), t => member.GetCustomAttributes<T>(inherit));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all attributes of a specific type from a member.
|
||||
/// </summary>
|
||||
/// <param name="member">The member.</param>
|
||||
/// <param name="type">The attribute type.</param>
|
||||
/// <param name="inherit"><c>true</c> to inspect the ancestors of element; otherwise, <c>false</c>.</param>
|
||||
/// <returns>An array of the attributes stored for the specified type.</returns>
|
||||
public IEnumerable<Object> Retrieve(MemberInfo member, Type type, Boolean inherit = false) {
|
||||
if(member == null) {
|
||||
throw new ArgumentNullException(nameof(member));
|
||||
}
|
||||
|
||||
if(type == null) {
|
||||
throw new ArgumentNullException(nameof(type));
|
||||
}
|
||||
|
||||
return this.Retrieve(new Tuple<Object, Type>(member, type), t => member.GetCustomAttributes(type, inherit));
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// Gets one attribute of a specific type from a member.
|
||||
/// </summary>
|
||||
@ -98,56 +54,6 @@ namespace Swan.Reflection {
|
||||
return ConvertToAttribute<T>(attr);
|
||||
}
|
||||
|
||||
/*/// <summary>
|
||||
/// Gets one attribute of a specific type from a generic type.
|
||||
/// </summary>
|
||||
/// <typeparam name="TAttribute">The type of the attribute.</typeparam>
|
||||
/// <typeparam name="T">The type to retrieve the attribute.</typeparam>
|
||||
/// <param name="inherit">if set to <c>true</c> [inherit].</param>
|
||||
/// <returns>An attribute stored for the specified type.</returns>
|
||||
public TAttribute RetrieveOne<TAttribute, T>(Boolean inherit = false) where TAttribute : Attribute {
|
||||
IEnumerable<Object> attr = this.Retrieve(new Tuple<Object, Type>(typeof(T), typeof(TAttribute)), t => typeof(T).GetCustomAttributes(typeof(TAttribute), inherit));
|
||||
|
||||
return ConvertToAttribute<TAttribute>(attr);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all properties an their attributes of a given type constrained to only attributes.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the attribute to retrieve.</typeparam>
|
||||
/// <param name="type">The type of the object.</param>
|
||||
/// <param name="inherit"><c>true</c> to inspect the ancestors of element; otherwise, <c>false</c>.</param>
|
||||
/// <returns>A dictionary of the properties and their attributes stored for the specified type.</returns>
|
||||
public Dictionary<PropertyInfo, IEnumerable<Object>> Retrieve<T>(Type type, Boolean inherit = false) where T : Attribute => this.PropertyTypeCache.RetrieveAllProperties(type, true).ToDictionary(x => x, x => this.Retrieve<T>(x, inherit));
|
||||
|
||||
/// <summary>
|
||||
/// Gets all properties and their attributes of a given type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The object type used to extract the properties from.</typeparam>
|
||||
/// <typeparam name="TAttribute">The type of the attribute.</typeparam>
|
||||
/// <param name="inherit"><c>true</c> to inspect the ancestors of element; otherwise, <c>false</c>.</param>
|
||||
/// <returns>
|
||||
/// A dictionary of the properties and their attributes stored for the specified type.
|
||||
/// </returns>
|
||||
public Dictionary<PropertyInfo, IEnumerable<Object>> RetrieveFromType<T, TAttribute>(Boolean inherit = false) => this.RetrieveFromType<T>(typeof(TAttribute), inherit);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all properties and their attributes of a given type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The object type used to extract the properties from.</typeparam>
|
||||
/// <param name="attributeType">Type of the attribute.</param>
|
||||
/// <param name="inherit"><c>true</c> to inspect the ancestors of element; otherwise, <c>false</c>.</param>
|
||||
/// <returns>
|
||||
/// A dictionary of the properties and their attributes stored for the specified type.
|
||||
/// </returns>
|
||||
public Dictionary<PropertyInfo, IEnumerable<Object>> RetrieveFromType<T>(Type attributeType, Boolean inherit = false) {
|
||||
if(attributeType == null) {
|
||||
throw new ArgumentNullException(nameof(attributeType));
|
||||
}
|
||||
|
||||
return this.PropertyTypeCache.RetrieveAllProperties<T>(true).ToDictionary(x => x, x => this.Retrieve(x, attributeType, inherit));
|
||||
}*/
|
||||
|
||||
private static T ConvertToAttribute<T>(IEnumerable<Object> attr) where T : Attribute => attr?.Any() != true ? (default!) : attr.Count() == 1 ? (T)Convert.ChangeType(attr.First(), typeof(T)) : throw new AmbiguousMatchException("Multiple custom attributes of the same type found.");
|
||||
|
||||
private IEnumerable<Object> Retrieve(Tuple<Object, Type> key, Func<Tuple<Object, Type>, IEnumerable<Object>> factory) {
|
||||
|
@ -17,16 +17,6 @@ namespace Swan.Lite.Reflection {
|
||||
/// </value>
|
||||
public static Lazy<ConstructorTypeCache> DefaultCache { get; } = new Lazy<ConstructorTypeCache>(() => new ConstructorTypeCache());
|
||||
|
||||
/*/// <summary>
|
||||
/// Retrieves all constructors order by the number of parameters ascending.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to inspect.</typeparam>
|
||||
/// <param name="includeNonPublic">if set to <c>true</c> [include non public].</param>
|
||||
/// <returns>
|
||||
/// A collection with all the constructors in the given type.
|
||||
/// </returns>
|
||||
public IEnumerable<Tuple<ConstructorInfo, ParameterInfo[]>> RetrieveAllConstructors<T>(Boolean includeNonPublic = false) => this.Retrieve<T>(GetConstructors(includeNonPublic));*/
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all constructors order by the number of parameters ascending.
|
||||
/// </summary>
|
||||
|
@ -234,14 +234,5 @@ namespace Swan.Reflection {
|
||||
public ExtendedTypeInfo() : base(typeof(T)) {
|
||||
// placeholder
|
||||
}
|
||||
|
||||
/*/// <summary>
|
||||
/// Converts this instance to its string representation,
|
||||
/// trying to use the CultureInfo.InvariantCulture
|
||||
/// IFormat provider if the overload is available.
|
||||
/// </summary>
|
||||
/// <param name="instance">The instance.</param>
|
||||
/// <returns>A <see cref="System.String" /> that represents the current object.</returns>
|
||||
public String ToStringInvariant(T instance) => base.ToStringInvariant(instance);*/
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +0,0 @@
|
||||
/*using System;
|
||||
|
||||
namespace Swan.Reflection {
|
||||
/// <summary>
|
||||
/// Represents a generic interface to store getters and setters.
|
||||
/// </summary>
|
||||
public interface IPropertyProxy {
|
||||
/// <summary>
|
||||
/// Gets the property value via a stored delegate.
|
||||
/// </summary>
|
||||
/// <param name="instance">The instance.</param>
|
||||
/// <returns>The property value.</returns>
|
||||
Object GetValue(Object instance);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the property value via a stored delegate.
|
||||
/// </summary>
|
||||
/// <param name="instance">The instance.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
void SetValue(Object instance, Object value);
|
||||
}
|
||||
}*/
|
@ -1,44 +0,0 @@
|
||||
/*using System;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Swan.Reflection {
|
||||
/// <summary>
|
||||
/// Represents a generic class to store getters and setters.
|
||||
/// </summary>
|
||||
/// <typeparam name="TClass">The type of the class.</typeparam>
|
||||
/// <typeparam name="TProperty">The type of the property.</typeparam>
|
||||
/// <seealso cref="IPropertyProxy" />
|
||||
public sealed class PropertyProxy<TClass, TProperty> : IPropertyProxy where TClass : class {
|
||||
private readonly Func<TClass, TProperty> _getter;
|
||||
private readonly Action<TClass, TProperty> _setter;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PropertyProxy{TClass, TProperty}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="property">The property.</param>
|
||||
public PropertyProxy(PropertyInfo property) {
|
||||
if(property == null) {
|
||||
throw new ArgumentNullException(nameof(property));
|
||||
}
|
||||
|
||||
MethodInfo getterInfo = property.GetGetMethod(false);
|
||||
if(getterInfo != null) {
|
||||
this._getter = (Func<TClass, TProperty>)Delegate.CreateDelegate(typeof(Func<TClass, TProperty>), getterInfo);
|
||||
}
|
||||
|
||||
MethodInfo setterInfo = property.GetSetMethod(false);
|
||||
if(setterInfo != null) {
|
||||
this._setter = (Action<TClass, TProperty>)Delegate.CreateDelegate(typeof(Action<TClass, TProperty>), setterInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
Object IPropertyProxy.GetValue(Object instance) => this._getter(instance as TClass);
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void IPropertyProxy.SetValue(Object instance, Object value) => this._setter(instance as TClass, (TProperty)value);
|
||||
}
|
||||
}*/
|
@ -16,16 +16,6 @@ namespace Swan.Reflection {
|
||||
/// </value>
|
||||
public static Lazy<PropertyTypeCache> DefaultCache { get; } = new Lazy<PropertyTypeCache>(() => new PropertyTypeCache());
|
||||
|
||||
/*/// <summary>
|
||||
/// Retrieves all properties.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to inspect.</typeparam>
|
||||
/// <param name="onlyPublic">if set to <c>true</c> [only public].</param>
|
||||
/// <returns>
|
||||
/// A collection with all the properties in the given type.
|
||||
/// </returns>
|
||||
public IEnumerable<PropertyInfo> RetrieveAllProperties<T>(Boolean onlyPublic = false) => this.Retrieve<T>(onlyPublic ? GetAllPublicPropertiesFunc() : GetAllPropertiesFunc());*/
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all properties.
|
||||
/// </summary>
|
||||
|
@ -13,24 +13,7 @@ namespace Swan.Reflection {
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of Member to be cached.</typeparam>
|
||||
public abstract class TypeCache<T> : CollectionCacheRepository<T> {
|
||||
/*/// <summary>
|
||||
/// Determines whether the cache contains the specified type.
|
||||
/// </summary>
|
||||
/// <typeparam name="TOut">The type of the out.</typeparam>
|
||||
/// <returns>
|
||||
/// <c>true</c> if [contains]; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public Boolean Contains<TOut>() => this.ContainsKey(typeof(TOut));
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <typeparam name="TOut">The type of the out.</typeparam>
|
||||
/// <param name="factory">The factory.</param>
|
||||
/// <returns>An array of the properties stored for the specified type.</returns>
|
||||
public IEnumerable<T> Retrieve<TOut>(Func<Type, IEnumerable<T>> factory) => this.Retrieve(typeof(TOut), factory);*/
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -48,15 +31,6 @@ namespace Swan.Reflection {
|
||||
/// </value>
|
||||
public static Lazy<FieldTypeCache> DefaultCache { get; } = new Lazy<FieldTypeCache>(() => new FieldTypeCache());
|
||||
|
||||
/*/// <summary>
|
||||
/// Retrieves all fields.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to inspect.</typeparam>
|
||||
/// <returns>
|
||||
/// A collection with all the fields in the given type.
|
||||
/// </returns>
|
||||
public IEnumerable<FieldInfo> RetrieveAllFields<T>() => this.Retrieve<T>(GetAllFieldsFunc());*/
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all fields.
|
||||
/// </summary>
|
||||
|
@ -1,27 +0,0 @@
|
||||
/*using System;
|
||||
|
||||
namespace Swan {
|
||||
/// <summary>
|
||||
/// An attribute used to help conversion structs back and forth into arrays of bytes via
|
||||
/// extension methods included in this library ToStruct and ToBytes.
|
||||
/// </summary>
|
||||
/// <seealso cref="Attribute" />
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Struct)]
|
||||
public class StructEndiannessAttribute : Attribute {
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="StructEndiannessAttribute"/> class.
|
||||
/// </summary>
|
||||
/// <param name="endianness">The endianness.</param>
|
||||
public StructEndiannessAttribute(Endianness endianness) => this.Endianness = endianness;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the endianness.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The endianness.
|
||||
/// </value>
|
||||
public Endianness Endianness {
|
||||
get;
|
||||
}
|
||||
}
|
||||
}*/
|
@ -1,35 +1,11 @@
|
||||
using Swan.Logging;
|
||||
using System;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
|
||||
namespace Swan {
|
||||
/// <summary>
|
||||
/// Provides utility methods to retrieve information about the current application.
|
||||
/// </summary>
|
||||
public static class SwanRuntime {
|
||||
/*private static readonly Lazy<Assembly> EntryAssemblyLazy = new Lazy<Assembly>(Assembly.GetEntryAssembly);
|
||||
|
||||
private static readonly Lazy<String> CompanyNameLazy = new Lazy<String>(() => {
|
||||
AssemblyCompanyAttribute attribute = EntryAssembly.GetCustomAttribute(typeof(AssemblyCompanyAttribute)) as AssemblyCompanyAttribute;
|
||||
return attribute?.Company ?? String.Empty;
|
||||
});
|
||||
|
||||
private static readonly Lazy<String> ProductNameLazy = new Lazy<String>(() => {
|
||||
AssemblyProductAttribute attribute = EntryAssembly.GetCustomAttribute(typeof(AssemblyProductAttribute)) as AssemblyProductAttribute;
|
||||
return attribute?.Product ?? String.Empty;
|
||||
});
|
||||
|
||||
private static readonly Lazy<String> ProductTrademarkLazy = new Lazy<String>(() => {
|
||||
AssemblyTrademarkAttribute attribute = EntryAssembly.GetCustomAttribute(typeof(AssemblyTrademarkAttribute)) as AssemblyTrademarkAttribute;
|
||||
return attribute?.Trademark ?? String.Empty;
|
||||
});
|
||||
|
||||
private static readonly String ApplicationMutexName = "Global\\{{" + EntryAssembly.FullName + "}}";
|
||||
|
||||
private static readonly Object SyncLock = new Object();*/
|
||||
|
||||
// [Obsolete("NEED", false)]
|
||||
private static OperatingSystem? _oS;
|
||||
|
||||
@ -54,148 +30,6 @@ namespace Swan {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*/// <summary>
|
||||
/// Checks if this application (including version number) is the only instance currently running.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance is the only instance; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Codequalität", "IDE0067:Objekte verwerfen, bevor Bereich verloren geht", Justification = "<Ausstehend>")]
|
||||
public static Boolean IsTheOnlyInstance {
|
||||
get {
|
||||
lock(SyncLock) {
|
||||
try {
|
||||
// Try to open existing mutex.
|
||||
_ = Mutex.OpenExisting(ApplicationMutexName);
|
||||
} catch {
|
||||
try {
|
||||
// If exception occurred, there is no such mutex.
|
||||
Mutex appMutex = new Mutex(true, ApplicationMutexName);
|
||||
$"Application Mutex created {appMutex} named '{ApplicationMutexName}'".Debug(typeof(SwanRuntime));
|
||||
|
||||
// Only one instance.
|
||||
return true;
|
||||
} catch {
|
||||
// Sometimes the user can't create the Global Mutex
|
||||
}
|
||||
}
|
||||
|
||||
// More than one instance.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this application instance is using the MONO runtime.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance is using MONO runtime; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public static Boolean IsUsingMonoRuntime => Type.GetType("Mono.Runtime") != null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the assembly that started the application.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The entry assembly.
|
||||
/// </value>
|
||||
public static Assembly EntryAssembly => EntryAssemblyLazy.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the entry assembly.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The name of the entry assembly.
|
||||
/// </value>
|
||||
public static AssemblyName EntryAssemblyName => EntryAssemblyLazy.Value.GetName();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the entry assembly version.
|
||||
/// </summary>
|
||||
public static Version EntryAssemblyVersion => EntryAssemblyName.Version;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the full path to the folder containing the assembly that started the application.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The entry assembly directory.
|
||||
/// </value>
|
||||
public static String EntryAssemblyDirectory {
|
||||
get {
|
||||
UriBuilder uri = new UriBuilder(EntryAssembly.CodeBase);
|
||||
String path = Uri.UnescapeDataString(uri.Path);
|
||||
return Path.GetDirectoryName(path);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the company.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The name of the company.
|
||||
/// </value>
|
||||
public static String CompanyName => CompanyNameLazy.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the product.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The name of the product.
|
||||
/// </value>
|
||||
public static String ProductName => ProductNameLazy.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the trademark.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The product trademark.
|
||||
/// </value>
|
||||
public static String ProductTrademark => ProductTrademarkLazy.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a local storage path with a version.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The local storage path.
|
||||
/// </value>
|
||||
public static String LocalStoragePath {
|
||||
get {
|
||||
String localAppDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), EntryAssemblyName.Name);
|
||||
|
||||
String returnPath = Path.Combine(localAppDataPath, EntryAssemblyVersion.ToString());
|
||||
|
||||
if(!Directory.Exists(returnPath)) {
|
||||
_ = Directory.CreateDirectory(returnPath);
|
||||
}
|
||||
|
||||
return returnPath;
|
||||
}
|
||||
}*/
|
||||
|
||||
#endregion
|
||||
|
||||
/*#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// Build a full path pointing to the current user's desktop with the given filename.
|
||||
/// </summary>
|
||||
/// <param name="filename">The filename.</param>
|
||||
/// <returns>
|
||||
/// The fully qualified location of path, such as "C:\MyFile.txt".
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">filename.</exception>
|
||||
public static String GetDesktopFilePath(String filename) {
|
||||
if(String.IsNullOrWhiteSpace(filename)) {
|
||||
throw new ArgumentNullException(nameof(filename));
|
||||
}
|
||||
|
||||
String pathWithFilename = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), filename);
|
||||
|
||||
return Path.GetFullPath(pathWithFilename);
|
||||
}
|
||||
|
||||
#endregion*/
|
||||
}
|
||||
}
|
||||
|
@ -7,33 +7,6 @@ namespace Swan {
|
||||
/// This class is thread-safe :).
|
||||
/// </summary>
|
||||
public static partial class Terminal {
|
||||
/*/// <summary>
|
||||
/// Writes a character a number of times, optionally adding a new line at the end.
|
||||
/// </summary>
|
||||
/// <param name="charCode">The character code.</param>
|
||||
/// <param name="color">The color.</param>
|
||||
/// <param name="count">The count.</param>
|
||||
/// <param name="newLine">if set to <c>true</c> [new line].</param>
|
||||
/// <param name="writerFlags">The writer flags.</param>
|
||||
public static void Write(Char charCode, ConsoleColor? color = null, Int32 count = 1, Boolean newLine = false, TerminalWriters writerFlags = TerminalWriters.StandardOutput) {
|
||||
lock(SyncLock) {
|
||||
String text = new String(charCode, count);
|
||||
|
||||
if(newLine) {
|
||||
text += Environment.NewLine;
|
||||
}
|
||||
|
||||
Byte[] buffer = OutputEncoding.GetBytes(text);
|
||||
OutputContext context = new OutputContext {
|
||||
OutputColor = color ?? Settings.DefaultColor,
|
||||
OutputText = OutputEncoding.GetChars(buffer),
|
||||
OutputWriters = writerFlags,
|
||||
};
|
||||
|
||||
EnqueueOutput(context);
|
||||
}
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// Writes the specified text in the given color.
|
||||
/// </summary>
|
||||
@ -57,33 +30,5 @@ namespace Swan {
|
||||
EnqueueOutput(context);
|
||||
}
|
||||
}
|
||||
|
||||
/*/// <summary>
|
||||
/// Writes a New Line Sequence to the standard output.
|
||||
/// </summary>
|
||||
/// <param name="writerFlags">The writer flags.</param>
|
||||
public static void WriteLine(TerminalWriters writerFlags = TerminalWriters.StandardOutput) => Write(Environment.NewLine, Settings.DefaultColor, writerFlags);
|
||||
|
||||
/// <summary>
|
||||
/// Writes a line of text in the current console foreground color
|
||||
/// to the standard output.
|
||||
/// </summary>
|
||||
/// <param name="text">The text.</param>
|
||||
/// <param name="color">The color.</param>
|
||||
/// <param name="writerFlags">The writer flags.</param>
|
||||
public static void WriteLine(String text, ConsoleColor? color = null, TerminalWriters writerFlags = TerminalWriters.StandardOutput) => Write($"{text ?? String.Empty}{Environment.NewLine}", color, writerFlags);
|
||||
|
||||
/// <summary>
|
||||
/// As opposed to WriteLine methods, it prepends a Carriage Return character to the text
|
||||
/// so that the console moves the cursor one position up after the text has been written out.
|
||||
/// </summary>
|
||||
/// <param name="text">The text.</param>
|
||||
/// <param name="color">The color.</param>
|
||||
/// <param name="writerFlags">The writer flags.</param>
|
||||
public static void OverwriteLine(String text, ConsoleColor? color = null, TerminalWriters writerFlags = TerminalWriters.StandardOutput) {
|
||||
Write($"\r{text ?? String.Empty}", color, writerFlags);
|
||||
Flush();
|
||||
CursorLeft = 0;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
@ -17,30 +17,6 @@ namespace Swan {
|
||||
/// The default color.
|
||||
/// </value>
|
||||
public static ConsoleColor DefaultColor { get; set; } = Console.ForegroundColor;
|
||||
|
||||
/*/// <summary>
|
||||
/// Gets the color of the border.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The color of the border.
|
||||
/// </value>
|
||||
public static ConsoleColor BorderColor { get; } = ConsoleColor.DarkGreen;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the user input prefix.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The user input prefix.
|
||||
/// </value>
|
||||
public static String UserInputPrefix { get; set; } = "USR";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the user option text.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The user option text.
|
||||
/// </value>
|
||||
public static String UserOptionText { get; set; } = " Option: ";*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -50,73 +50,7 @@ namespace Swan {
|
||||
DequeueOutputTimer = new ExclusiveTimer(DequeueOutputCycle);
|
||||
DequeueOutputTimer.Resume(OutputFlushInterval);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/*#region Synchronized Cursor Movement
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the cursor left position.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The cursor left.
|
||||
/// </value>
|
||||
public static Int32 CursorLeft {
|
||||
get {
|
||||
if(IsConsolePresent == false) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
lock(SyncLock) {
|
||||
Flush();
|
||||
return Console.CursorLeft;
|
||||
}
|
||||
}
|
||||
set {
|
||||
if(IsConsolePresent == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
lock(SyncLock) {
|
||||
Flush();
|
||||
Console.CursorLeft = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the cursor top position.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The cursor top.
|
||||
/// </value>
|
||||
public static Int32 CursorTop {
|
||||
get {
|
||||
if(IsConsolePresent == false) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
lock(SyncLock) {
|
||||
Flush();
|
||||
return Console.CursorTop;
|
||||
}
|
||||
}
|
||||
set {
|
||||
if(IsConsolePresent == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
lock(SyncLock) {
|
||||
Flush();
|
||||
Console.CursorTop = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion*/
|
||||
|
||||
#region Properties
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the Console is present.
|
||||
@ -166,75 +100,6 @@ namespace Swan {
|
||||
|
||||
#region Methods
|
||||
|
||||
/*/// <summary>
|
||||
/// Waits for all of the queued output messages to be written out to the console.
|
||||
/// Call this method if it is important to display console text before
|
||||
/// quitting the application such as showing usage or help.
|
||||
/// Set the timeout to null or TimeSpan.Zero to wait indefinitely.
|
||||
/// </summary>
|
||||
/// <param name="timeout">The timeout. Set the amount of time to black before this method exits.</param>
|
||||
public static void Flush(TimeSpan? timeout = null) {
|
||||
if(timeout == null) {
|
||||
timeout = TimeSpan.Zero;
|
||||
}
|
||||
|
||||
DateTime startTime = DateTime.UtcNow;
|
||||
|
||||
while(OutputQueue.Count > 0) {
|
||||
// Manually trigger a timer cycle to run immediately
|
||||
DequeueOutputTimer.Change(0, OutputFlushInterval);
|
||||
|
||||
// Wait for the output to finish
|
||||
if(OutputDone.Wait(OutputFlushInterval)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// infinite timeout
|
||||
if(timeout.Value == TimeSpan.Zero) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// break if we have reached a timeout condition
|
||||
if(DateTime.UtcNow.Subtract(startTime) >= timeout.Value) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the cursor position.
|
||||
/// </summary>
|
||||
/// <param name="left">The left.</param>
|
||||
/// <param name="top">The top.</param>
|
||||
public static void SetCursorPosition(Int32 left, Int32 top) {
|
||||
if(!IsConsolePresent) {
|
||||
return;
|
||||
}
|
||||
|
||||
lock(SyncLock) {
|
||||
Flush();
|
||||
Console.SetCursorPosition(left.Clamp(0, left), top.Clamp(0, top));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moves the output cursor one line up starting at left position 0
|
||||
/// Please note that backlining the cursor does not clear the contents of the
|
||||
/// previous line so you might need to clear it by writing an empty string the
|
||||
/// length of the console width.
|
||||
/// </summary>
|
||||
public static void BacklineCursor() => SetCursorPosition(0, CursorTop - 1);
|
||||
|
||||
/// <summary>
|
||||
/// Writes a standard banner to the standard output
|
||||
/// containing the company name, product name, assembly version and trademark.
|
||||
/// </summary>
|
||||
/// <param name="color">The color.</param>
|
||||
public static void WriteWelcomeBanner(ConsoleColor color = ConsoleColor.Gray) {
|
||||
WriteLine($"{SwanRuntime.CompanyName} {SwanRuntime.ProductName} [Version {SwanRuntime.EntryAssemblyVersion}]", color);
|
||||
WriteLine($"{SwanRuntime.ProductTrademark}", color);
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// Enqueues the output to be written to the console
|
||||
/// This is the only method that should enqueue to the output
|
||||
|
@ -54,96 +54,6 @@ namespace Swan.Threading {
|
||||
/// </returns>
|
||||
public static Boolean operator !=(AtomicTypeBase<T> a, T b) => a?.Equals(b) == false;
|
||||
|
||||
/*/// <summary>
|
||||
/// Implements the operator >.
|
||||
/// </summary>
|
||||
/// <param name="a">a.</param>
|
||||
/// <param name="b">The b.</param>
|
||||
/// <returns>
|
||||
/// The result of the operator.
|
||||
/// </returns>
|
||||
public static Boolean operator >(AtomicTypeBase<T> a, T b) => a.CompareTo(b) > 0;
|
||||
|
||||
/// <summary>
|
||||
/// Implements the operator <.
|
||||
/// </summary>
|
||||
/// <param name="a">a.</param>
|
||||
/// <param name="b">The b.</param>
|
||||
/// <returns>
|
||||
/// The result of the operator.
|
||||
/// </returns>
|
||||
public static Boolean operator <(AtomicTypeBase<T> a, T b) => a.CompareTo(b) < 0;
|
||||
|
||||
/// <summary>
|
||||
/// Implements the operator >=.
|
||||
/// </summary>
|
||||
/// <param name="a">a.</param>
|
||||
/// <param name="b">The b.</param>
|
||||
/// <returns>
|
||||
/// The result of the operator.
|
||||
/// </returns>
|
||||
public static Boolean operator >=(AtomicTypeBase<T> a, T b) => a.CompareTo(b) >= 0;
|
||||
|
||||
/// <summary>
|
||||
/// Implements the operator <=.
|
||||
/// </summary>
|
||||
/// <param name="a">a.</param>
|
||||
/// <param name="b">The b.</param>
|
||||
/// <returns>
|
||||
/// The result of the operator.
|
||||
/// </returns>
|
||||
public static Boolean operator <=(AtomicTypeBase<T> a, T b) => a.CompareTo(b) <= 0;
|
||||
|
||||
/// <summary>
|
||||
/// Implements the operator ++.
|
||||
/// </summary>
|
||||
/// <param name="instance">The instance.</param>
|
||||
/// <returns>
|
||||
/// The result of the operator.
|
||||
/// </returns>
|
||||
public static AtomicTypeBase<T> operator ++(AtomicTypeBase<T> instance) {
|
||||
_ = Interlocked.Increment(ref instance._backingValue);
|
||||
return instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements the operator --.
|
||||
/// </summary>
|
||||
/// <param name="instance">The instance.</param>
|
||||
/// <returns>
|
||||
/// The result of the operator.
|
||||
/// </returns>
|
||||
public static AtomicTypeBase<T> operator --(AtomicTypeBase<T> instance) {
|
||||
_ = Interlocked.Decrement(ref instance._backingValue);
|
||||
return instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements the operator -<.
|
||||
/// </summary>
|
||||
/// <param name="instance">The instance.</param>
|
||||
/// <param name="operand">The operand.</param>
|
||||
/// <returns>
|
||||
/// The result of the operator.
|
||||
/// </returns>
|
||||
public static AtomicTypeBase<T> operator +(AtomicTypeBase<T> instance, Int64 operand) {
|
||||
instance.BackingValue += operand;
|
||||
return instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements the operator -.
|
||||
/// </summary>
|
||||
/// <param name="instance">The instance.</param>
|
||||
/// <param name="operand">The operand.</param>
|
||||
/// <returns>
|
||||
/// The result of the operator.
|
||||
/// </returns>
|
||||
public static AtomicTypeBase<T> operator -(AtomicTypeBase<T> instance, Int64 operand) {
|
||||
instance.BackingValue -= operand;
|
||||
return instance;
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// Compares the value to the other instance.
|
||||
/// </summary>
|
||||
|
@ -29,25 +29,6 @@ namespace Swan.Threading {
|
||||
this._backingTimer = new Timer(this.InternalCallback, state ?? this, dueTime, Timeout.Infinite);
|
||||
}
|
||||
|
||||
/*/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ExclusiveTimer"/> class.
|
||||
/// </summary>
|
||||
/// <param name="timerCallback">The timer callback.</param>
|
||||
/// <param name="state">The state.</param>
|
||||
/// <param name="dueTime">The due time.</param>
|
||||
/// <param name="period">The period.</param>
|
||||
public ExclusiveTimer(TimerCallback timerCallback, Object state, TimeSpan dueTime, TimeSpan period) : this(timerCallback, state, Convert.ToInt32(dueTime.TotalMilliseconds), Convert.ToInt32(period.TotalMilliseconds)) {
|
||||
// placeholder
|
||||
}*/
|
||||
|
||||
/*/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ExclusiveTimer"/> class.
|
||||
/// </summary>
|
||||
/// <param name="timerCallback">The timer callback.</param>
|
||||
public ExclusiveTimer(TimerCallback timerCallback) : this(timerCallback, null, Timeout.Infinite, Timeout.Infinite) {
|
||||
// placeholder
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ExclusiveTimer"/> class.
|
||||
/// </summary>
|
||||
@ -58,16 +39,6 @@ namespace Swan.Threading {
|
||||
// placeholder
|
||||
}
|
||||
|
||||
/*/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ExclusiveTimer"/> class.
|
||||
/// </summary>
|
||||
/// <param name="timerCallback">The timer callback.</param>
|
||||
/// <param name="dueTime">The due time.</param>
|
||||
/// <param name="period">The period.</param>
|
||||
public ExclusiveTimer(Action timerCallback, TimeSpan dueTime, TimeSpan period) : this(s => timerCallback?.Invoke(), null, dueTime, period) {
|
||||
// placeholder
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ExclusiveTimer"/> class.
|
||||
/// </summary>
|
||||
@ -93,36 +64,6 @@ namespace Swan.Threading {
|
||||
/// </value>
|
||||
public Boolean IsDisposed => this._isDisposed.Value;
|
||||
|
||||
/*/// <summary>
|
||||
/// Waits until the time is elapsed.
|
||||
/// </summary>
|
||||
/// <param name="untilDate">The until date.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
public static void WaitUntil(DateTime untilDate, CancellationToken cancellationToken = default) {
|
||||
static void Callback(IWaitEvent waitEvent) {
|
||||
try {
|
||||
waitEvent.Complete();
|
||||
waitEvent.Begin();
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
using IWaitEvent delayLock = WaitEventFactory.Create(true);
|
||||
using ExclusiveTimer _ = new ExclusiveTimer(() => Callback(delayLock), 0, 15);
|
||||
while(!cancellationToken.IsCancellationRequested && DateTime.UtcNow < untilDate) {
|
||||
delayLock.Wait();
|
||||
}
|
||||
}*/
|
||||
|
||||
/*/// <summary>
|
||||
/// Waits the specified wait time.
|
||||
/// </summary>
|
||||
/// <param name="waitTime">The wait time.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
public static void Wait(TimeSpan waitTime, CancellationToken cancellationToken = default) =>
|
||||
WaitUntil(DateTime.UtcNow.Add(waitTime), cancellationToken);*/
|
||||
|
||||
/// <summary>
|
||||
/// Changes the start time and the interval between method invocations for the internal timer.
|
||||
/// </summary>
|
||||
@ -134,13 +75,6 @@ namespace Swan.Threading {
|
||||
_ = this._backingTimer.Change(dueTime, Timeout.Infinite);
|
||||
}
|
||||
|
||||
/*/// <summary>
|
||||
/// Changes the start time and the interval between method invocations for the internal timer.
|
||||
/// </summary>
|
||||
/// <param name="dueTime">The due time.</param>
|
||||
/// <param name="period">The period.</param>
|
||||
public void Change(TimeSpan dueTime, TimeSpan period) => this.Change(Convert.ToInt32(dueTime.TotalMilliseconds), Convert.ToInt32(period.TotalMilliseconds));*/
|
||||
|
||||
/// <summary>
|
||||
/// Changes the interval between method invocations for the internal timer.
|
||||
/// </summary>
|
||||
@ -148,12 +82,6 @@ namespace Swan.Threading {
|
||||
// [Obsolete("NEED", false)]
|
||||
public void Resume(Int32 period) => this.Change(0, period);
|
||||
|
||||
/*/// <summary>
|
||||
/// Changes the interval between method invocations for the internal timer.
|
||||
/// </summary>
|
||||
/// <param name="period">The period.</param>
|
||||
public void Resume(TimeSpan period) => this.Change(TimeSpan.Zero, period);*/
|
||||
|
||||
/// <summary>
|
||||
/// Pauses this instance.
|
||||
/// </summary>
|
||||
|
@ -67,14 +67,6 @@ namespace Swan.Threading {
|
||||
/// <returns>The Wait Event.</returns>
|
||||
public static IWaitEvent CreateSlim(Boolean isCompleted) => new WaitEventSlim(isCompleted);
|
||||
|
||||
/*/// <summary>
|
||||
/// Creates a Wait Event backed by a ManualResetEventSlim.
|
||||
/// </summary>
|
||||
/// <param name="isCompleted">if initially set to completed. Generally true.</param>
|
||||
/// <param name="useSlim">if set to <c>true</c> creates a slim version of the wait event.</param>
|
||||
/// <returns>The Wait Event.</returns>
|
||||
public static IWaitEvent Create(Boolean isCompleted, Boolean useSlim) => useSlim ? CreateSlim(isCompleted) : Create(isCompleted);*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region Backing Classes
|
||||
|
Loading…
Reference in New Issue
Block a user