Bleeding next

This commit is contained in:
BlubbFish 2019-12-10 20:20:45 +01:00
parent b2f110b8d6
commit dfe1d86af2
50 changed files with 22 additions and 5423 deletions

View File

@ -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.

View File

@ -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;
}
}
}

View File

@ -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());*/
}
}

View File

@ -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
}
}

View File

@ -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));*/
}
}

View File

@ -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,
}*/
}
}

View File

@ -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.

View File

@ -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();
}*/
}
}

View File

@ -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;*/
}
}

View File

@ -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}";
}*/
}
}

View File

@ -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);
}
}*/
}
}

View File

@ -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;
}*/
}
}

View File

@ -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;*/
}
}

View File

@ -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;*/
}
}

View File

@ -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;
}
*/
}
}

View File

@ -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.
///

View File

@ -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;
}

View File

@ -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&lt;BasicJson&gt;(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

View File

@ -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>

View File

@ -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;

View File

@ -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) {

View File

@ -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;
}*/
}
}

View File

@ -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();
}
}
}*/

View File

@ -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());

View File

@ -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);
}
}
}*/

View File

@ -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;
}
}
}
}
}*/

View File

@ -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
};
}
}
}
}*/

View File

@ -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;
}
}
}
}*/

View File

@ -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();
}
}
}*/

View File

@ -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}";
}
}
*/

View File

@ -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;
}
}
*/

View File

@ -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;
}
}
}
*/

View File

@ -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,
}
}
*/

View File

@ -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;
}
}

View File

@ -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

View File

@ -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) {

View File

@ -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>

View File

@ -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);*/
}
}

View File

@ -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);
}
}*/

View File

@ -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);
}
}*/

View File

@ -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>

View File

@ -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>

View File

@ -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;
}
}
}*/

View File

@ -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*/
}
}

View File

@ -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;
}*/
}
}

View File

@ -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: ";*/
}
}
}

View File

@ -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

View File

@ -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 &gt;.
/// </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 &lt;.
/// </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 &gt;=.
/// </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 &lt;=.
/// </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 -&lt;.
/// </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>

View File

@ -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>

View File

@ -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