diff --git a/01-Core/Jinget.Core/Attributes/AuthenticationRequired.cs b/01-Core/Jinget.Core/Attributes/AuthenticationRequired.cs index 7c5d2de..e9e4792 100644 --- a/01-Core/Jinget.Core/Attributes/AuthenticationRequired.cs +++ b/01-Core/Jinget.Core/Attributes/AuthenticationRequired.cs @@ -1,12 +1,10 @@ -using System; +namespace Jinget.Core.Attributes; -namespace Jinget.Core.Attributes +/// +/// This attribute are useful in scenarios like Service Hub, where prior to calling an API we need to authenticate it +/// +[AttributeUsage(AttributeTargets.Method)] +public class AuthenticationRequiredAttribute(bool required) : Attribute { - /// - /// This attribute are useful in scenarios like Service Hub, where prior to calling an API we need to authenticate it - /// - public class AuthenticationRequiredAttribute(bool required) : Attribute - { - public bool Required { get; set; } = required; - } + public bool Required { get; set; } = required; } diff --git a/01-Core/Jinget.Core/Attributes/ClaimAttribute.cs b/01-Core/Jinget.Core/Attributes/ClaimAttribute.cs index 8da2a3e..a63e38c 100644 --- a/01-Core/Jinget.Core/Attributes/ClaimAttribute.cs +++ b/01-Core/Jinget.Core/Attributes/ClaimAttribute.cs @@ -1,19 +1,13 @@ -using Microsoft.AspNetCore.Authorization; +namespace Jinget.Core.Attributes; -namespace Jinget.Core.Attributes +/// +/// Used for assigning claims for actions +/// + +public class ClaimAttribute : AuthorizeAttribute { /// - /// Used for assigning claims for actions + /// Gets or sets the claim title. /// -#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - - public class ClaimAttribute : AuthorizeAttribute - { - /// - /// Gets or sets the claim title. - /// - public string Title { get; set; } - } -#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - + public required string Title { get; set; } } \ No newline at end of file diff --git a/01-Core/Jinget.Core/Attributes/EntityAttribute.cs b/01-Core/Jinget.Core/Attributes/EntityAttribute.cs index c44837b..2fa9ee1 100644 --- a/01-Core/Jinget.Core/Attributes/EntityAttribute.cs +++ b/01-Core/Jinget.Core/Attributes/EntityAttribute.cs @@ -1,16 +1,14 @@ -using System; +namespace Jinget.Core.Attributes; -namespace Jinget.Core.Attributes +/// +/// Used for assigning custom configurations for entity properties +/// +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class)] +public class EntityAttribute : Attribute { - /// - /// Used for assigning custom configurations for entity properties + /// + /// Gets or sets a value indicating whether the entity is used as an elastic search index or not. /// - public class EntityAttribute : Attribute - { - /// - /// Gets or sets a value indicating whether the entity is used as an elastic search index or not. - /// - /// true if [elastic search enabled]; otherwise, false. - public bool ElasticSearchEnabled { get; set; } - } + /// true if [elastic search enabled]; otherwise, false. + public bool ElasticSearchEnabled { get; set; } } \ No newline at end of file diff --git a/01-Core/Jinget.Core/Attributes/SummaryAttribute.cs b/01-Core/Jinget.Core/Attributes/SummaryAttribute.cs index 6f10a72..54cd799 100644 --- a/01-Core/Jinget.Core/Attributes/SummaryAttribute.cs +++ b/01-Core/Jinget.Core/Attributes/SummaryAttribute.cs @@ -1,20 +1,18 @@ -using System; +namespace Jinget.Core.Attributes; -namespace Jinget.Core.Attributes +/// +/// Manage Method Summary Attribute +/// +/// +/// provide method summary for using in access management +/// +/// +[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)] +public class SummaryAttribute(string description) : Attribute { + /// - /// Manage Method Summary Attribute + /// Action's description. this value will be shown to the end user /// - /// - /// provide method summary for using in access management - /// - /// - public class SummaryAttribute(string description) : Attribute - { - - /// - /// Action's description. this value will be shown to the end user - /// - public string Description { get; set; } = description; - } + public string Description { get; set; } = description; } \ No newline at end of file diff --git a/01-Core/Jinget.Core/Attributes/SwaggerExcludeAttribute.cs b/01-Core/Jinget.Core/Attributes/SwaggerExcludeAttribute.cs index 48bea66..4c7181f 100644 --- a/01-Core/Jinget.Core/Attributes/SwaggerExcludeAttribute.cs +++ b/01-Core/Jinget.Core/Attributes/SwaggerExcludeAttribute.cs @@ -1,7 +1,4 @@ -using System; +namespace Jinget.Core.Attributes; -namespace Jinget.Core.Attributes -{ - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Class)] - public class SwaggerExcludeAttribute : Attribute { } -} \ No newline at end of file +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class)] +public class SwaggerExcludeAttribute : Attribute { } \ No newline at end of file diff --git a/01-Core/Jinget.Core/CodeDom/JingetDynamicCode.cs b/01-Core/Jinget.Core/CodeDom/JingetDynamicCode.cs index a57dfcb..3962384 100644 --- a/01-Core/Jinget.Core/CodeDom/JingetDynamicCode.cs +++ b/01-Core/Jinget.Core/CodeDom/JingetDynamicCode.cs @@ -1,213 +1,196 @@ -using System; -using System.CodeDom; -using System.CodeDom.Compiler; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Text; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.Text; -using Microsoft.CSharp; - -namespace Jinget.Core.CodeDom +namespace Jinget.Core.CodeDom; + +public sealed class JingetDynamicCode { - public sealed class JingetDynamicCode + private class Compiler { - private class Compiler + /// Compilation might be ended with some errors. The compile time errors are stored in this output parameter + /// During the dynamic code execution process, given sourceCode might change. Changed version of the sourceCode are stored in this output parameter + /// C# 9.0 enables you to write top level statements. + /// In order to compile the given sourceCode, some external references might needed to be added. Required references are being passed using this parameter + internal static byte[]? Compile(string sourceCode, MethodOptions? args, out List errors, out string jingetSource, + bool isTopLevelStatement = true, List? references = null) { - /// Compilation might be ended with some errors. The compile time errors are stored in this output parameter - /// During the dynamic code execution process, given sourceCode might change. Changed version of the sourceCode are stored in this output parameter - /// C# 9.0 enables you to write top level statements. - /// In order to compile the given sourceCode, some external references might needed to be added. Required references are being passed using this parameter - internal static byte[]? Compile(string sourceCode, MethodOptions? args, out List errors, out string jingetSource, - bool isTopLevelStatement = true, List? references = null) - { - references ??= []; - jingetSource = string.Empty; - errors = []; + references ??= []; + jingetSource = string.Empty; + errors = []; - sourceCode = sourceCode.Trim(); - sourceCode = sourceCode.StartsWith(Environment.NewLine) - ? sourceCode.TrimStart(Environment.NewLine.ToCharArray()) - : sourceCode; - sourceCode = sourceCode.Trim(); + sourceCode = sourceCode.Trim(); + sourceCode = sourceCode.StartsWith(Environment.NewLine) + ? sourceCode.TrimStart(Environment.NewLine.ToCharArray()) + : sourceCode; + sourceCode = sourceCode.Trim(); - if (isTopLevelStatement) - sourceCode = GenerateSourceCode(sourceCode, args); - jingetSource = sourceCode; + if (isTopLevelStatement) + sourceCode = GenerateSourceCode(sourceCode, args); + jingetSource = sourceCode; - using var peStream = new MemoryStream(); - var result = GenerateAssembly(sourceCode, references).Emit(peStream); + using var peStream = new MemoryStream(); + var result = GenerateAssembly(sourceCode, references).Emit(peStream); - if (!result.Success) - { - var failures = result.Diagnostics.Where(diagnostic => - diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error); + if (!result.Success) + { + var failures = result.Diagnostics.Where(diagnostic => + diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error); - errors.AddRange(failures.Select(diagnostic => $"{diagnostic.Id} {diagnostic.GetMessage()}")); + errors.AddRange(failures.Select(diagnostic => $"{diagnostic.Id} {diagnostic.GetMessage()}")); - return null; - } + return null; + } - peStream.Seek(0, SeekOrigin.Begin); + peStream.Seek(0, SeekOrigin.Begin); - return peStream.ToArray(); - } + return peStream.ToArray(); + } - /// - /// Generaetes new dynamic dll, based on the given source code. this dll created on the fly - /// - static CSharpCompilation GenerateAssembly(string sourceCode, List externalReferences) - { - var codeString = SourceText.From(sourceCode); - var options = CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.Latest); + /// + /// Generaetes new dynamic dll, based on the given source code. this dll created on the fly + /// + static CSharpCompilation GenerateAssembly(string sourceCode, List externalReferences) + { + var codeString = SourceText.From(sourceCode); + var options = CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.Latest); - var parsedSyntaxTree = SyntaxFactory.ParseSyntaxTree(codeString, options); + var parsedSyntaxTree = SyntaxFactory.ParseSyntaxTree(codeString, options); - externalReferences ??= []; + externalReferences ??= []; - var defaultReferences = new[] { "System.Private.CoreLib", "netstandard", "System.Runtime" }; + var defaultReferences = new[] { "System.Private.CoreLib", "netstandard", "System.Runtime" }; - externalReferences.AddRange(defaultReferences.Select(x => Assembly.Load(x).Location)); + externalReferences.AddRange(defaultReferences.Select(x => Assembly.Load(x).Location)); - var references = new List(); - references.AddRange(externalReferences.Distinct().Select(x => MetadataReference.CreateFromFile(x))); + var references = new List(); + references.AddRange(externalReferences.Distinct().Select(x => MetadataReference.CreateFromFile(x))); - return CSharpCompilation.Create($"{Guid.NewGuid()}.dll", - [parsedSyntaxTree], - references: references, - options: new CSharpCompilationOptions( - OutputKind.DynamicallyLinkedLibrary, - optimizationLevel: OptimizationLevel.Release, - assemblyIdentityComparer: DesktopAssemblyIdentityComparer.Default)); - } + return CSharpCompilation.Create($"{Guid.NewGuid()}.dll", + [parsedSyntaxTree], + references: references, + options: new CSharpCompilationOptions( + OutputKind.DynamicallyLinkedLibrary, + optimizationLevel: OptimizationLevel.Release, + assemblyIdentityComparer: DesktopAssemblyIdentityComparer.Default)); + } - /// - /// Generate source code using given expression. This method tries to put the given expression inside a method in a class - /// so that it could be invoked - /// - static string GenerateSourceCode(string expression, MethodOptions? methodOptions) - { - CodeNamespace globalCodeNamespace = new(); - //add default using: using System; - globalCodeNamespace.Imports.Add(new CodeNamespaceImport("System")); + /// + /// Generate source code using given expression. This method tries to put the given expression inside a method in a class + /// so that it could be invoked + /// + static string GenerateSourceCode(string expression, MethodOptions? methodOptions) + { + CodeNamespace globalCodeNamespace = new(); + //add default using: using System; + globalCodeNamespace.Imports.Add(new CodeNamespaceImport(nameof(System))); - if (expression.StartsWith("using ")) + if (expression.StartsWith("using ")) + { + string[] statements = expression.Split(";", StringSplitOptions.RemoveEmptyEntries); + foreach (var @using in statements.Where(x => x.StartsWith("using "))) { - string[] statements = expression.Split(";", StringSplitOptions.RemoveEmptyEntries); - foreach (var @using in statements.Where(x => x.StartsWith("using "))) + string[] usingSections = @using.Split(" ", StringSplitOptions.RemoveEmptyEntries); + //if len>2 then using statement does not terminated with semicolon + if (@usingSections.Length <= 2) { - string[] usingSections = @using.Split(" ", StringSplitOptions.RemoveEmptyEntries); - //if len>2 then using statement does not terminated with semicolon - if (@usingSections.Length <= 2) - { - globalCodeNamespace.Imports.Add(new CodeNamespaceImport(usingSections[1])); - expression = expression.Replace(@using, ""); - } + globalCodeNamespace.Imports.Add(new CodeNamespaceImport(usingSections[1])); + expression = expression.Replace(@using, ""); } } + } - CodeNamespace myNamespace = new("JingetDynamic"); - CodeTypeDeclaration classDeclaration = new() - { - IsClass = true, - Name = "DynamicInvoker", - TypeAttributes = TypeAttributes.NotPublic | TypeAttributes.Sealed + CodeNamespace myNamespace = new("JingetDynamic"); + CodeTypeDeclaration classDeclaration = new() + { + IsClass = true, + Name = "DynamicInvoker", + TypeAttributes = TypeAttributes.NotPublic | TypeAttributes.Sealed - }; + }; - CodeMemberMethod myMethod = new() - { - Name = "DynamicInvoke", - Attributes = MemberAttributes.Public | MemberAttributes.Final, - ReturnType = methodOptions?.ReturnType is null ? new CodeTypeReference(typeof(void)) : new CodeTypeReference(methodOptions.ReturnType) - }; - if (methodOptions?.Parameters != null) - { - myMethod.Parameters.AddRange(new CodeParameterDeclarationExpressionCollection(methodOptions - .Parameters.Select(x => new CodeParameterDeclarationExpression(x.Type, x.Name)).ToArray())); - } + CodeMemberMethod myMethod = new() + { + Name = "DynamicInvoke", + Attributes = MemberAttributes.Public | MemberAttributes.Final, + ReturnType = methodOptions?.ReturnType is null ? new CodeTypeReference(typeof(void)) : new CodeTypeReference(methodOptions.ReturnType) + }; + if (methodOptions?.Parameters != null) + { + myMethod.Parameters.AddRange(new CodeParameterDeclarationExpressionCollection(methodOptions + .Parameters.Select(x => new CodeParameterDeclarationExpression(x.Type, x.Name)).ToArray())); + } - expression = expression.Trim(';').Trim(); + expression = expression.Trim(';').Trim(); - myMethod.Statements.Add(new CodeSnippetExpression(expression)); - classDeclaration.Members.Add(myMethod); + myMethod.Statements.Add(new CodeSnippetExpression(expression)); + classDeclaration.Members.Add(myMethod); - myNamespace.Types.Add(classDeclaration); + myNamespace.Types.Add(classDeclaration); - CodeCompileUnit codeCompileUnit = new(); - codeCompileUnit.Namespaces.Add(globalCodeNamespace); - codeCompileUnit.Namespaces.Add(myNamespace); + CodeCompileUnit codeCompileUnit = new(); + codeCompileUnit.Namespaces.Add(globalCodeNamespace); + codeCompileUnit.Namespaces.Add(myNamespace); - var source = new StringBuilder(); - using (var sw = new StringWriter(source)) - { - ICodeGenerator generator = new CSharpCodeProvider().CreateGenerator(sw); - CodeGeneratorOptions codeOpts = new(); - generator.GenerateCodeFromCompileUnit(codeCompileUnit, sw, codeOpts); - sw.Flush(); - sw.Close(); - } + var source = new StringBuilder(); + using (var sw = new StringWriter(source)) + { + ICodeGenerator generator = new CSharpCodeProvider().CreateGenerator(sw); + CodeGeneratorOptions codeOpts = new(); + generator.GenerateCodeFromCompileUnit(codeCompileUnit, sw, codeOpts); + sw.Flush(); + sw.Close(); + } - //remove auto generated comments - var marker = "//------------------------------------------------------------------------------"; - var allTheCode = source.ToString(); - var justTheRealCode = allTheCode.Substring(allTheCode.IndexOf(marker) + marker.Length, allTheCode.LastIndexOf(marker) + marker.Length); + //remove auto generated comments + var marker = "//------------------------------------------------------------------------------"; + var allTheCode = source.ToString(); + var justTheRealCode = allTheCode.Substring(allTheCode.IndexOf(marker) + marker.Length, allTheCode.LastIndexOf(marker) + marker.Length); - string removedComments = allTheCode[justTheRealCode.Length..].Trim(); + string removedComments = allTheCode[justTheRealCode.Length..].Trim(); - var removedNewLine = removedComments.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries).Where(x => !string.IsNullOrWhiteSpace(x)); - source = new StringBuilder(string.Join(Environment.NewLine, removedNewLine)); - return source.ToString(); - } + var removedNewLine = removedComments.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries).Where(x => !string.IsNullOrWhiteSpace(x)); + source = new StringBuilder(string.Join(Environment.NewLine, removedNewLine)); + return source.ToString(); } + } - [MethodImpl(MethodImplOptions.NoInlining)] - public static object? Execute(string sourceCode, out List errors, out string compiledSourceCode, MethodOptions? options = null, bool isTopLevelStatement = true, bool compileOnly = false, List? references = null) + [MethodImpl(MethodImplOptions.NoInlining)] + public static object? Execute(string sourceCode, out List errors, out string compiledSourceCode, MethodOptions? options = null, bool isTopLevelStatement = true, bool compileOnly = false, List? references = null) + { + if (sourceCode.Length > 10000) { - if (sourceCode.Length > 10000) - { - throw new ArgumentException("Jinget says: sourceCode is too long. sourceCode max length is 10000 characters"); - } + throw new ArgumentException("Jinget says: sourceCode is too long. sourceCode max length is 10000 characters"); + } - var compiledCode = Compiler.Compile(sourceCode, options, out errors, out compiledSourceCode, - isTopLevelStatement, references); - if (compiledCode is null || compileOnly) - { - return null; - } + var compiledCode = Compiler.Compile(sourceCode, options, out errors, out compiledSourceCode, + isTopLevelStatement, references); + if (compiledCode is null || compileOnly) + { + return null; + } - var @class = Assembly.Load(compiledCode).GetTypes().FirstOrDefault(x => x.Name == "DynamicInvoker"); - var method = @class?.GetMethod("DynamicInvoke"); + var @class = Assembly.Load(compiledCode).GetTypes().FirstOrDefault(x => x.Name == "DynamicInvoker"); + var method = @class?.GetMethod("DynamicInvoke"); - var instance = Activator.CreateInstance(@class ?? throw new InvalidOperationException("Jinget Says: Invalid Operation")); + var instance = Activator.CreateInstance(@class ?? throw new InvalidOperationException("Jinget Says: Invalid Operation")); - return method?.Invoke(instance, options?.Parameters.Select(x => x.Value).ToArray()); - } -#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - public class MethodOptions + return method?.Invoke(instance, options?.Parameters.Select(x => x.Value).ToArray()); + } + public class MethodOptions + { + /// + /// What should be return type of the dynamically injected Invoke method? + /// If not set, void will be used + /// + public Type ReturnType { get; set; } + + /// + /// What are the input parameters for dynamically injected Invoke method? + /// + public List Parameters { get; set; } = []; + + public class ParameterOptions { - /// - /// What should be return type of the dynamically injected Invoke method? - /// If not set, void will be used - /// - public Type ReturnType { get; set; } - - /// - /// What are the input parameters for dynamically injected Invoke method? - /// - public List Parameters { get; set; } = []; - - public class ParameterOptions - { - public Type Type { get; set; } - public string Name { get; set; } - public object Value { get; set; } - } + public Type Type { get; set; } + public string Name { get; set; } + public object Value { get; set; } } -#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. } } \ No newline at end of file diff --git a/01-Core/Jinget.Core/Compiler/CompilerFeatureRequiredAttribute.cs b/01-Core/Jinget.Core/Compiler/CompilerFeatureRequiredAttribute.cs index a1b6718..20cf141 100644 --- a/01-Core/Jinget.Core/Compiler/CompilerFeatureRequiredAttribute.cs +++ b/01-Core/Jinget.Core/Compiler/CompilerFeatureRequiredAttribute.cs @@ -3,8 +3,6 @@ /// /// add support for 'required' keyword using latest lang version and .net standard 2.1 /// -#pragma warning disable CA1018 // Mark attributes with AttributeUsageAttribute public class CompilerFeatureRequiredAttribute(string name) : Attribute -#pragma warning restore CA1018 // Mark attributes with AttributeUsageAttribute { } \ No newline at end of file diff --git a/01-Core/Jinget.Core/Contracts/IOrderBy.cs b/01-Core/Jinget.Core/Contracts/IOrderBy.cs index a1737f8..11bee2d 100644 --- a/01-Core/Jinget.Core/Contracts/IOrderBy.cs +++ b/01-Core/Jinget.Core/Contracts/IOrderBy.cs @@ -1,25 +1,21 @@ -using System.Collections.Generic; -using Jinget.Core.ExpressionToSql.Internal; +namespace Jinget.Core.Contracts; -namespace Jinget.Core.Contracts +/// +/// Used for supporting sorting mechanism in elastic search query handling +/// +/// +public interface IOrderBy { /// - /// Used for supporting sorting mechanism in elastic search query handling + /// Gets or sets the order by clause. /// - /// - public interface IOrderBy - { - /// - /// Gets or sets the order by clause. - /// - /// The order by. - T OrderBy { get; set; } - } + /// The order by. + T OrderBy { get; set; } +} - /// - /// Used for supporting sorting mechanism in dapper query handling - /// - public interface IOrderBy : IOrderBy> - { - } +/// +/// Used for supporting sorting mechanism in dapper query handling +/// +public interface IOrderBy : IOrderBy> +{ } diff --git a/01-Core/Jinget.Core/Contracts/IPaginated.cs b/01-Core/Jinget.Core/Contracts/IPaginated.cs index 0219fbc..f0e79fd 100644 --- a/01-Core/Jinget.Core/Contracts/IPaginated.cs +++ b/01-Core/Jinget.Core/Contracts/IPaginated.cs @@ -1,16 +1,13 @@ -using Jinget.Core.ExpressionToSql.Internal; +namespace Jinget.Core.Contracts; -namespace Jinget.Core.Contracts +/// +/// Used for supporting paging mechanism in query handling +/// +public interface IPaginated { /// - /// Used for supporting paging mechanism in query handling + /// Gets or sets the paging configuration. /// - public interface IPaginated - { - /// - /// Gets or sets the paging configuration. - /// - /// The paging configuration. - Paging PagingConfig { get; set; } - } + /// The paging configuration. + Paging PagingConfig { get; set; } } diff --git a/01-Core/Jinget.Core/Contracts/IRowRestriction.cs b/01-Core/Jinget.Core/Contracts/IRowRestriction.cs index 94bb171..06c8dee 100644 --- a/01-Core/Jinget.Core/Contracts/IRowRestriction.cs +++ b/01-Core/Jinget.Core/Contracts/IRowRestriction.cs @@ -1,20 +1,16 @@ -using System; -using System.Linq.Expressions; +namespace Jinget.Core.Contracts; -namespace Jinget.Core.Contracts +/// +/// Used for supporting row restriction mechanism in query handling. +/// RowRestrictions are filters which should be automatically applied to the queries regardless of their FILTER properties. +/// The final WHERE clause is made up: (RowRestrictions) AND (Filter) +/// +/// The type of the t model type. +public interface IRowRestriction { /// - /// Used for supporting row restriction mechanism in query handling. - /// RowRestrictions are filters which should be automatically applied to the queries regardless of their FILTER properties. - /// The final WHERE clause is made up: (RowRestrictions) AND (Filter) + /// Gets or sets the row restrictions. /// - /// The type of the t model type. - public interface IRowRestriction - { - /// - /// Gets or sets the row restrictions. - /// - /// The row restrictions. - Expression> RowRestrictions { get; set; } - } + /// The row restrictions. + Expression> RowRestrictions { get; set; } } diff --git a/01-Core/Jinget.Core/Contracts/IUserContext.cs b/01-Core/Jinget.Core/Contracts/IUserContext.cs index 21fff1c..494e10c 100644 --- a/01-Core/Jinget.Core/Contracts/IUserContext.cs +++ b/01-Core/Jinget.Core/Contracts/IUserContext.cs @@ -1,30 +1,26 @@ -using System.Security.Principal; -using System.Threading.Tasks; +namespace Jinget.Core.Contracts; -namespace Jinget.Core.Contracts +/// +/// Provide functionality for user context validation and management +/// Implements the +/// +/// +public interface IUserContext : IPrincipal { /// - /// Provide functionality for user context validation and management - /// Implements the + /// check the access using claim attribute /// - /// - public interface IUserContext : IPrincipal - { - /// - /// check the access using claim attribute - /// - /// The user identifier. - /// Name of the sub system. - /// Name of the API. - /// The action title. - /// The claim. - Task HasAccessAsync(string userIdentifier, string subSystemName, string apiName, string actionTitle, string claim); + /// The user identifier. + /// Name of the sub system. + /// Name of the API. + /// The action title. + /// The claim. + Task HasAccessAsync(string userIdentifier, string subSystemName, string apiName, string actionTitle, string claim); - /// - /// Determines whether the token is valid for the given user or not. - /// - /// The user identifier. - /// The token. - Task IsTokenValidAsync(string userIdentifier, string token); - } + /// + /// Determines whether the token is valid for the given user or not. + /// + /// The user identifier. + /// The token. + Task IsTokenValidAsync(string userIdentifier, string token); } diff --git a/01-Core/Jinget.Core/Enumerations/ConditionJoinType.cs b/01-Core/Jinget.Core/Enumerations/ConditionJoinType.cs index 6f367db..5e48c1f 100644 --- a/01-Core/Jinget.Core/Enumerations/ConditionJoinType.cs +++ b/01-Core/Jinget.Core/Enumerations/ConditionJoinType.cs @@ -1,12 +1,11 @@ -namespace Jinget.Core.Enumerations +namespace Jinget.Core.Enumerations; + +/// +/// Define Condition Join Type types which can be used in usecases such as joining filter criterias +/// +public enum ConditionCombiningType { - /// - /// Define Condition Join Type types which can be used in usecases such as joining filter criterias - /// - public enum ConditionCombiningType - { - Unknown = 0, - AndAlso, - OrElse - } + Unknown = 0, + AndAlso, + OrElse } diff --git a/01-Core/Jinget.Core/Enumerations/ExceptionType.cs b/01-Core/Jinget.Core/Enumerations/ExceptionType.cs index 0dc270b..3174795 100644 --- a/01-Core/Jinget.Core/Enumerations/ExceptionType.cs +++ b/01-Core/Jinget.Core/Enumerations/ExceptionType.cs @@ -1,23 +1,22 @@ -namespace Jinget.Core.Enumerations +namespace Jinget.Core.Enumerations; + +/// +/// Define different exception types +/// +public enum ExceptionType { /// - /// Define different exception types + /// Exceptions raised from the jinget internal + /// + JingetInternal, + + /// + /// Exceptions raised from the .Net framework internal /// - public enum ExceptionType - { - /// - /// Exceptions raised from the jinget internal - /// - JingetInternal, - - /// - /// Exceptions raised from the .Net framework internal - /// - DotNetInternal, + DotNetInternal, - /// - /// Custom exceptoins defined by user itself in his/her code. - /// - Custom - } + /// + /// Custom exceptoins defined by user itself in his/her code. + /// + Custom } diff --git a/01-Core/Jinget.Core/Enumerations/Operator.cs b/01-Core/Jinget.Core/Enumerations/Operator.cs index 564773d..7ae89e3 100644 --- a/01-Core/Jinget.Core/Enumerations/Operator.cs +++ b/01-Core/Jinget.Core/Enumerations/Operator.cs @@ -1,16 +1,15 @@ -namespace Jinget.Core.Enumerations +namespace Jinget.Core.Enumerations; + +/// +/// Define Operator types which can be used in usecases such as filter criteria +/// +public enum Operator { - /// - /// Define Operator types which can be used in usecases such as filter criteria - /// - public enum Operator - { - Equal, - Contains, - GreaterThan, - LowerThan, - GreaterThanOrEqual, - LowerThanOrEqual, - NotEqual - } + Equal, + Contains, + GreaterThan, + LowerThan, + GreaterThanOrEqual, + LowerThanOrEqual, + NotEqual } diff --git a/01-Core/Jinget.Core/Enumerations/OrderByDirection.cs b/01-Core/Jinget.Core/Enumerations/OrderByDirection.cs index bddbc1b..5aea86f 100644 --- a/01-Core/Jinget.Core/Enumerations/OrderByDirection.cs +++ b/01-Core/Jinget.Core/Enumerations/OrderByDirection.cs @@ -1,18 +1,17 @@ using System.ComponentModel; -namespace Jinget.Core.Enumerations +namespace Jinget.Core.Enumerations; + +/// +/// Define order by directions used in query handling +/// +public enum OrderByDirection { - /// - /// Define order by directions used in query handling - /// - public enum OrderByDirection - { - /// - [Description("ASC")] - Ascending, + /// + [Description("ASC")] + Ascending, - /// - [Description("DESC")] - Descending - } + /// + [Description("DESC")] + Descending } diff --git a/01-Core/Jinget.Core/Exceptions/JingetException.cs b/01-Core/Jinget.Core/Exceptions/JingetException.cs index 2bbe282..3b70386 100644 --- a/01-Core/Jinget.Core/Exceptions/JingetException.cs +++ b/01-Core/Jinget.Core/Exceptions/JingetException.cs @@ -1,27 +1,23 @@ -using System; -using Jinget.Core.Enumerations; +namespace Jinget.Core.Exceptions; -namespace Jinget.Core.Exceptions +/// +/// Provide a mechanism for defining custom jinget exceptions +/// Implements the +/// +/// +/// Exception message to be thrown +/// The inner exception to be thrown +/// Custom code of exception +/// Type of exception +public class JingetException(string message, Exception ex, int code = -1, ExceptionType type = ExceptionType.JingetInternal) : Exception(message, ex) { - /// - /// Provide a mechanism for defining custom jinget exceptions - /// Implements the - /// - /// + public int Code { get; set; } = code; + + public ExceptionType Type { get; set; } = type; + /// Exception message to be thrown - /// The inner exception to be thrown /// Custom code of exception /// Type of exception - public class JingetException(string message, Exception ex, int code = -1, ExceptionType type = ExceptionType.JingetInternal) : Exception(message, ex) - { - public int Code { get; set; } = code; - - public ExceptionType Type { get; set; } = type; - - /// Exception message to be thrown - /// Custom code of exception - /// Type of exception - public JingetException(string message, int code = -1, ExceptionType type = ExceptionType.JingetInternal) - : this(message, null, code, type) { } - } + public JingetException(string message, int code = -1, ExceptionType type = ExceptionType.JingetInternal) + : this(message, new Exception(), code, type) { } } diff --git a/01-Core/Jinget.Core/ExpressionToSql/Internal/OrderBy.cs b/01-Core/Jinget.Core/ExpressionToSql/Internal/OrderBy.cs index e77fbd8..7f6ea96 100644 --- a/01-Core/Jinget.Core/ExpressionToSql/Internal/OrderBy.cs +++ b/01-Core/Jinget.Core/ExpressionToSql/Internal/OrderBy.cs @@ -6,52 +6,51 @@ using Jinget.Core.ExtensionMethods.Expressions; using Jinget.Core.Utilities.Expressions; -namespace Jinget.Core.ExpressionToSql.Internal +namespace Jinget.Core.ExpressionToSql.Internal; + +/// +/// Provides the order by functionality used in query handling +/// +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + +public class OrderBy { + public OrderBy() + { + + } + public OrderBy(string name) => Name = ExpressionUtility.ToExpression(name, "x"); + /// - /// Provides the order by functionality used in query handling + /// The order by expression /// -#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public Expression> Name { get; set; } + + /// + /// Gets or sets the direction of sorting. + /// + /// + public OrderByDirection Direction { get; set; } - public class OrderBy + /// + /// Returns a that represents the order by clause in T-SQL. + /// + public override string ToString() { - public OrderBy() - { - - } - public OrderBy(string name) => Name = ExpressionUtility.ToExpression(name, "x"); - - /// - /// The order by expression - /// - public Expression> Name { get; set; } - - /// - /// Gets or sets the direction of sorting. - /// - /// - public OrderByDirection Direction { get; set; } - - /// - /// Returns a that represents the order by clause in T-SQL. - /// - public override string ToString() - { - StringBuilder orderByClause = new(); - orderByClause.Append('['); - - if (Name.Body is MemberExpression expression && expression.Expression.NodeType != ExpressionType.Convert) - orderByClause.Append(Expression.Lambda(expression).Compile().DynamicInvoke()); - else - orderByClause.Append(Name.Stringfy()); - - orderByClause.Append(']'); - orderByClause.Append(' '); - orderByClause.Append(Direction.GetDescription()); - - return orderByClause.ToString(); - } + StringBuilder orderByClause = new(); + orderByClause.Append('['); + + if (Name.Body is MemberExpression expression && expression.Expression.NodeType != ExpressionType.Convert) + orderByClause.Append(Expression.Lambda(expression).Compile().DynamicInvoke()); + else + orderByClause.Append(Name.Stringfy()); + + orderByClause.Append(']'); + orderByClause.Append(' '); + orderByClause.Append(Direction.GetDescription()); + + return orderByClause.ToString(); } +} #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. -} diff --git a/01-Core/Jinget.Core/ExpressionToSql/Internal/Paging.cs b/01-Core/Jinget.Core/ExpressionToSql/Internal/Paging.cs index 22ca476..f30f417 100644 --- a/01-Core/Jinget.Core/ExpressionToSql/Internal/Paging.cs +++ b/01-Core/Jinget.Core/ExpressionToSql/Internal/Paging.cs @@ -1,34 +1,33 @@ -namespace Jinget.Core.ExpressionToSql.Internal +namespace Jinget.Core.ExpressionToSql.Internal; + +/// +/// Provides the paging functionality used in query handling +/// +public class Paging { /// - /// Provides the paging functionality used in query handling + /// Gets or sets the size of the page. /// - public class Paging - { - /// - /// Gets or sets the size of the page. - /// - public int PageSize { get; set; } + public int PageSize { get; set; } - /// - /// Gets or sets the page number. - /// - public int PageNumber { get; set; } + /// + /// Gets or sets the page number. + /// + public int PageNumber { get; set; } - /// - /// Returns a that represents the OFFSET-FETCH T-SQL code. - /// - public override string ToString() - { - if (PageNumber == 0 && PageSize == 0) - return string.Empty; + /// + /// Returns a that represents the OFFSET-FETCH T-SQL code. + /// + public override string ToString() + { + if (PageNumber == 0 && PageSize == 0) + return string.Empty; - if (PageNumber <= 0) - PageNumber = 1; - if (PageSize <= 0) - PageSize = 10; + if (PageNumber <= 0) + PageNumber = 1; + if (PageSize <= 0) + PageSize = 10; - return $"OFFSET {(PageNumber - 1) * PageSize} ROWS FETCH NEXT {PageSize} ROWS ONLY"; - } + return $"OFFSET {(PageNumber - 1) * PageSize} ROWS FETCH NEXT {PageSize} ROWS ONLY"; } } diff --git a/01-Core/Jinget.Core/ExpressionToSql/Internal/Query.cs b/01-Core/Jinget.Core/ExpressionToSql/Internal/Query.cs index 325777b..4ef9048 100644 --- a/01-Core/Jinget.Core/ExpressionToSql/Internal/Query.cs +++ b/01-Core/Jinget.Core/ExpressionToSql/Internal/Query.cs @@ -1,18 +1,17 @@ using System.Collections.Generic; using System.Text; -namespace Jinget.Core.ExpressionToSql.Internal -{ - public abstract class Query - { - public (QueryBuilder query, Dictionary? parameters) ToSql() => ToSql(new StringBuilder()); +namespace Jinget.Core.ExpressionToSql.Internal; - private (QueryBuilder query, Dictionary? parameters) ToSql(StringBuilder sb) - { - var (query, parameters) = ToSql(new QueryBuilder(sb)); - return (query, parameters); - } +public abstract class Query +{ + public (QueryBuilder query, Dictionary? parameters) ToSql() => ToSql(new StringBuilder()); - internal abstract (QueryBuilder query, Dictionary? parameters) ToSql(QueryBuilder query); + private (QueryBuilder query, Dictionary? parameters) ToSql(StringBuilder sb) + { + var (query, parameters) = ToSql(new QueryBuilder(sb)); + return (query, parameters); } + + internal abstract (QueryBuilder query, Dictionary? parameters) ToSql(QueryBuilder query); } \ No newline at end of file diff --git a/01-Core/Jinget.Core/ExpressionToSql/Internal/QueryBuilder.cs b/01-Core/Jinget.Core/ExpressionToSql/Internal/QueryBuilder.cs index bfc16ed..f2d3c1d 100644 --- a/01-Core/Jinget.Core/ExpressionToSql/Internal/QueryBuilder.cs +++ b/01-Core/Jinget.Core/ExpressionToSql/Internal/QueryBuilder.cs @@ -1,136 +1,135 @@ using System; using System.Text; -namespace Jinget.Core.ExpressionToSql.Internal +namespace Jinget.Core.ExpressionToSql.Internal; + +public class QueryBuilder { - public class QueryBuilder - { - private readonly StringBuilder _sb; - public const string AliasName = "a"; + private readonly StringBuilder _sb; + public const string AliasName = "a"; - public QueryBuilder(StringBuilder sb) + public QueryBuilder(StringBuilder sb) + { + if (sb.Length == 0) { - if (sb.Length == 0) - { - sb.Append("SELECT"); - } - _sb = sb; + sb.Append("SELECT"); } + _sb = sb; + } - public override string ToString() => _sb.ToString(); + public override string ToString() => _sb.ToString(); - /// - /// create TOP clause - /// - public QueryBuilder Take(int count) - { - if (count >= 0) - _sb.Append(" TOP ").Append(count); + /// + /// create TOP clause + /// + public QueryBuilder Take(int count) + { + if (count >= 0) + _sb.Append(" TOP ").Append(count); + return this; + } + + public QueryBuilder AddParameter(string parameterName) + { + if (!string.IsNullOrWhiteSpace(parameterName)) + _sb.Append(" @").Append(parameterName); + return this; + } + + /// + /// Adds aliasname and column names + /// + public QueryBuilder AddAttribute(string attributeName, string aliasName = AliasName) + { + if (string.IsNullOrWhiteSpace(attributeName)) return this; - } - public QueryBuilder AddParameter(string parameterName) + _sb.Append(' '); + + if (!string.IsNullOrWhiteSpace(aliasName)) { - if (!string.IsNullOrWhiteSpace(parameterName)) - _sb.Append(" @").Append(parameterName); - return this; + _sb.Append(aliasName).Append('.'); } - /// - /// Adds aliasname and column names - /// - public QueryBuilder AddAttribute(string attributeName, string aliasName = AliasName) - { - if (string.IsNullOrWhiteSpace(attributeName)) - return this; + AppendEscapedValue(attributeName); + return this; + } - _sb.Append(' '); + public QueryBuilder AddValue(object? value) + { + _sb.Append(' ').Append(value); + return this; + } + + /// + /// Adds comma separator. + /// + public QueryBuilder AddSeparator() + { + _sb.Append(','); + return this; + } - if (!string.IsNullOrWhiteSpace(aliasName)) - { - _sb.Append(aliasName).Append('.'); - } + public QueryBuilder Remove(int count = 1) + { + if (count > 0) + _sb.Length -= count; + return this; + } - AppendEscapedValue(attributeName); + /// + /// Create FROM Table clause + /// + public QueryBuilder AddTable(Table table, string aliasName = AliasName) + { + if (table == null) return this; - } - public QueryBuilder AddValue(object? value) - { - _sb.Append(' ').Append(value); - return this; - } + _sb.Append(" FROM "); - /// - /// Adds comma separator. - /// - public QueryBuilder AddSeparator() + if (!string.IsNullOrWhiteSpace(table.Schema)) { - _sb.Append(','); - return this; + AppendEscapedValue(table.Schema); + _sb.Append('.'); } - public QueryBuilder Remove(int count = 1) - { - if (count > 0) - _sb.Length -= count; - return this; - } + AppendEscapedValue(table.Name); - /// - /// Create FROM Table clause - /// - public QueryBuilder AddTable(Table table, string aliasName = AliasName) + if (!string.IsNullOrWhiteSpace(aliasName)) { - if (table == null) - return this; - - _sb.Append(" FROM "); - - if (!string.IsNullOrWhiteSpace(table.Schema)) - { - AppendEscapedValue(table.Schema); - _sb.Append('.'); - } + _sb.Append(" AS ").Append(aliasName); + } + return this; + } - AppendEscapedValue(table.Name); + internal void AppendCondition(string condition) + { + if (!string.IsNullOrWhiteSpace(condition)) + _sb.Append(" WHERE ").Append(condition); + } - if (!string.IsNullOrWhiteSpace(aliasName)) - { - _sb.Append(" AS ").Append(aliasName); - } - return this; - } + /// + /// Add [ and ] to column, table and function names + /// + private void AppendEscapedValue(string attributeName) + { + if (string.IsNullOrWhiteSpace(attributeName)) + return; - internal void AppendCondition(string condition) + if (attributeName.StartsWith("[") && attributeName.EndsWith("]")) { - if (!string.IsNullOrWhiteSpace(condition)) - _sb.Append(" WHERE ").Append(condition); + _sb.Append(attributeName); + return; } - /// - /// Add [ and ] to column, table and function names - /// - private void AppendEscapedValue(string attributeName) + // Table value function. [ and ] should added to function name only, not to its parameters + if (attributeName.Contains('(') && attributeName.Contains(')')) { - if (string.IsNullOrWhiteSpace(attributeName)) - return; - - if (attributeName.StartsWith("[") && attributeName.EndsWith("]")) - { - _sb.Append(attributeName); - return; - } - - // Table value function. [ and ] should added to function name only, not to its parameters - if (attributeName.Contains('(') && attributeName.Contains(')')) - { - string functionName = attributeName[..attributeName.IndexOf("(", StringComparison.Ordinal)]; - string functionParameters = attributeName[attributeName.IndexOf("(", StringComparison.Ordinal)..]; - _sb.Append('[').Append(functionName).Append(']').Append(functionParameters); - } - else - _sb.Append('[').Append(attributeName).Append(']'); + string functionName = attributeName[..attributeName.IndexOf("(", StringComparison.Ordinal)]; + string functionParameters = attributeName[attributeName.IndexOf("(", StringComparison.Ordinal)..]; + _sb.Append('[').Append(functionName).Append(']').Append(functionParameters); } + else + _sb.Append('[').Append(attributeName).Append(']'); } } \ No newline at end of file diff --git a/01-Core/Jinget.Core/ExpressionToSql/Internal/Select.cs b/01-Core/Jinget.Core/ExpressionToSql/Internal/Select.cs index a82ebb8..6675f84 100644 --- a/01-Core/Jinget.Core/ExpressionToSql/Internal/Select.cs +++ b/01-Core/Jinget.Core/ExpressionToSql/Internal/Select.cs @@ -4,93 +4,92 @@ using System.Linq; using System.Linq.Expressions; -namespace Jinget.Core.ExpressionToSql.Internal +namespace Jinget.Core.ExpressionToSql.Internal; + +public class Select : Query { - public class Select : Query - { - private readonly Expression> _select; - private readonly int? _take; - private readonly Table _table; + private readonly Expression> _select; + private readonly int? _take; + private readonly Table _table; + + public Where Where(Expression> predicate) => new(this, predicate); - public Where Where(Expression> predicate) => new(this, predicate); + internal Select(Expression> select, int? take, Table table) + { + _select = select; + _take = take; + _table = table; + } - internal Select(Expression> select, int? take, Table table) + internal override (QueryBuilder query, Dictionary? parameters) ToSql(QueryBuilder query) + { + if (_take.HasValue) { - _select = select; - _take = take; - _table = table; + query.Take(_take.Value); } - internal override (QueryBuilder query, Dictionary? parameters) ToSql(QueryBuilder query) - { - if (_take.HasValue) - { - query.Take(_take.Value); - } + var type = _select.Parameters[0].Type; - var type = _select.Parameters[0].Type; + var expressions = GetExpressions(type, _select.Body); - var expressions = GetExpressions(type, _select.Body); + AddExpressions(expressions, type, query); - AddExpressions(expressions, type, query); + query.AddTable(_table); - query.AddTable(_table); + return (query, null); + } - return (query, null); + private static IEnumerable GetExpressions(Type type, Expression body) + { + switch (body.NodeType) + { + case ExpressionType.New: + var n = (NewExpression)body; + return n.Arguments; + case ExpressionType.Parameter: + var propertyInfos = type.GetWritableProperties(); + return propertyInfos.Values.Select(pi => Expression.Property(body, pi)); + default: + return [body]; } + } - private static IEnumerable GetExpressions(Type type, Expression body) + private static void AddExpressions(IEnumerable es, Type t, QueryBuilder qb) + { + foreach (var e in es) { - switch (body.NodeType) - { - case ExpressionType.New: - var n = (NewExpression)body; - return n.Arguments; - case ExpressionType.Parameter: - var propertyInfos = type.GetWritableProperties(); - return propertyInfos.Values.Select(pi => Expression.Property(body, pi)); - default: - return [body]; - } + AddExpression(e, t, qb); + qb.AddSeparator(); } + qb.Remove(); // Remove last comma + } - private static void AddExpressions(IEnumerable es, Type t, QueryBuilder qb) + private static void AddExpression(Expression e, Type t, QueryBuilder qb) + { + switch (e.NodeType) { - foreach (var e in es) - { - AddExpression(e, t, qb); - qb.AddSeparator(); - } - qb.Remove(); // Remove last comma + case ExpressionType.Constant: + var c = (ConstantExpression)e; + qb.AddValue(c.Value); + break; + case ExpressionType.MemberAccess: + var m = (MemberExpression)e; + AddExpression(m, t, qb); + break; + default: + throw new NotImplementedException(); } + } - private static void AddExpression(Expression e, Type t, QueryBuilder qb) + private static void AddExpression(MemberExpression m, Type t, QueryBuilder qb) + { + if (m.Member.DeclaringType == t) { - switch (e.NodeType) - { - case ExpressionType.Constant: - var c = (ConstantExpression)e; - qb.AddValue(c.Value); - break; - case ExpressionType.MemberAccess: - var m = (MemberExpression)e; - AddExpression(m, t, qb); - break; - default: - throw new NotImplementedException(); - } + qb.AddAttribute(m.Member.Name); } - - private static void AddExpression(MemberExpression m, Type t, QueryBuilder qb) + else { - if (m.Member.DeclaringType == t) - { - qb.AddAttribute(m.Member.Name); - } - else - { - qb.AddParameter(m.Member.Name); - } + qb.AddParameter(m.Member.Name); } } } \ No newline at end of file diff --git a/01-Core/Jinget.Core/ExpressionToSql/Internal/Table.cs b/01-Core/Jinget.Core/ExpressionToSql/Internal/Table.cs index 99e8ccd..bcc1c2f 100644 --- a/01-Core/Jinget.Core/ExpressionToSql/Internal/Table.cs +++ b/01-Core/Jinget.Core/ExpressionToSql/Internal/Table.cs @@ -1,11 +1,10 @@ -namespace Jinget.Core.ExpressionToSql.Internal -{ +namespace Jinget.Core.ExpressionToSql.Internal; + #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - public class Table - { - public virtual string Name { get; set; } +public class Table +{ + public virtual string Name { get; set; } - public string Schema { get; set; } = "[dbo]"; - } + public string Schema { get; set; } = "[dbo]"; +} #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. -} \ No newline at end of file diff --git a/01-Core/Jinget.Core/ExpressionToSql/Internal/Where.cs b/01-Core/Jinget.Core/ExpressionToSql/Internal/Where.cs index 3f01ad1..a36a3a1 100644 --- a/01-Core/Jinget.Core/ExpressionToSql/Internal/Where.cs +++ b/01-Core/Jinget.Core/ExpressionToSql/Internal/Where.cs @@ -9,287 +9,286 @@ using Jinget.Core.Exceptions; #pragma warning disable CS8604 // Possible null reference argument. -namespace Jinget.Core.ExpressionToSql.Internal +namespace Jinget.Core.ExpressionToSql.Internal; + +public class Where : Query { - public class Where : Query + private readonly Select _select; + private readonly Expression> _where; + + internal Where(Select select, Expression> where) { - private readonly Select _select; - private readonly Expression> _where; + _select = select; + _where = where; + } - internal Where(Select select, Expression> where) - { - _select = select; - _where = where; - } + internal override (QueryBuilder query, Dictionary parameters) ToSql(QueryBuilder query) + { + _select.ToSql(query); - internal override (QueryBuilder query, Dictionary parameters) ToSql(QueryBuilder query) - { - _select.ToSql(query); + var i = 1; - var i = 1; + if (_where is null) + return (query, new Dictionary()); - if (_where is null) - return (query, new Dictionary()); + var where = Where.Recurse(ref i, _where.Body, true); + query.AppendCondition(where.ToString()); + return (query, @where.Parameters); + } - var where = Where.Recurse(ref i, _where.Body, true); - query.AppendCondition(where.ToString()); - return (query, @where.Parameters); + private static WherePart Recurse(ref int i, Expression expression, bool isUnary = false, string? prefix = null, string? postfix = null) + { + if (expression is UnaryExpression unary) + { + return WherePart.Concat(NodeTypeToString(unary.NodeType), Where.Recurse(ref i, unary.Operand, true)); } - - private static WherePart Recurse(ref int i, Expression expression, bool isUnary = false, string? prefix = null, string? postfix = null) + if (expression is BinaryExpression binary) { - if (expression is UnaryExpression unary) - { - return WherePart.Concat(NodeTypeToString(unary.NodeType), Where.Recurse(ref i, unary.Operand, true)); - } - if (expression is BinaryExpression binary) + return WherePart.Concat(Where.Recurse(ref i, binary.Left), NodeTypeToString(binary.NodeType), Where.Recurse(ref i, binary.Right)); + } + if (expression is ConstantExpression constant) + { + var value = constant.Value; + if (value is string @string) { - return WherePart.Concat(Where.Recurse(ref i, binary.Left), NodeTypeToString(binary.NodeType), Where.Recurse(ref i, binary.Right)); + value = prefix + @string + postfix; } - if (expression is ConstantExpression constant) + if (value is bool && isUnary) { - var value = constant.Value; - if (value is string @string) - { - value = prefix + @string + postfix; - } - if (value is bool && isUnary) - { - return WherePart.Concat(WherePart.IsParameter(i++, value), "=", WherePart.IsSql("1")); - } - return WherePart.IsParameter(i++, value); + return WherePart.Concat(WherePart.IsParameter(i++, value), "=", WherePart.IsSql("1")); } - if (expression is MemberExpression member) + return WherePart.IsParameter(i++, value); + } + if (expression is MemberExpression member) + { + switch (member.Member) { - switch (member.Member) - { - case PropertyInfo property: - if (isUnary && member.Type == typeof(bool)) - { - return WherePart.Concat(Where.Recurse(ref i, member), "=", WherePart.IsParameter(i++, true)); - } + case PropertyInfo property: + if (isUnary && member.Type == typeof(bool)) + { + return WherePart.Concat(Where.Recurse(ref i, member), "=", WherePart.IsParameter(i++, true)); + } - if (((MemberExpression)expression).Expression.NodeType == ExpressionType.Constant) - { - goto case_ConstantExpression; - } - return WherePart.IsSql("[" + property.Name + "]"); - case FieldInfo _: - case_ConstantExpression: - var value = GetValue(member); - if (value is string @string) - { - value = prefix + @string + postfix; - } + if (((MemberExpression)expression).Expression.NodeType == ExpressionType.Constant) + { + goto case_ConstantExpression; + } + return WherePart.IsSql("[" + property.Name + "]"); + case FieldInfo _: + case_ConstantExpression: + var value = GetValue(member); + if (value is string @string) + { + value = prefix + @string + postfix; + } - return WherePart.IsParameter(i++, value); - } + return WherePart.IsParameter(i++, value); + } - throw new JingetException($"Jinget Says: Expression does not refer to a property or field: {member}"); + throw new JingetException($"Jinget Says: Expression does not refer to a property or field: {member}"); + } + if (expression is MethodCallExpression methodCall) + { + // %xxx LIKE queries: + if (methodCall.Method == typeof(string).GetMethod("StartsWith", [typeof(string)])) + { + return WherePart.Concat(Where.Recurse(ref i, methodCall.Object), "LIKE", Where.Recurse(ref i, methodCall.Arguments[0], postfix: "%")); + } + // xxx% LIKE queries: + if (methodCall.Method == typeof(string).GetMethod("EndsWith", [typeof(string)])) + { + return WherePart.Concat(Where.Recurse(ref i, methodCall.Object), "LIKE", Where.Recurse(ref i, methodCall.Arguments[0], prefix: "%")); + } + // %xxx% LIKE queries: + if (methodCall.Method == typeof(string).GetMethod("Contains", [typeof(string)])) + { + return WherePart.Concat(Where.Recurse(ref i, methodCall.Object), "LIKE", Where.Recurse(ref i, methodCall.Arguments[0], prefix: "%", postfix: "%")); } - if (expression is MethodCallExpression methodCall) + // IN queries: + if (methodCall.Method.Name == "Contains") { - // %xxx LIKE queries: - if (methodCall.Method == typeof(string).GetMethod("StartsWith", [typeof(string)])) + Expression? collection; + Expression property; + if (methodCall.Method.IsDefined(typeof(ExtensionAttribute)) && methodCall.Arguments.Count == 2) { - return WherePart.Concat(Where.Recurse(ref i, methodCall.Object), "LIKE", Where.Recurse(ref i, methodCall.Arguments[0], postfix: "%")); + collection = methodCall.Arguments[0]; + property = methodCall.Arguments[1]; } - // xxx% LIKE queries: - if (methodCall.Method == typeof(string).GetMethod("EndsWith", [typeof(string)])) + else if (!methodCall.Method.IsDefined(typeof(ExtensionAttribute)) && methodCall.Arguments.Count == 1) { - return WherePart.Concat(Where.Recurse(ref i, methodCall.Object), "LIKE", Where.Recurse(ref i, methodCall.Arguments[0], prefix: "%")); + collection = methodCall.Object; + property = methodCall.Arguments[0]; } - // %xxx% LIKE queries: - if (methodCall.Method == typeof(string).GetMethod("Contains", [typeof(string)])) + else { - return WherePart.Concat(Where.Recurse(ref i, methodCall.Object), "LIKE", Where.Recurse(ref i, methodCall.Arguments[0], prefix: "%", postfix: "%")); + throw new JingetException("Jinget Says: Unsupported method call: " + methodCall.Method.Name); } - // IN queries: - if (methodCall.Method.Name == "Contains") + var values = (IEnumerable)GetValue(collection); + return WherePart.Concat(Where.Recurse(ref i, property), "IN", WherePart.IsCollection(ref i, values)); + } + // column.ToString() OR Convert.ToString(column) queries + if (methodCall.Method.Name == "ToString") + { + //Convert.ToString(column) + if (methodCall.Object is null) { - Expression collection; - Expression property; - if (methodCall.Method.IsDefined(typeof(ExtensionAttribute)) && methodCall.Arguments.Count == 2) - { - collection = methodCall.Arguments[0]; - property = methodCall.Arguments[1]; - } - else if (!methodCall.Method.IsDefined(typeof(ExtensionAttribute)) && methodCall.Arguments.Count == 1) - { - collection = methodCall.Object; - property = methodCall.Arguments[0]; - } - else - { - throw new JingetException("Jinget Says: Unsupported method call: " + methodCall.Method.Name); - } - var values = (IEnumerable)GetValue(collection); - return WherePart.Concat(Where.Recurse(ref i, property), "IN", WherePart.IsCollection(ref i, values)); + return WherePart.Cast(((MemberExpression)methodCall.Arguments[0]).Member.Name, methodCall.Method.Name); } - // column.ToString() OR Convert.ToString(column) queries - if (methodCall.Method.Name == "ToString") + //column.ToString() + else { - //Convert.ToString(column) - if (methodCall.Object is null) - { - return WherePart.Cast(((MemberExpression)methodCall.Arguments[0]).Member.Name, methodCall.Method.Name); - } - //column.ToString() - else - { - return WherePart.Cast(((MemberExpression)methodCall.Object).Member.Name, methodCall.Method.Name); - } + return WherePart.Cast(((MemberExpression)methodCall.Object).Member.Name, methodCall.Method.Name); } + } - // column.ToLower() OR column.SomeMethod().ToLower() OR SomeMethod(column).ToLower() queries - // column.ToUpper() OR column.SomeMethod().ToUpper() OR SomeMethod(column).ToUpper() queries - if (new[] { "ToLower", "ToUpper" }.Contains(methodCall.Method.Name)) + // column.ToLower() OR column.SomeMethod().ToLower() OR SomeMethod(column).ToLower() queries + // column.ToUpper() OR column.SomeMethod().ToUpper() OR SomeMethod(column).ToUpper() queries + if (new[] { "ToLower", "ToUpper" }.Contains(methodCall.Method.Name)) + { + if (methodCall.Object != null) { - if (methodCall.Object != null) + //column.ToLower() + //column.ToUpper() + if (methodCall.Object.NodeType == ExpressionType.MemberAccess) + { + return WherePart.IsFunction(((MemberExpression)methodCall.Object).Member.Name, methodCall.Method.Name); + } + //column.SomeMethod().ToLower() AND SomeMethod(column).ToLower() + //column.SomeMethod().ToUpper() AND SomeMethod(column).ToUpper() + if (methodCall.Object.NodeType == ExpressionType.Call) { - //column.ToLower() - //column.ToUpper() - if (methodCall.Object.NodeType == ExpressionType.MemberAccess) - { - return WherePart.IsFunction(((MemberExpression)methodCall.Object).Member.Name, methodCall.Method.Name); - } - //column.SomeMethod().ToLower() AND SomeMethod(column).ToLower() - //column.SomeMethod().ToUpper() AND SomeMethod(column).ToUpper() - if (methodCall.Object.NodeType == ExpressionType.Call) - { - return WherePart.IsFunction(Where.Recurse(ref i, methodCall.Object).Sql, methodCall.Method.Name); - } + return WherePart.IsFunction(Where.Recurse(ref i, methodCall.Object).Sql, methodCall.Method.Name); } } - return WherePart.IsParameter(i++, Expression.Lambda(methodCall).Compile().DynamicInvoke()); } - throw new JingetException("Jinget Says: Unsupported expression: " + expression.GetType().Name); + return WherePart.IsParameter(i++, Expression.Lambda(methodCall).Compile().DynamicInvoke()); } + throw new JingetException("Jinget Says: Unsupported expression: " + expression.GetType().Name); + } - private static object GetValue(Expression member) - { - // source: http://stackoverflow.com/a/2616980/291955 - var objectMember = Expression.Convert(member, typeof(object)); - var getterLambda = Expression.Lambda>(objectMember); - var getter = getterLambda.Compile(); - return getter(); - } + private static object GetValue(Expression member) + { + // source: http://stackoverflow.com/a/2616980/291955 + var objectMember = Expression.Convert(member, typeof(object)); + var getterLambda = Expression.Lambda>(objectMember); + var getter = getterLambda.Compile(); + return getter(); + } - private static string NodeTypeToString(ExpressionType nodeType) + private static string NodeTypeToString(ExpressionType nodeType) + { + return nodeType switch { - return nodeType switch - { - ExpressionType.Add => "+", - ExpressionType.And => "&", - ExpressionType.AndAlso => "AND", - ExpressionType.Divide => "/", - ExpressionType.Equal => "=", - ExpressionType.ExclusiveOr => "^", - ExpressionType.GreaterThan => ">", - ExpressionType.GreaterThanOrEqual => ">=", - ExpressionType.LessThan => "<", - ExpressionType.LessThanOrEqual => "<=", - ExpressionType.Modulo => "%", - ExpressionType.Multiply => "*", - ExpressionType.Negate => "-", - ExpressionType.Not => "NOT", - ExpressionType.NotEqual => "<>", - ExpressionType.Or => "|", - ExpressionType.OrElse => "OR", - ExpressionType.Subtract => "-", - _ => throw new JingetException($"Jinget Says: Unsupported node type: {nodeType}"), - }; - } + ExpressionType.Add => "+", + ExpressionType.And => "&", + ExpressionType.AndAlso => "AND", + ExpressionType.Divide => "/", + ExpressionType.Equal => "=", + ExpressionType.ExclusiveOr => "^", + ExpressionType.GreaterThan => ">", + ExpressionType.GreaterThanOrEqual => ">=", + ExpressionType.LessThan => "<", + ExpressionType.LessThanOrEqual => "<=", + ExpressionType.Modulo => "%", + ExpressionType.Multiply => "*", + ExpressionType.Negate => "-", + ExpressionType.Not => "NOT", + ExpressionType.NotEqual => "<>", + ExpressionType.Or => "|", + ExpressionType.OrElse => "OR", + ExpressionType.Subtract => "-", + _ => throw new JingetException($"Jinget Says: Unsupported node type: {nodeType}"), + }; } +} + +public class WherePart +{ + public string? Sql { get; set; } + public Dictionary Parameters { get; set; } = []; - public class WherePart + public static WherePart IsSql(string sql) => new() { - public string? Sql { get; set; } - public Dictionary Parameters { get; set; } = []; + Parameters = [], + Sql = sql + }; - public static WherePart IsSql(string sql) => new() + private static string ToSqlSyntax(string method, int len = 0) + { + return method.ToLower() switch { - Parameters = [], - Sql = sql + "tolower" => "LOWER(@P1)", + "toupper" => "UPPER(@P1)", + "tostring" => $"NVARCHAR({(len <= 0 ? "MAX" : len.ToString())})", + _ => string.Empty, }; + } - private static string ToSqlSyntax(string method, int len = 0) - { - return method.ToLower() switch - { - "tolower" => "LOWER(@P1)", - "toupper" => "UPPER(@P1)", - "tostring" => $"NVARCHAR({(len <= 0 ? "MAX" : len.ToString())})", - _ => string.Empty, - }; - } - - public static WherePart Cast(string column, string method) => - new() - { - Sql = $"CAST({column} AS {ToSqlSyntax(method)})" - }; - - public static WherePart IsFunction(string? column, string method) + public static WherePart Cast(string column, string method) => + new() { - if (string.IsNullOrWhiteSpace(column)) - return new WherePart(); - return new() - { - Sql = $"{ToSqlSyntax(method).Replace("@P1", column)}" - }; - } + Sql = $"CAST({column} AS {ToSqlSyntax(method)})" + }; - public static WherePart IsParameter(int count, object? value) => new() + public static WherePart IsFunction(string? column, string method) + { + if (string.IsNullOrWhiteSpace(column)) + return new WherePart(); + return new() { - Parameters = { { count.ToString(), value } }, - Sql = $"@{count}" + Sql = $"{ToSqlSyntax(method).Replace("@P1", column)}" }; + } + + public static WherePart IsParameter(int count, object? value) => new() + { + Parameters = { { count.ToString(), value } }, + Sql = $"@{count}" + }; - public static WherePart IsCollection(ref int countStart, IEnumerable values) + public static WherePart IsCollection(ref int countStart, IEnumerable values) + { + var parameters = new Dictionary(); + var sql = new StringBuilder("("); + foreach (object value in values) { - var parameters = new Dictionary(); - var sql = new StringBuilder("("); - foreach (object value in values) - { - parameters.Add((countStart).ToString(), value); - sql.Append($"@{countStart},"); - countStart++; - } - if (sql.Length == 1) - { - sql.Append("null,"); - } - sql[^1] = ')';//sql[len -1] - return new WherePart - { - Parameters = parameters, - Sql = sql.ToString() - }; + parameters.Add((countStart).ToString(), value); + sql.Append($"@{countStart},"); + countStart++; } - - public static WherePart Concat(string @operator, WherePart operand) => new() + if (sql.Length == 1) + { + sql.Append("null,"); + } + sql[^1] = ')';//sql[len -1] + return new WherePart { - Parameters = operand.Parameters, - Sql = $"({@operator} {operand.Sql})" + Parameters = parameters, + Sql = sql.ToString() }; + } - public static WherePart Concat(WherePart left, string @operator, WherePart right) - { - //these operators does not need to append @ - List excludedList = ["IN", "AND", "OR"]; - var rightExpr = !excludedList.Contains(@operator) && !right.Sql.StartsWith("@") - ? "@" + right.Sql.Replace("[", "").Replace("]", "") - : right.Sql; + public static WherePart Concat(string @operator, WherePart operand) => new() + { + Parameters = operand.Parameters, + Sql = $"({@operator} {operand.Sql})" + }; - return new WherePart - { - Parameters = left.Parameters.Union(right.Parameters).ToDictionary(kvp => kvp.Key, kvp => kvp.Value), - Sql = $"({left.Sql} {@operator} {rightExpr})" - }; - } + public static WherePart Concat(WherePart left, string @operator, WherePart right) + { + //these operators does not need to append @ + List excludedList = ["IN", "AND", "OR"]; + var rightExpr = !excludedList.Contains(@operator) && !right.Sql.StartsWith("@") + ? "@" + right.Sql.Replace("[", "").Replace("]", "") + : right.Sql; - public override string? ToString() => Sql; + return new WherePart + { + Parameters = left.Parameters.Union(right.Parameters).ToDictionary(kvp => kvp.Key, kvp => kvp.Value), + Sql = $"({left.Sql} {@operator} {rightExpr})" + }; } + + public override string? ToString() => Sql; } #pragma warning restore CS8604 // Possible null reference argument. \ No newline at end of file diff --git a/01-Core/Jinget.Core/ExpressionToSql/Sql.cs b/01-Core/Jinget.Core/ExpressionToSql/Sql.cs index 0ec8ef4..f7ab5c7 100644 --- a/01-Core/Jinget.Core/ExpressionToSql/Sql.cs +++ b/01-Core/Jinget.Core/ExpressionToSql/Sql.cs @@ -2,20 +2,19 @@ using System; using System.Linq.Expressions; -namespace Jinget.Core.ExpressionToSql +namespace Jinget.Core.ExpressionToSql; + +public static class Sql { - public static class Sql - { - public static Select Select(Expression> selector, string tableName) => Create(selector, null, tableName); + public static Select Select(Expression> selector, string tableName) => Create(selector, null, tableName); - public static Select Select(Expression> selector, Table table) => Create(selector, null, table); + public static Select Select(Expression> selector, Table table) => Create(selector, null, table); - public static Select Top(Expression> selector, int take, string tableName) => Create(selector, take, tableName); + public static Select Top(Expression> selector, int take, string tableName) => Create(selector, take, tableName); - public static Select Top(Expression> selector, int take, Table table) => Create(selector, take, table); + public static Select Top(Expression> selector, int take, Table table) => Create(selector, take, table); - private static Select Create(Expression> selector, int? take, string tableName) => Create(selector, take, new Table { Name = tableName }); + private static Select Create(Expression> selector, int? take, string tableName) => Create(selector, take, new Table { Name = tableName }); - private static Select Create(Expression> selector, int? take, Table table) => new(selector, take, table); - } + private static Select Create(Expression> selector, int? take, Table table) => new(selector, take, table); } diff --git a/01-Core/Jinget.Core/ExtensionMethods/Collections/IDictionaryExtensions.cs b/01-Core/Jinget.Core/ExtensionMethods/Collections/IDictionaryExtensions.cs index 3246231..c570878 100644 --- a/01-Core/Jinget.Core/ExtensionMethods/Collections/IDictionaryExtensions.cs +++ b/01-Core/Jinget.Core/ExtensionMethods/Collections/IDictionaryExtensions.cs @@ -2,56 +2,55 @@ using System.Collections.Generic; using System.Linq; -namespace Jinget.Core.ExtensionMethods.Collections +namespace Jinget.Core.ExtensionMethods.Collections; + +public static class IDictionaryExtensions { - public static class IDictionaryExtensions + /// + /// By default(=false), only keys in second collection which do not exist + /// in the first collection will be merged and duplicate keys will be ignored + /// + /// if set to true, then duplicate keys from second collection will be overwritten to the first collection + public static IDictionary? Merge(this IDictionary? first, IDictionary? second, bool overwrite = false) { - /// - /// By default(=false), only keys in second collection which do not exist - /// in the first collection will be merged and duplicate keys will be ignored - /// - /// if set to true, then duplicate keys from second collection will be overwritten to the first collection - public static IDictionary? Merge(this IDictionary? first, IDictionary? second, bool overwrite = false) - { - if (first == null && second == null) - return null; - if (first == null) - return second; - if (second == null) - return first; + if (first == null && second == null) + return null; + if (first == null) + return second; + if (second == null) + return first; - foreach (var member in second) + foreach (var member in second) + { + if (overwrite) { - if (overwrite) + if (first.ContainsKey(member.Key)) { - if (first.ContainsKey(member.Key)) - { - first[member.Key] = member.Value; - } - else - { - first.Add(member.Key, member.Value); - } + first[member.Key] = member.Value; } - else if (!first.ContainsKey(member.Key)) + else { first.Add(member.Key, member.Value); } } - - return first; + else if (!first.ContainsKey(member.Key)) + { + first.Add(member.Key, member.Value); + } } - /// - /// convert dictionary to - /// - /// - /// - public static List ToFilterCriteria(this IDictionary input) - => input.Select(x => new FilterCriteria - { - Operand = x.Key, - Value = x.Value - }).ToList(); + return first; } + + /// + /// convert dictionary to + /// + /// + /// + public static List ToFilterCriteria(this IDictionary input) + => input.Select(x => new FilterCriteria + { + Operand = x.Key, + Value = x.Value + }).ToList(); } diff --git a/01-Core/Jinget.Core/ExtensionMethods/Collections/IQueryableExtensions.cs b/01-Core/Jinget.Core/ExtensionMethods/Collections/IQueryableExtensions.cs index 5a34d06..6850120 100644 --- a/01-Core/Jinget.Core/ExtensionMethods/Collections/IQueryableExtensions.cs +++ b/01-Core/Jinget.Core/ExtensionMethods/Collections/IQueryableExtensions.cs @@ -4,43 +4,42 @@ using Jinget.Core.Enumerations; using Jinget.Core.Exceptions; -namespace Jinget.Core.ExtensionMethods.Collections +namespace Jinget.Core.ExtensionMethods.Collections; + +public static class IQueryableExtensions { - public static class IQueryableExtensions + /// + /// Sort a collection based on a property name. + /// This method is similar to + /// and + /// + /// methods except that this method sort the collection using property name. + /// + /// If the given not found and also has 'null' value, then 's will have presedence over . + /// + /// + /// + public static IQueryable OrderByDynamic(this IQueryable query, string orderByMember, OrderByDirection direction) { - /// - /// Sort a collection based on a property name. - /// This method is similar to - /// and - /// - /// methods except that this method sort the collection using property name. - /// - /// If the given not found and also has 'null' value, then 's will have presedence over . - /// - /// - /// - public static IQueryable OrderByDynamic(this IQueryable query, string orderByMember, OrderByDirection direction) + var queryElementTypeParam = Expression.Parameter(typeof(T)); + Expression memberAccess = queryElementTypeParam; + foreach (var member in orderByMember.Split('.', StringSplitOptions.RemoveEmptyEntries)) { - var queryElementTypeParam = Expression.Parameter(typeof(T)); - Expression memberAccess = queryElementTypeParam; - foreach (var member in orderByMember.Split('.', StringSplitOptions.RemoveEmptyEntries)) - { - memberAccess = Expression.PropertyOrField(memberAccess, member); - } + memberAccess = Expression.PropertyOrField(memberAccess, member); + } - if (memberAccess is null) - throw new JingetException($"Jinget Says: {orderByMember} not found in the given type", new NullReferenceException()); + if (memberAccess is null) + throw new JingetException($"Jinget Says: {orderByMember} not found in the given type", new NullReferenceException()); - var keySelector = Expression.Lambda(memberAccess, queryElementTypeParam); + var keySelector = Expression.Lambda(memberAccess, queryElementTypeParam); - var orderBy = Expression.Call( - typeof(Queryable), - direction == OrderByDirection.Ascending ? "OrderBy" : "OrderByDescending", - [typeof(T), memberAccess.Type], - query.Expression, - Expression.Quote(keySelector)); + var orderBy = Expression.Call( + typeof(Queryable), + direction == OrderByDirection.Ascending ? "OrderBy" : "OrderByDescending", + [typeof(T), memberAccess.Type], + query.Expression, + Expression.Quote(keySelector)); - return query.Provider.CreateQuery(orderBy); - } + return query.Provider.CreateQuery(orderBy); } } \ No newline at end of file diff --git a/01-Core/Jinget.Core/ExtensionMethods/Dapper/DynamicParametersExtensions.cs b/01-Core/Jinget.Core/ExtensionMethods/Dapper/DynamicParametersExtensions.cs index 24bdb98..02b9b21 100644 --- a/01-Core/Jinget.Core/ExtensionMethods/Dapper/DynamicParametersExtensions.cs +++ b/01-Core/Jinget.Core/ExtensionMethods/Dapper/DynamicParametersExtensions.cs @@ -1,51 +1,37 @@ -using System.Collections; -using System.Collections.Generic; -using System.Data; -using System.Linq; -using System.Reflection; -using Dapper; -using Jinget.Core.ExtensionMethods.Enums; +namespace Jinget.Core.ExtensionMethods.Dapper; -namespace Jinget.Core.ExtensionMethods.Dapper +public static class DynamicParametersExtensions { - public static class DynamicParametersExtensions - { - /// - /// Convert `DynamicParameters` to `Dictionary` - /// - public static Dictionary GetKeyValues(this DynamicParameters parameters) => parameters.ParameterNames.ToDictionary(param => param, param => parameters.Get(param)); - - /// - /// Convert `DynamicParameters` values to SQL values - /// - /// - /// - public static List GetSQLValues(this DynamicParameters parameters) - { - List lstValues = []; - var t = parameters.GetType().GetField("parameters", BindingFlags.NonPublic | BindingFlags.Instance); - - if (t == null) - return lstValues; -#pragma warning disable CS8604 // Possible null reference argument. + /// + /// Convert `DynamicParameters` to `Dictionary` + /// + public static Dictionary GetKeyValues(this DynamicParameters parameters) => parameters.ParameterNames.ToDictionary(param => param, param => parameters.Get(param)); - foreach (DictionaryEntry dictionaryEntry in (IDictionary)t.GetValue(parameters)) - { -#pragma warning disable CS8605 // Unboxing a possibly null value. - var dbType = (DbType)dictionaryEntry.Value.GetValue("DbType"); -#pragma warning restore CS8605 // Unboxing a possibly null value. - if (dbType.IsBooleanDbType()) - lstValues.Add(parameters.Get(dictionaryEntry.Key.ToString()) == true ? 1 : 0); - else if (dbType.IsNumericDbType()) - lstValues.Add(parameters.Get(dictionaryEntry.Key.ToString())); - else if (dbType.IsUnicodeDbType()) - lstValues.Add("N'" + parameters.Get(dictionaryEntry.Key.ToString()) + "'"); - else - lstValues.Add("'" + parameters.Get(dictionaryEntry.Key.ToString()) + "'"); - } -#pragma warning restore CS8604 // Possible null reference argument. + /// + /// Convert `DynamicParameters` values to SQL values + /// + /// + /// + public static List GetSQLValues(this DynamicParameters parameters) + { + List lstValues = []; + var t = parameters.GetType().GetField("parameters", BindingFlags.NonPublic | BindingFlags.Instance); + if (t == null) return lstValues; + + foreach (DictionaryEntry dictionaryEntry in (IDictionary)t.GetValue(parameters)) + { + var dbType = (DbType)dictionaryEntry.Value.GetValue("DbType"); + if (dbType.IsBooleanDbType()) + lstValues.Add(parameters.Get(dictionaryEntry.Key.ToString()) == true ? 1 : 0); + else if (dbType.IsNumericDbType()) + lstValues.Add(parameters.Get(dictionaryEntry.Key.ToString())); + else if (dbType.IsUnicodeDbType()) + lstValues.Add("N'" + parameters.Get(dictionaryEntry.Key.ToString()) + "'"); + else + lstValues.Add("'" + parameters.Get(dictionaryEntry.Key.ToString()) + "'"); } + return lstValues; } } \ No newline at end of file diff --git a/01-Core/Jinget.Core/ExtensionMethods/Database/SqlClient/IDbCommandExtensions.cs b/01-Core/Jinget.Core/ExtensionMethods/Database/SqlClient/IDbCommandExtensions.cs index d74e67e..e5cc54e 100644 --- a/01-Core/Jinget.Core/ExtensionMethods/Database/SqlClient/IDbCommandExtensions.cs +++ b/01-Core/Jinget.Core/ExtensionMethods/Database/SqlClient/IDbCommandExtensions.cs @@ -1,33 +1,32 @@ using System; using System.Data; -namespace Jinget.Core.ExtensionMethods.Database.SqlClient +namespace Jinget.Core.ExtensionMethods.Database.SqlClient; + +public static class IDbCommandExtensions { - public static class IDbCommandExtensions + /// + /// Replace Arabic ي and ك characters in CommandText and Parameters with their Farsi equalivants + /// + public static void ApplyCorrectYeKe(this IDbCommand command) { - /// - /// Replace Arabic ي and ك characters in CommandText and Parameters with their Farsi equalivants - /// - public static void ApplyCorrectYeKe(this IDbCommand command) + command.CommandText = command.CommandText.ApplyCorrectYeKe(); + + foreach (IDataParameter parameter in command.Parameters) { - command.CommandText = command.CommandText.ApplyCorrectYeKe(); + if (parameter.Value is DBNull) + continue; - foreach (IDataParameter parameter in command.Parameters) + switch (parameter.DbType) { - if (parameter.Value is DBNull) - continue; - - switch (parameter.DbType) - { - case DbType.AnsiString: - case DbType.AnsiStringFixedLength: - case DbType.String: - case DbType.StringFixedLength: - case DbType.Xml: - if (parameter.Value != null) - parameter.Value = parameter.Value.ToString().ApplyCorrectYeKe(); - break; - } + case DbType.AnsiString: + case DbType.AnsiStringFixedLength: + case DbType.String: + case DbType.StringFixedLength: + case DbType.Xml: + if (parameter.Value != null) + parameter.Value = parameter.Value.ToString().ApplyCorrectYeKe(); + break; } } } diff --git a/01-Core/Jinget.Core/ExtensionMethods/Database/SqlClient/IDbConnectionExtensions.cs b/01-Core/Jinget.Core/ExtensionMethods/Database/SqlClient/IDbConnectionExtensions.cs index ecfc0e0..c1dab60 100644 --- a/01-Core/Jinget.Core/ExtensionMethods/Database/SqlClient/IDbConnectionExtensions.cs +++ b/01-Core/Jinget.Core/ExtensionMethods/Database/SqlClient/IDbConnectionExtensions.cs @@ -9,93 +9,92 @@ using Jinget.Core.ExtensionMethods.ExpressionToSql; using Jinget.Core.ExtensionMethods.Collections; -namespace Jinget.Core.ExtensionMethods.Database.SqlClient +namespace Jinget.Core.ExtensionMethods.Database.SqlClient; + +public static class IDbConnectionExtensions { - public static class IDbConnectionExtensions + /// + /// Opens a connection to database safely + /// + /// This method first check if the connection state is already equal to or not, if not, + /// first it tries to Close the connection and then reopen it + public static void SafeOpen(this IDbConnection connection) { - /// - /// Opens a connection to database safely - /// - /// This method first check if the connection state is already equal to or not, if not, - /// first it tries to Close the connection and then reopen it - public static void SafeOpen(this IDbConnection connection) - { - if (connection.State != ConnectionState.Closed) - connection.Close(); - connection.Open(); - } + if (connection.State != ConnectionState.Closed) + connection.Close(); + connection.Open(); + } - private static (string queryText, Dictionary? queryParameters) PrepareQuery(Query sql, object? param) - { - var query = sql.ToSql(); - var queryText = query.query.ToString(); + private static (string queryText, Dictionary? queryParameters) PrepareQuery(Query sql, object? param) + { + var query = sql.ToSql(); + var queryText = query.query.ToString(); - if (queryText.IndexOf("SELECT FROM ", StringComparison.InvariantCultureIgnoreCase) > 0) - queryText = queryText.Replace("SELECT FROM ", "SELECT * FROM "); + if (queryText.IndexOf("SELECT FROM ", StringComparison.InvariantCultureIgnoreCase) > 0) + queryText = queryText.Replace("SELECT FROM ", "SELECT * FROM "); - string countQueryText = ""; - if (param != null) - { - var orderBy = (param as IOrderBy)?.OrderBy; - var paging = (param as IPaginated)?.PagingConfig; + string countQueryText = ""; + if (param != null) + { + var orderBy = (param as IOrderBy)?.OrderBy; + var paging = (param as IPaginated)?.PagingConfig; - if (paging != null) - { - countQueryText = queryText[queryText.IndexOf(" FROM ", StringComparison.CurrentCultureIgnoreCase)..]; - countQueryText = "Select Count(*) " + countQueryText; + if (paging != null) + { + countQueryText = queryText[queryText.IndexOf(" FROM ", StringComparison.CurrentCultureIgnoreCase)..]; + countQueryText = "Select Count(*) " + countQueryText; - queryText = string.Join(" ", queryText, paging.GetPaging(orderBy)); - } + queryText = string.Join(" ", queryText, paging.GetPaging(orderBy)); } + } - var queryParams = query.parameters; - if (query.parameters != null && !query.parameters.Any() && param != null) - queryParams.Merge(param.ToDictionary()); + var queryParams = query.parameters; + if (query.parameters != null && !query.parameters.Any() && param != null) + queryParams.Merge(param.ToDictionary()); - return (countQueryText == "" ? queryText : string.Join(";", queryText, countQueryText), queryParams); - } + return (countQueryText == "" ? queryText : string.Join(";", queryText, countQueryText), queryParams); + } - private static async Task<(IEnumerable Data, int TotalCount)> ExecQueryAsync(IDbConnection cnn, Query sql, object? param, IDbTransaction? transaction, int? commandTimeout, CommandType? commandType) - { - var (queryText, queryParameters) = PrepareQuery(sql, param); + private static async Task<(IEnumerable Data, int TotalCount)> ExecQueryAsync(IDbConnection cnn, Query sql, object? param, IDbTransaction? transaction, int? commandTimeout, CommandType? commandType) + { + var (queryText, queryParameters) = PrepareQuery(sql, param); - var result = - await cnn.QueryMultipleAsync(queryText, queryParameters, transaction, commandTimeout, - commandType); + var result = + await cnn.QueryMultipleAsync(queryText, queryParameters, transaction, commandTimeout, + commandType); - return (Data: await result.ReadAsync(), - TotalCount: param is IPaginated paginated && paginated.PagingConfig != null - ? (await result.ReadAsync()).FirstOrDefault() - : 0); - } + return (Data: await result.ReadAsync(), + TotalCount: param is IPaginated paginated && paginated.PagingConfig != null + ? (await result.ReadAsync()).FirstOrDefault() + : 0); + } - private static (IEnumerable Data, int TotalCount) ExecQuery( - IDbConnection cnn, - Query sql, - object? param, - IDbTransaction? transaction, - int? commandTimeout, - CommandType? commandType) - { - var (queryText, queryParameters) = PrepareQuery(sql, param); + private static (IEnumerable Data, int TotalCount) ExecQuery( + IDbConnection cnn, + Query sql, + object? param, + IDbTransaction? transaction, + int? commandTimeout, + CommandType? commandType) + { + var (queryText, queryParameters) = PrepareQuery(sql, param); - var result = cnn.QueryMultiple(queryText, queryParameters, transaction, commandTimeout, commandType); - return (Data: result.Read(), - TotalCount: param is IPaginated paginated && paginated.PagingConfig != null - ? result.Read().FirstOrDefault() - : 0); - } + var result = cnn.QueryMultiple(queryText, queryParameters, transaction, commandTimeout, commandType); + return (Data: result.Read(), + TotalCount: param is IPaginated paginated && paginated.PagingConfig != null + ? result.Read().FirstOrDefault() + : 0); + } - public static async Task<(IEnumerable Data, int TotalCount)> QueryAsync(this IDbConnection cnn, Select sql, object? param = null, IDbTransaction? transaction = null, int? commandTimeout = null, CommandType? commandType = null) - => await ExecQueryAsync(cnn, sql, param, transaction, commandTimeout, commandType); + public static async Task<(IEnumerable Data, int TotalCount)> QueryAsync(this IDbConnection cnn, Select sql, object? param = null, IDbTransaction? transaction = null, int? commandTimeout = null, CommandType? commandType = null) + => await ExecQueryAsync(cnn, sql, param, transaction, commandTimeout, commandType); - public static async Task<(IEnumerable Data, int TotalCount)> QueryAsync(this IDbConnection cnn, Where sql, object? param = null, IDbTransaction? transaction = null, int? commandTimeout = null, CommandType? commandType = null) - => await ExecQueryAsync(cnn, sql, param, transaction, commandTimeout, commandType); + public static async Task<(IEnumerable Data, int TotalCount)> QueryAsync(this IDbConnection cnn, Where sql, object? param = null, IDbTransaction? transaction = null, int? commandTimeout = null, CommandType? commandType = null) + => await ExecQueryAsync(cnn, sql, param, transaction, commandTimeout, commandType); - public static (IEnumerable Data, int TotalCount) Query(this IDbConnection cnn, Select sql, object? param = null, IDbTransaction? transaction = null, int? commandTimeout = null, CommandType? commandType = null) - => ExecQuery(cnn, sql, param, transaction, commandTimeout, commandType); + public static (IEnumerable Data, int TotalCount) Query(this IDbConnection cnn, Select sql, object? param = null, IDbTransaction? transaction = null, int? commandTimeout = null, CommandType? commandType = null) + => ExecQuery(cnn, sql, param, transaction, commandTimeout, commandType); - public static (IEnumerable Data, int TotalCount) Query(this IDbConnection cnn, Where sql, object? param = null, IDbTransaction? transaction = null, int? commandTimeout = null, CommandType? commandType = null) - => ExecQuery(cnn, sql, param, transaction, commandTimeout, commandType); - } + public static (IEnumerable Data, int TotalCount) Query(this IDbConnection cnn, Where sql, object? param = null, IDbTransaction? transaction = null, int? commandTimeout = null, CommandType? commandType = null) + => ExecQuery(cnn, sql, param, transaction, commandTimeout, commandType); } diff --git a/01-Core/Jinget.Core/ExtensionMethods/Enums/DbTypeExtensions.cs b/01-Core/Jinget.Core/ExtensionMethods/Enums/DbTypeExtensions.cs index 9898b92..4433c84 100644 --- a/01-Core/Jinget.Core/ExtensionMethods/Enums/DbTypeExtensions.cs +++ b/01-Core/Jinget.Core/ExtensionMethods/Enums/DbTypeExtensions.cs @@ -1,71 +1,70 @@ using System.Data; -namespace Jinget.Core.ExtensionMethods.Enums +namespace Jinget.Core.ExtensionMethods.Enums; + +public static class DbTypeExtensions { - public static class DbTypeExtensions + /// + /// Check if given is a numeric type or not + /// + public static bool IsNumericDbType(this DbType type) { - /// - /// Check if given is a numeric type or not - /// - public static bool IsNumericDbType(this DbType type) - { #if NET5_0_OR_GREATER - return type switch - { - DbType.AnsiString - or DbType.Binary - or DbType.Currency - or DbType.Date - or DbType.DateTime - or DbType.Guid - or DbType.Object - or DbType.String - or DbType.Time - or DbType.AnsiStringFixedLength - or DbType.StringFixedLength - or DbType.Xml - or DbType.DateTime2 - or DbType.DateTimeOffset => false, - _ => true, - }; + return type switch + { + DbType.AnsiString + or DbType.Binary + or DbType.Currency + or DbType.Date + or DbType.DateTime + or DbType.Guid + or DbType.Object + or DbType.String + or DbType.Time + or DbType.AnsiStringFixedLength + or DbType.StringFixedLength + or DbType.Xml + or DbType.DateTime2 + or DbType.DateTimeOffset => false, + _ => true, + }; #else - switch (type) - { - case DbType.AnsiString: - case DbType.Binary: - case DbType.Currency: - case DbType.Date: - case DbType.DateTime: - case DbType.Guid: - case DbType.Object: - case DbType.String: - case DbType.Time: - case DbType.AnsiStringFixedLength: - case DbType.StringFixedLength: - case DbType.Xml: - case DbType.DateTime2: - case DbType.DateTimeOffset: - return false; - default: - return true; - } -#endif + switch (type) + { + case DbType.AnsiString: + case DbType.Binary: + case DbType.Currency: + case DbType.Date: + case DbType.DateTime: + case DbType.Guid: + case DbType.Object: + case DbType.String: + case DbType.Time: + case DbType.AnsiStringFixedLength: + case DbType.StringFixedLength: + case DbType.Xml: + case DbType.DateTime2: + case DbType.DateTimeOffset: + return false; + default: + return true; } +#endif + } - /// - /// Check if the given type is an unicode string type such as 'nchar' or 'nvarchar' - /// - public static bool IsUnicodeDbType(this DbType type) => type == DbType.String; + /// + /// Check if the given type is an unicode string type such as 'nchar' or 'nvarchar' + /// + public static bool IsUnicodeDbType(this DbType type) => type == DbType.String; - /// - /// Check if the given type is a non-unicode string type such as 'char' or 'varchar' - /// - public static bool IsNonUnicodeDbType(this DbType type) => type == DbType.AnsiString; + /// + /// Check if the given type is a non-unicode string type such as 'char' or 'varchar' + /// + public static bool IsNonUnicodeDbType(this DbType type) => type == DbType.AnsiString; - /// - /// Check if the given type is a boolean type - /// - public static bool IsBooleanDbType(this DbType type) => type == DbType.Boolean; - } + /// + /// Check if the given type is a boolean type + /// + public static bool IsBooleanDbType(this DbType type) => type == DbType.Boolean; } \ No newline at end of file diff --git a/01-Core/Jinget.Core/ExtensionMethods/Enums/EnumExtensions.cs b/01-Core/Jinget.Core/ExtensionMethods/Enums/EnumExtensions.cs index e2ed34a..7ae103a 100644 --- a/01-Core/Jinget.Core/ExtensionMethods/Enums/EnumExtensions.cs +++ b/01-Core/Jinget.Core/ExtensionMethods/Enums/EnumExtensions.cs @@ -4,100 +4,99 @@ using System.ComponentModel.DataAnnotations; using System.Linq; -namespace Jinget.Core.ExtensionMethods.Enums +namespace Jinget.Core.ExtensionMethods.Enums; + +public static class EnumExtensions { - public static class EnumExtensions + /// + /// Get Name property of Display attribute for a specific enum value + /// If no Name is set on a field, then the stringfied value will be returned + /// + public static string? GetDisplayName(this Enum value) { - /// - /// Get Name property of Display attribute for a specific enum value - /// If no Name is set on a field, then the stringfied value will be returned - /// - public static string? GetDisplayName(this Enum value) - { - var fi = value.GetType().GetField(value.ToString()); - if (fi is null) - return string.Empty; - var attributes = (DisplayAttribute[])fi.GetCustomAttributes(typeof(DisplayAttribute), false); - return attributes.Length > 0 ? attributes[0].Name : value.ToString(); - } + var fi = value.GetType().GetField(value.ToString()); + if (fi is null) + return string.Empty; + var attributes = (DisplayAttribute[])fi.GetCustomAttributes(typeof(DisplayAttribute), false); + return attributes.Length > 0 ? attributes[0].Name : value.ToString(); + } - /// - /// Get Description of a specific enum value - /// If no Description is set on a field, then the stringfied value will be returned - /// - public static string GetDescription(this Enum value) - { - var fi = value.GetType().GetField(value.ToString()); - if (fi is null) - return string.Empty; - var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false); - return attributes.Length > 0 ? attributes[0].Description : value.ToString(); - } + /// + /// Get Description of a specific enum value + /// If no Description is set on a field, then the stringfied value will be returned + /// + public static string GetDescription(this Enum value) + { + var fi = value.GetType().GetField(value.ToString()); + if (fi is null) + return string.Empty; + var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false); + return attributes.Length > 0 ? attributes[0].Description : value.ToString(); + } - /// - /// Return enum value based on the given Description. - /// If no Description is set on a field, then field name will be compared aginst the given description - /// - /// typeof enum - /// - /// - public static TEnum GetValueFromDescription(string description) where TEnum : struct, IConvertible - { - var type = typeof(TEnum); - if (!type.IsEnum) - throw new InvalidOperationException(); + /// + /// Return enum value based on the given Description. + /// If no Description is set on a field, then field name will be compared aginst the given description + /// + /// typeof enum + /// + /// + public static TEnum GetValueFromDescription(string description) where TEnum : struct, IConvertible + { + var type = typeof(TEnum); + if (!type.IsEnum) + throw new InvalidOperationException(); - foreach (var field in type.GetFields()) + foreach (var field in type.GetFields()) + { + //Is there any Description attribute set for the field? + if ( + string.Equals( + Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) is DescriptionAttribute attribute ? attribute.Description : field.Name, + description, + StringComparison.CurrentCultureIgnoreCase) + ) { - //Is there any Description attribute set for the field? - if ( - string.Equals( - Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) is DescriptionAttribute attribute ? attribute.Description : field.Name, - description, - StringComparison.CurrentCultureIgnoreCase) - ) - { - var value = field.GetValue(null); - return value == null ? default : (TEnum)value; - } + var value = field.GetValue(null); + return value == null ? default : (TEnum)value; } - - throw new InvalidEnumArgumentException($"Enum member with description/name '{description}', not found!"); } - /// - /// Return enum value based on the given Name property of Display attribute. - /// If no Name is set on a field, then field name will be compared aginst the given displayName - /// - /// typeof enum - /// - /// - public static List GetValueFromDisplayName(string displayName) where TEnum : struct, IConvertible - { - var type = typeof(TEnum); - if (!type.IsEnum) - throw new InvalidOperationException(); + throw new InvalidEnumArgumentException($"Enum member with description/name '{description}', not found!"); + } - List results = []; + /// + /// Return enum value based on the given Name property of Display attribute. + /// If no Name is set on a field, then field name will be compared aginst the given displayName + /// + /// typeof enum + /// + /// + public static List GetValueFromDisplayName(string displayName) where TEnum : struct, IConvertible + { + var type = typeof(TEnum); + if (!type.IsEnum) + throw new InvalidOperationException(); - foreach (var field in type.GetFields()) + List results = []; + + foreach (var field in type.GetFields()) + { + //Is there any Description attribute set for the field? + if ( + string.Equals( + Attribute.GetCustomAttribute(field, typeof(DisplayAttribute)) is DisplayAttribute attribute ? attribute.Name : field.Name, + displayName, + StringComparison.CurrentCultureIgnoreCase) + ) { - //Is there any Description attribute set for the field? - if ( - string.Equals( - Attribute.GetCustomAttribute(field, typeof(DisplayAttribute)) is DisplayAttribute attribute ? attribute.Name : field.Name, - displayName, - StringComparison.CurrentCultureIgnoreCase) - ) - { - var value = field.GetValue(null); - results.Add(value == null ? default : (TEnum)value); - } + var value = field.GetValue(null); + results.Add(value == null ? default : (TEnum)value); } - if (results.Any()) - return results; - - throw new InvalidEnumArgumentException($"Enum member with displayName/name '{displayName}', not found!"); } + if (results.Any()) + return results; + + throw new InvalidEnumArgumentException($"Enum member with displayName/name '{displayName}', not found!"); } } \ No newline at end of file diff --git a/01-Core/Jinget.Core/ExtensionMethods/ExpressionToSql/OrderByExtensions.cs b/01-Core/Jinget.Core/ExtensionMethods/ExpressionToSql/OrderByExtensions.cs index f7ceb7c..d2684e5 100644 --- a/01-Core/Jinget.Core/ExtensionMethods/ExpressionToSql/OrderByExtensions.cs +++ b/01-Core/Jinget.Core/ExtensionMethods/ExpressionToSql/OrderByExtensions.cs @@ -2,20 +2,19 @@ using System.Linq; using Jinget.Core.ExpressionToSql.Internal; -namespace Jinget.Core.ExtensionMethods.ExpressionToSql +namespace Jinget.Core.ExtensionMethods.ExpressionToSql; + +public static class OrderByExtensions { - public static class OrderByExtensions - { - static string Stringfy(this List lstOrderBy) => - lstOrderBy.Any() - ? $"ORDER BY {string.Join(",", lstOrderBy.Select(x => x.ToString()))}" - : string.Empty; + static string Stringfy(this List lstOrderBy) => + lstOrderBy.Any() + ? $"ORDER BY {string.Join(",", lstOrderBy.Select(x => x.ToString()))}" + : string.Empty; - public static string GetSorting(this List lstOrderBy) - { - lstOrderBy ??= []; + public static string GetSorting(this List lstOrderBy) + { + lstOrderBy ??= []; - return lstOrderBy.Any() ? lstOrderBy.Stringfy() : string.Empty; - } + return lstOrderBy.Any() ? lstOrderBy.Stringfy() : string.Empty; } } diff --git a/01-Core/Jinget.Core/ExtensionMethods/ExpressionToSql/PagingExtensions.cs b/01-Core/Jinget.Core/ExtensionMethods/ExpressionToSql/PagingExtensions.cs index c1ee06d..1581367 100644 --- a/01-Core/Jinget.Core/ExtensionMethods/ExpressionToSql/PagingExtensions.cs +++ b/01-Core/Jinget.Core/ExtensionMethods/ExpressionToSql/PagingExtensions.cs @@ -2,20 +2,19 @@ using Jinget.Core.Exceptions; using Jinget.Core.ExpressionToSql.Internal; -namespace Jinget.Core.ExtensionMethods.ExpressionToSql +namespace Jinget.Core.ExtensionMethods.ExpressionToSql; + +public static class PagingExtensions { - public static class PagingExtensions + public static string GetPaging(this Paging paging, List? lstOrderBy) { - public static string GetPaging(this Paging paging, List? lstOrderBy) - { - lstOrderBy ??= []; + lstOrderBy ??= []; - string strOrderby = lstOrderBy.GetSorting(); + string strOrderby = lstOrderBy.GetSorting(); - if (string.IsNullOrEmpty(strOrderby) && paging != null) - throw new JingetException("In order to use paging, you should specify at least one order by expression.", 4000); + if (string.IsNullOrEmpty(strOrderby) && paging != null) + throw new JingetException("In order to use paging, you should specify at least one order by expression.", 4000); - return $"{strOrderby} {(paging is null ? "" : paging.ToString())}"; - } + return $"{strOrderby} {(paging is null ? "" : paging.ToString())}"; } } diff --git a/01-Core/Jinget.Core/ExtensionMethods/Expressions/BooleanExpressionExtensions.cs b/01-Core/Jinget.Core/ExtensionMethods/Expressions/BooleanExpressionExtensions.cs index b57f1b2..4457631 100644 --- a/01-Core/Jinget.Core/ExtensionMethods/Expressions/BooleanExpressionExtensions.cs +++ b/01-Core/Jinget.Core/ExtensionMethods/Expressions/BooleanExpressionExtensions.cs @@ -2,61 +2,60 @@ using System; using System.Linq.Expressions; -namespace Jinget.Core.ExtensionMethods.Expressions +namespace Jinget.Core.ExtensionMethods.Expressions; + +public static class BooleanExpressionExtensions { - public static class BooleanExpressionExtensions + /// + /// Negate a boolean expression + /// + public static Expression> Not(this Expression> expr) + => Expression.Lambda>(Expression.Not(expr.Body), expr.Parameters[0]); + + /// + /// Visit a boolean expression + /// + private static (Expression? LeftExpression, Expression? RightExpression) Visit(Expression> leftExpression, + Expression> rightExpression, ParameterExpression parameter) + { + ReplaceExpressionVisitor leftVisitor = new(leftExpression.Parameters[0], parameter); + Expression? left = leftVisitor.Visit(leftExpression.Body); + + var rightVisitor = new ReplaceExpressionVisitor(rightExpression.Parameters[0], parameter); + var right = rightVisitor.Visit(rightExpression.Body); + + return (left, right); + } + + /// + /// should combine conditions using AND operator. if any of expressions passed as null, then the other expression will be returned + /// + /// parameter name used in expression. for example in x=>x.Id>0, parameterName is 'x' + public static Expression> AndAlso(this Expression> expr1, Expression> expr2, string parameterName = "Param_0") { - /// - /// Negate a boolean expression - /// - public static Expression> Not(this Expression> expr) - => Expression.Lambda>(Expression.Not(expr.Body), expr.Parameters[0]); - - /// - /// Visit a boolean expression - /// - private static (Expression? LeftExpression, Expression? RightExpression) Visit(Expression> leftExpression, - Expression> rightExpression, ParameterExpression parameter) - { - ReplaceExpressionVisitor leftVisitor = new(leftExpression.Parameters[0], parameter); - Expression? left = leftVisitor.Visit(leftExpression.Body); - - var rightVisitor = new ReplaceExpressionVisitor(rightExpression.Parameters[0], parameter); - var right = rightVisitor.Visit(rightExpression.Body); - - return (left, right); - } - - /// - /// should combine conditions using AND operator. if any of expressions passed as null, then the other expression will be returned - /// - /// parameter name used in expression. for example in x=>x.Id>0, parameterName is 'x' - public static Expression> AndAlso(this Expression> expr1, Expression> expr2, string parameterName = "Param_0") - { - if (expr1 is null) return expr2; - if (expr2 is null) return expr1; - var parameter = Expression.Parameter(typeof(T), parameterName); - - (Expression? LeftExpression, Expression? RightExpression) = Visit(expr1, expr2, parameter); + if (expr1 is null) return expr2; + if (expr2 is null) return expr1; + var parameter = Expression.Parameter(typeof(T), parameterName); + + (Expression? LeftExpression, Expression? RightExpression) = Visit(expr1, expr2, parameter); #pragma warning disable CS8604 // Possible null reference argument. - return Expression.Lambda>(Expression.AndAlso(LeftExpression, RightExpression), parameter); + return Expression.Lambda>(Expression.AndAlso(LeftExpression, RightExpression), parameter); #pragma warning restore CS8604 // Possible null reference argument. - } - - /// - /// should combine conditions using OR operator. if any of expressions passed as null, then the other expression will be returned - /// - /// parameter name used in expression. for example in x=>x.Id>0, parameterName is 'x' - public static Expression> OrElse(this Expression> expr1, Expression> expr2, string parameterName = "Param_0") - { - if (expr1 is null) return expr2; - if (expr2 is null) return expr1; - var parameter = Expression.Parameter(typeof(T), parameterName); - - (Expression? LeftExpression, Expression? RightExpression) = Visit(expr1, expr2, parameter); + } + + /// + /// should combine conditions using OR operator. if any of expressions passed as null, then the other expression will be returned + /// + /// parameter name used in expression. for example in x=>x.Id>0, parameterName is 'x' + public static Expression> OrElse(this Expression> expr1, Expression> expr2, string parameterName = "Param_0") + { + if (expr1 is null) return expr2; + if (expr2 is null) return expr1; + var parameter = Expression.Parameter(typeof(T), parameterName); + + (Expression? LeftExpression, Expression? RightExpression) = Visit(expr1, expr2, parameter); #pragma warning disable CS8604 // Possible null reference argument. - return Expression.Lambda>(Expression.OrElse(LeftExpression, RightExpression), parameter); + return Expression.Lambda>(Expression.OrElse(LeftExpression, RightExpression), parameter); #pragma warning restore CS8604 // Possible null reference argument. - } } } \ No newline at end of file diff --git a/01-Core/Jinget.Core/ExtensionMethods/Expressions/ExpressionExtensions.cs b/01-Core/Jinget.Core/ExtensionMethods/Expressions/ExpressionExtensions.cs index 2350d9b..af031df 100644 --- a/01-Core/Jinget.Core/ExtensionMethods/Expressions/ExpressionExtensions.cs +++ b/01-Core/Jinget.Core/ExtensionMethods/Expressions/ExpressionExtensions.cs @@ -2,16 +2,15 @@ using System; using System.Linq.Expressions; -namespace Jinget.Core.ExtensionMethods.Expressions +namespace Jinget.Core.ExtensionMethods.Expressions; + +public static class ExpressionExtensions { - public static class ExpressionExtensions - { - /// - /// Transform anonymouse expression to non-anonymouse expression - /// This method is useful wherever the class's default constructor is not accessable due to its access level - /// but you need to use this constructor to define your expression - /// - public static Expression> Transform(this Expression> source) - => Expression.Lambda>(ExpressionUtility.Transform(source.Body, typeof(T)), source.Parameters); - } + /// + /// Transform anonymouse expression to non-anonymouse expression + /// This method is useful wherever the class's default constructor is not accessable due to its access level + /// but you need to use this constructor to define your expression + /// + public static Expression> Transform(this Expression> source) + => Expression.Lambda>(ExpressionUtility.Transform(source.Body, typeof(T)), source.Parameters); } \ No newline at end of file diff --git a/01-Core/Jinget.Core/ExtensionMethods/Expressions/LambdaExpressionExtensions.cs b/01-Core/Jinget.Core/ExtensionMethods/Expressions/LambdaExpressionExtensions.cs index 39f031d..0d1424d 100644 --- a/01-Core/Jinget.Core/ExtensionMethods/Expressions/LambdaExpressionExtensions.cs +++ b/01-Core/Jinget.Core/ExtensionMethods/Expressions/LambdaExpressionExtensions.cs @@ -1,19 +1,18 @@ using Jinget.Core.Utilities.Expressions; using System.Linq.Expressions; -namespace Jinget.Core.ExtensionMethods.Expressions +namespace Jinget.Core.ExtensionMethods.Expressions; + +public static class LambdaExpressionExtensions { - public static class LambdaExpressionExtensions + /// + /// Converts a to string + /// + public static string? Stringfy(this LambdaExpression expression) { - /// - /// Converts a to string - /// - public static string? Stringfy(this LambdaExpression expression) - { - if (expression is null) - return null; - var result = ExpressionUtility.TryParseExpression(expression.Body, out var path); - return result ? path : null; - } + if (expression is null) + return null; + var result = ExpressionUtility.TryParseExpression(expression.Body, out var path); + return result ? path : null; } } \ No newline at end of file diff --git a/01-Core/Jinget.Core/ExtensionMethods/Generics/GenericTypeExtensions.cs b/01-Core/Jinget.Core/ExtensionMethods/Generics/GenericTypeExtensions.cs index b23ce0a..2c61481 100644 --- a/01-Core/Jinget.Core/ExtensionMethods/Generics/GenericTypeExtensions.cs +++ b/01-Core/Jinget.Core/ExtensionMethods/Generics/GenericTypeExtensions.cs @@ -1,26 +1,25 @@ using System; -namespace Jinget.Core.ExtensionMethods.Generics +namespace Jinget.Core.ExtensionMethods.Generics; + +public static class GenericTypeExtensions { - public static class GenericTypeExtensions + /// + /// Check if a type is a child of another type(including generic and non-generic types) + /// This method is very likely to IsSubclassOf method but also supports generic types too + /// + public static bool IsSubclassOfRawGeneric(this Type derivedType, Type parentType) { - /// - /// Check if a type is a child of another type(including generic and non-generic types) - /// This method is very likely to IsSubclassOf method but also supports generic types too - /// - public static bool IsSubclassOfRawGeneric(this Type derivedType, Type parentType) - { - while (derivedType != null && derivedType != typeof(object)) + while (derivedType != null && derivedType != typeof(object)) + { + var currentType = derivedType.IsGenericType ? derivedType.GetGenericTypeDefinition() : derivedType; + if (parentType == currentType) { - var currentType = derivedType.IsGenericType ? derivedType.GetGenericTypeDefinition() : derivedType; - if (parentType == currentType) - { - return true; - } - derivedType = derivedType.BaseType; + return true; } - return false; + derivedType = derivedType.BaseType; } + return false; } } diff --git a/01-Core/Jinget.Core/ExtensionMethods/IServiceProviderExtensions.cs b/01-Core/Jinget.Core/ExtensionMethods/IServiceProviderExtensions.cs index 58510f1..e4d2fc9 100644 --- a/01-Core/Jinget.Core/ExtensionMethods/IServiceProviderExtensions.cs +++ b/01-Core/Jinget.Core/ExtensionMethods/IServiceProviderExtensions.cs @@ -1,19 +1,18 @@ using System; using Microsoft.Extensions.DependencyInjection; -namespace Jinget.Core.ExtensionMethods +namespace Jinget.Core.ExtensionMethods; + +public static class IServiceProviderExtensions { - public static class IServiceProviderExtensions + /// + /// Find a registered service inside the service collection and return the matching type, if found + /// + /// If there is no registered service of given type found, then will be thrown + public static T? GetJingetService(this IServiceProvider serviceProvider) where T : class { - /// - /// Find a registered service inside the service collection and return the matching type, if found - /// - /// If there is no registered service of given type found, then will be thrown - public static T? GetJingetService(this IServiceProvider serviceProvider) where T : class - { - if (serviceProvider.CreateScope().ServiceProvider.GetRequiredService(typeof(T)) is T service) - return service; - return null; - } + if (serviceProvider.CreateScope().ServiceProvider.GetRequiredService(typeof(T)) is T service) + return service; + return null; } } \ No newline at end of file diff --git a/01-Core/Jinget.Core/ExtensionMethods/ObjectExtensions.cs b/01-Core/Jinget.Core/ExtensionMethods/ObjectExtensions.cs index 9224321..00460b2 100644 --- a/01-Core/Jinget.Core/ExtensionMethods/ObjectExtensions.cs +++ b/01-Core/Jinget.Core/ExtensionMethods/ObjectExtensions.cs @@ -10,187 +10,186 @@ using Jinget.Core.ExtensionMethods.Reflection; using Newtonsoft.Json; -namespace Jinget.Core.ExtensionMethods +namespace Jinget.Core.ExtensionMethods; + +public static class ObjectExtensions { - public static class ObjectExtensions + public class Options(bool ignoreNull = true, bool ignoreExpressions = true) { - public class Options(bool ignoreNull = true, bool ignoreExpressions = true) - { - public bool IgnoreNull { get; set; } = ignoreNull; - public bool IgnoreExpressions { get; set; } = ignoreExpressions; - public bool IgnoreExpr2SQLPagings { get; set; } = true; - public bool IgnoreExpr2SQLOrderBys { get; set; } = true; - } - + public bool IgnoreNull { get; set; } = ignoreNull; + public bool IgnoreExpressions { get; set; } = ignoreExpressions; + public bool IgnoreExpr2SQLPagings { get; set; } = true; + public bool IgnoreExpr2SQLOrderBys { get; set; } = true; + } - /// - /// Check if given type is numeric or not - /// - public static bool IsNumericType(this object o) => Type.GetTypeCode(o.GetType()) switch - { - TypeCode.Byte or - TypeCode.SByte or - TypeCode.UInt16 or - TypeCode.UInt32 or - TypeCode.UInt64 or - TypeCode.Int16 or - TypeCode.Int32 or - TypeCode.Int64 or - TypeCode.Decimal or - TypeCode.Double or - TypeCode.Single => true, - _ => false, - }; - /// - /// Convert source object to dictionary(key=property name, value=property value) - /// - public static Dictionary ToDictionary(this object? source, Options? options = null) - { - if (source == null) - return []; - options ??= new Options(); + /// + /// Check if given type is numeric or not + /// + public static bool IsNumericType(this object o) => Type.GetTypeCode(o.GetType()) switch + { + TypeCode.Byte or + TypeCode.SByte or + TypeCode.UInt16 or + TypeCode.UInt32 or + TypeCode.UInt64 or + TypeCode.Int16 or + TypeCode.Int32 or + TypeCode.Int64 or + TypeCode.Decimal or + TypeCode.Double or + TypeCode.Single => true, + _ => false, + }; + + /// + /// Convert source object to dictionary(key=property name, value=property value) + /// + public static Dictionary ToDictionary(this object? source, Options? options = null) + { + if (source == null) + return []; + options ??= new Options(); - Dictionary result = []; + Dictionary result = []; - foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(source)) + foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(source)) + { + object? value = property.GetValue(source); + if (options.IgnoreNull && value == null) + continue; + else if (options.IgnoreExpressions && value is Expression) + continue; + else if (options.IgnoreExpr2SQLOrderBys && value is List) + continue; + else if (options.IgnoreExpr2SQLPagings && value is Paging) + continue; + string key = property.Name; + if (!result.ContainsKey(key)) { - object? value = property.GetValue(source); - if (options.IgnoreNull && value == null) - continue; - else if (options.IgnoreExpressions && value is Expression) - continue; - else if (options.IgnoreExpr2SQLOrderBys && value is List) - continue; - else if (options.IgnoreExpr2SQLPagings && value is Paging) - continue; - string key = property.Name; - if (!result.ContainsKey(key)) - { - result.Add(key, value); - } + result.Add(key, value); } - - return result; } - /// - /// Get the value of the given property - /// - public static object? GetValue(this object obj, string propertyName) - => obj.GetType().GetProperty(propertyName)?.GetValue(obj); + return result; + } - /// - /// Convert two unrelated objects to each other. - /// - public static T? ToType(this object obj, bool suppressError = false) where T : class - { - Type type = typeof(T); + /// + /// Get the value of the given property + /// + public static object? GetValue(this object obj, string propertyName) + => obj.GetType().GetProperty(propertyName)?.GetValue(obj); + + /// + /// Convert two unrelated objects to each other. + /// + public static T? ToType(this object obj, bool suppressError = false) where T : class + { + Type type = typeof(T); - var newObj = type.InvokeDefaultConstructor(); + var newObj = type.InvokeDefaultConstructor(); - if (obj == null) - return newObj; + if (obj == null) + return newObj; + + foreach (PropertyInfo pi in obj.GetType().GetProperties().Where(x => x.Name != "Empty" && x.CanWrite)) + { + var property = type.GetProperty(pi.Name); - foreach (PropertyInfo pi in obj.GetType().GetProperties().Where(x => x.Name != "Empty" && x.CanWrite)) + if (property == null) { - var property = type.GetProperty(pi.Name); + if (suppressError) + continue; + throw new JingetException($"Jinget Says: Model {typeof(T).Name} does not contain property with the name {pi.Name}", 1000); + } - if (property == null) - { - if (suppressError) - continue; - throw new JingetException($"Jinget Says: Model {typeof(T).Name} does not contain property with the name {pi.Name}", 1000); - } + if (pi.PropertyType.IsValueType || pi.PropertyType == typeof(string)) + { + property.SetValue(newObj, pi.GetValue(obj, null)); + } + else + { + var value = pi.GetValue(obj); - if (pi.PropertyType.IsValueType || pi.PropertyType == typeof(string)) + if (!property.PropertyType.IsGenericType || property.PropertyType.GetGenericTypeDefinition() != typeof(ICollection<>)) { - property.SetValue(newObj, pi.GetValue(obj, null)); + var referenceTypeValue = typeof(ObjectExtensions).Call( + name: nameof(ToType), + parameters: [value], + generics: property.PropertyType); + + property.SetValue(newObj, referenceTypeValue); } else { - var value = pi.GetValue(obj); + if (value == null) + continue; - if (!property.PropertyType.IsGenericType || property.PropertyType.GetGenericTypeDefinition() != typeof(ICollection<>)) + foreach (var + item in (IEnumerable)value) { var referenceTypeValue = typeof(ObjectExtensions).Call( name: nameof(ToType), - parameters: [value], - generics: property.PropertyType); + parameters: [item], + generics: property.PropertyType.GetGenericArguments()[0]); - property.SetValue(newObj, referenceTypeValue); - } - else - { - if (value == null) - continue; - - foreach (var - item in (IEnumerable)value) + if (property.PropertyType.GetGenericTypeDefinition() != typeof(ICollection<>)) + { + property.SetValue(newObj, referenceTypeValue); + } + else { - var referenceTypeValue = typeof(ObjectExtensions).Call( - name: nameof(ToType), - parameters: [item], - generics: property.PropertyType.GetGenericArguments()[0]); + var field = type.GetField($"<{property.Name}>k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic); - if (property.PropertyType.GetGenericTypeDefinition() != typeof(ICollection<>)) + if (field == null) { - property.SetValue(newObj, referenceTypeValue); - } - else - { - var field = type.GetField($"<{property.Name}>k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic); + field = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic) + .FirstOrDefault(x => string.Equals(x.Name, "_" + property.Name, + StringComparison.OrdinalIgnoreCase)); if (field == null) { - field = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic) - .FirstOrDefault(x => string.Equals(x.Name, "_" + property.Name, - StringComparison.OrdinalIgnoreCase)); - - if (field == null) - { - throw new JingetException($"Jinget Says: Unable to find backing field for Property '{property.Name}'", 1000); - } + throw new JingetException($"Jinget Says: Unable to find backing field for Property '{property.Name}'", 1000); } + } - if (typeof(IEnumerable).IsAssignableFrom(field.FieldType)) + if (typeof(IEnumerable).IsAssignableFrom(field.FieldType)) + { + if (field.GetValue(newObj) == null)//init the list { - if (field.GetValue(newObj) == null)//init the list - { - var instance = typeof(List<>) - .MakeGenericType(property.PropertyType.GetGenericArguments()[0]) - .GetConstructor(Type.EmptyTypes) - ?.Invoke(null); - - field.SetValue(newObj, instance); - } + var instance = typeof(List<>) + .MakeGenericType(property.PropertyType.GetGenericArguments()[0]) + .GetConstructor(Type.EmptyTypes) + ?.Invoke(null); - field.FieldType.GetMethod("Add")?.Invoke(field.GetValue(newObj), [referenceTypeValue]); - } - else - { - field.SetValue(newObj, referenceTypeValue); + field.SetValue(newObj, instance); } + + field.FieldType.GetMethod("Add")?.Invoke(field.GetValue(newObj), [referenceTypeValue]); + } + else + { + field.SetValue(newObj, referenceTypeValue); } } } } } - return newObj; } + return newObj; + } - /// - /// check if two objects(from same/different types) have exactly same structure and values - /// - public static bool HasSameValuesAs(this object source, object target) + /// + /// check if two objects(from same/different types) have exactly same structure and values + /// + public static bool HasSameValuesAs(this object source, object target) + { + var settings = new JsonSerializerSettings { - var settings = new JsonSerializerSettings - { - ReferenceLoopHandling = ReferenceLoopHandling.Ignore, - NullValueHandling = NullValueHandling.Ignore - }; + ReferenceLoopHandling = ReferenceLoopHandling.Ignore, + NullValueHandling = NullValueHandling.Ignore + }; - return JsonConvert.SerializeObject(source, settings) == JsonConvert.SerializeObject(target, settings); - } + return JsonConvert.SerializeObject(source, settings) == JsonConvert.SerializeObject(target, settings); } } \ No newline at end of file diff --git a/01-Core/Jinget.Core/ExtensionMethods/Reflection/AssemblyExtensions.cs b/01-Core/Jinget.Core/ExtensionMethods/Reflection/AssemblyExtensions.cs index 2d635d9..cb53caa 100644 --- a/01-Core/Jinget.Core/ExtensionMethods/Reflection/AssemblyExtensions.cs +++ b/01-Core/Jinget.Core/ExtensionMethods/Reflection/AssemblyExtensions.cs @@ -9,92 +9,91 @@ using Jinget.Core.Utilities; using Microsoft.AspNetCore.Authorization; -namespace Jinget.Core.ExtensionMethods.Reflection +namespace Jinget.Core.ExtensionMethods.Reflection; + +public static class AssemblyExtensions { - public static class AssemblyExtensions + public class AssemblyInfo { - public class AssemblyInfo - { - public string Summary { get; set; } = ""; - public string TypeName { get; set; } = ""; - public string AssemblyName { get; set; } = ""; - public string MethodName { get; set; } = ""; - public string Claim { get; set; } = ""; - public string ParentTitle { get; set; } = ""; - } + public string Summary { get; set; } = ""; + public string TypeName { get; set; } = ""; + public string AssemblyName { get; set; } = ""; + public string MethodName { get; set; } = ""; + public string Claim { get; set; } = ""; + public string ParentTitle { get; set; } = ""; + } - /// - /// Get all types which has as their parent in the given assembly - /// This Method is mainly used for gathering Controllers in a WebAPI or MVC project - /// - /// If types have any then its description will also parsed - public static List GetTypes(this Assembly assembly, Type resourceType, Type? methodSummaryAttribute = null, string normalizingPattern = @"Controller$") - { - methodSummaryAttribute ??= typeof(SummaryAttribute); + /// + /// Get all types which has as their parent in the given assembly + /// This Method is mainly used for gathering Controllers in a WebAPI or MVC project + /// + /// If types have any then its description will also parsed + public static List GetTypes(this Assembly assembly, Type resourceType, Type? methodSummaryAttribute = null, string normalizingPattern = @"Controller$") + { + methodSummaryAttribute ??= typeof(SummaryAttribute); #pragma warning disable CS8601 // Possible null reference assignment. #pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type. - return assembly.GetTypes() - .Where(resourceType.IsAssignableFrom) - .Select(x => new AssemblyInfo - { - Summary = ((SummaryAttribute)x.GetCustomAttributes().FirstOrDefault(a => a.GetType() == methodSummaryAttribute))?.Description.Trim(), - TypeName = Regex.Replace(x.Name, normalizingPattern, string.Empty, RegexOptions.IgnoreCase), //x.Name.Replace("Controller", string.Empty).Trim(), - AssemblyName = assembly.GetName().Name - }).ToList(); + return assembly.GetTypes() + .Where(resourceType.IsAssignableFrom) + .Select(x => new AssemblyInfo + { + Summary = ((SummaryAttribute)x.GetCustomAttributes().FirstOrDefault(a => a.GetType() == methodSummaryAttribute))?.Description.Trim(), + TypeName = Regex.Replace(x.Name, normalizingPattern, string.Empty, RegexOptions.IgnoreCase), //x.Name.Replace("Controller", string.Empty).Trim(), + AssemblyName = assembly.GetName().Name + }).ToList(); #pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type. #pragma warning restore CS8601 // Possible null reference assignment. - } + } - public static List GetTypes(this Assembly assembly, Expression>? filter = null) - { - return assembly.GetTypes() - .Where(c => c.IsClass && !c.IsGenericTypeDefinition && !c.IsAbstract && !c.IsNested) - .Where(filter?.Compile() ?? BooleanUtility.TrueCondition().Compile()).ToList(); - } + public static List GetTypes(this Assembly assembly, Expression>? filter = null) + { + return assembly.GetTypes() + .Where(c => c.IsClass && !c.IsGenericTypeDefinition && !c.IsAbstract && !c.IsNested) + .Where(filter?.Compile() ?? BooleanUtility.TrueCondition().Compile()).ToList(); + } - /// - /// Get all methods of th egiven resource type inside an assembly - /// - /// If true, then only methods with will be returned - public static List GetMethods(this Assembly executingAssembly, Type resourceType, Type? methodSummaryAttribute = null, bool onlyAuthorizedMethods = true) - { - methodSummaryAttribute ??= typeof(SummaryAttribute); + /// + /// Get all methods of th egiven resource type inside an assembly + /// + /// If true, then only methods with will be returned + public static List GetMethods(this Assembly executingAssembly, Type resourceType, Type? methodSummaryAttribute = null, bool onlyAuthorizedMethods = true) + { + methodSummaryAttribute ??= typeof(SummaryAttribute); - var allMethods = executingAssembly.GetTypes() - .Where(resourceType.IsAssignableFrom) - .SelectMany(type => - type.GetMethods(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public)) - .Where(m => !m.GetCustomAttributes(typeof(CompilerGeneratedAttribute), true).Any()); + var allMethods = executingAssembly.GetTypes() + .Where(resourceType.IsAssignableFrom) + .SelectMany(type => + type.GetMethods(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public)) + .Where(m => !m.GetCustomAttributes(typeof(CompilerGeneratedAttribute), true).Any()); #pragma warning disable CS8604 // Possible null reference argument. - var authorizedMethods = allMethods.Where(m => !onlyAuthorizedMethods || - (//methods marked as Authorize - m.GetCustomAttributes().Any(x => x.GetType() == typeof(AuthorizeAttribute)) || - //class marked as Authorize - m.DeclaringType.GetCustomAttributes().Any(x => x.GetType() == typeof(AuthorizeAttribute)))); + var authorizedMethods = allMethods.Where(m => !onlyAuthorizedMethods || + (//methods marked as Authorize + m.GetCustomAttributes().Any(x => x.GetType() == typeof(AuthorizeAttribute)) || + //class marked as Authorize + m.DeclaringType.GetCustomAttributes().Any(x => x.GetType() == typeof(AuthorizeAttribute)))); #pragma warning restore CS8604 // Possible null reference argument. #pragma warning disable CS8601 // Possible null reference assignment. #pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type. - return + return - [ - .. authorizedMethods.Select(x => new AssemblyInfo - { - Summary = ((SummaryAttribute)x.GetCustomAttributes() - .FirstOrDefault(a => a.GetType() == methodSummaryAttribute))?.Description.Trim(), - TypeName = x.DeclaringType?.Name.Replace("Controller", string.Empty).Trim(), - AssemblyName = executingAssembly.GetName().Name, - MethodName = x.Name.Trim(), - Claim = ((ClaimAttribute)x.GetCustomAttributes() - .FirstOrDefault(a => a.GetType() == typeof(ClaimAttribute)))?.Title, - ParentTitle = ((SummaryAttribute)x.DeclaringType?.GetCustomAttributes() - .FirstOrDefault(a => a.GetType() == methodSummaryAttribute))?.Description - }) - .OrderBy(x => x.Summary).ThenBy(x => x.MethodName).ThenBy(x => x.Claim), - ]; + [ + .. authorizedMethods.Select(x => new AssemblyInfo + { + Summary = ((SummaryAttribute)x.GetCustomAttributes() + .FirstOrDefault(a => a.GetType() == methodSummaryAttribute))?.Description.Trim(), + TypeName = x.DeclaringType?.Name.Replace("Controller", string.Empty).Trim(), + AssemblyName = executingAssembly.GetName().Name, + MethodName = x.Name.Trim(), + Claim = ((ClaimAttribute)x.GetCustomAttributes() + .FirstOrDefault(a => a.GetType() == typeof(ClaimAttribute)))?.Title, + ParentTitle = ((SummaryAttribute)x.DeclaringType?.GetCustomAttributes() + .FirstOrDefault(a => a.GetType() == methodSummaryAttribute))?.Description + }) + .OrderBy(x => x.Summary).ThenBy(x => x.MethodName).ThenBy(x => x.Claim), + ]; #pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type. #pragma warning restore CS8601 // Possible null reference assignment. - } } } diff --git a/01-Core/Jinget.Core/ExtensionMethods/Reflection/ConstructorExtensions.cs b/01-Core/Jinget.Core/ExtensionMethods/Reflection/ConstructorExtensions.cs index 053776d..c6701d1 100644 --- a/01-Core/Jinget.Core/ExtensionMethods/Reflection/ConstructorExtensions.cs +++ b/01-Core/Jinget.Core/ExtensionMethods/Reflection/ConstructorExtensions.cs @@ -1,16 +1,15 @@ using System; using System.Reflection; -namespace Jinget.Core.ExtensionMethods.Reflection +namespace Jinget.Core.ExtensionMethods.Reflection; + +public static class ConstructorExtensions { - public static class ConstructorExtensions - { - /// - /// Get parameterless constructor - /// - public static ConstructorInfo? GetDefaultConstructor(this Type type) => - type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); + /// + /// Get parameterless constructor + /// + public static ConstructorInfo? GetDefaultConstructor(this Type type) => + type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); - public static Tout? InvokeDefaultConstructor(this Type type) where Tout : class => type.GetDefaultConstructor()?.Invoke(null) as Tout; - } + public static Tout? InvokeDefaultConstructor(this Type type) where Tout : class => type.GetDefaultConstructor()?.Invoke(null) as Tout; } diff --git a/01-Core/Jinget.Core/ExtensionMethods/Reflection/MethodInfoExtensions.cs b/01-Core/Jinget.Core/ExtensionMethods/Reflection/MethodInfoExtensions.cs index 0ec7e88..46f2666 100644 --- a/01-Core/Jinget.Core/ExtensionMethods/Reflection/MethodInfoExtensions.cs +++ b/01-Core/Jinget.Core/ExtensionMethods/Reflection/MethodInfoExtensions.cs @@ -1,30 +1,29 @@ using Microsoft.VisualStudio.Threading; using System.Reflection; -namespace Jinget.Core.ExtensionMethods.Reflection +namespace Jinget.Core.ExtensionMethods.Reflection; + +public static class MethodInfoExtensions { - public static class MethodInfoExtensions - { - /// - /// Dynamically invoke async method - /// + /// + /// Dynamically invoke async method + /// #pragma warning disable VSTHRD200 // Use "Async" suffix for async methods - public static object InvokeAsync(this MethodInfo method, object obj, params object[] parameters) + public static object InvokeAsync(this MethodInfo method, object obj, params object[] parameters) #pragma warning restore VSTHRD200 // Use "Async" suffix for async methods + { + using var taskContext = new JoinableTaskContext(); + var joinableTaskFactory = new JoinableTaskFactory(taskContext); + return joinableTaskFactory.Run(async () => { - using var taskContext = new JoinableTaskContext(); - var joinableTaskFactory = new JoinableTaskFactory(taskContext); - return joinableTaskFactory.Run(async () => - { #pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type. - dynamic awaitable = method.Invoke(obj, parameters); + dynamic awaitable = method.Invoke(obj, parameters); #pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type. - await awaitable; + await awaitable; #pragma warning disable CS8602 // Dereference of a possibly null reference. - return awaitable.GetAwaiter().GetResult(); + return awaitable.GetAwaiter().GetResult(); #pragma warning restore CS8602 // Dereference of a possibly null reference. - }); - } + }); } } diff --git a/01-Core/Jinget.Core/ExtensionMethods/Reflection/PropertiesExtensions.cs b/01-Core/Jinget.Core/ExtensionMethods/Reflection/PropertiesExtensions.cs index f0162c9..07e40ae 100644 --- a/01-Core/Jinget.Core/ExtensionMethods/Reflection/PropertiesExtensions.cs +++ b/01-Core/Jinget.Core/ExtensionMethods/Reflection/PropertiesExtensions.cs @@ -3,80 +3,79 @@ using System.Linq; using System.Reflection; -namespace Jinget.Core.ExtensionMethods.Reflection +namespace Jinget.Core.ExtensionMethods.Reflection; + +public static class PropertiesExtensions { - public static class PropertiesExtensions - { - /// - /// Check if given type is a nullable type or not - /// - public static bool IsNullable(this Type type) => type != null && type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>); + /// + /// Check if given type is a nullable type or not + /// + public static bool IsNullable(this Type type) => type != null && type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>); - /// - /// Get all writable primitive types - /// - public static Dictionary GetWritableProperties(this Type t) - { - var properties = from prop in GetDeclaredProperties(t) - where prop.CanWrite - where IsSimpleType(prop.PropertyType) - select prop; - return properties.ToDictionary(x => x.Name); - } + /// + /// Get all writable primitive types + /// + public static Dictionary GetWritableProperties(this Type t) + { + var properties = from prop in GetDeclaredProperties(t) + where prop.CanWrite + where IsSimpleType(prop.PropertyType) + select prop; + return properties.ToDictionary(x => x.Name); + } - private static IEnumerable GetDeclaredProperties(Type t) => + private static IEnumerable GetDeclaredProperties(Type t) => #if NET45 - return t.GetRuntimeProperties(); + return t.GetRuntimeProperties(); #else - t.GetTypeInfo().DeclaredProperties; + t.GetTypeInfo().DeclaredProperties; #endif - private static bool IsSimpleType(Type t) + private static bool IsSimpleType(Type t) + { + while (true) { - while (true) + if (IsPrimitive(t)) + { + return true; + } + if (t == typeof(decimal)) { - if (IsPrimitive(t)) - { - return true; - } - if (t == typeof(decimal)) - { - return true; - } - if (t == typeof(string)) - { - return true; - } - if (t == typeof(Guid)) - { - return true; - } - if (t == typeof(DateTime)) - { - return true; - } - if (t.BaseType == typeof(Enum)) - { - return true; - } - if (t == typeof(byte[])) - { - return true; - } - t = Nullable.GetUnderlyingType(t); - if (t is null) - { - break; - } + return true; + } + if (t == typeof(string)) + { + return true; + } + if (t == typeof(Guid)) + { + return true; + } + if (t == typeof(DateTime)) + { + return true; + } + if (t.BaseType == typeof(Enum)) + { + return true; + } + if (t == typeof(byte[])) + { + return true; + } + t = Nullable.GetUnderlyingType(t); + if (t is null) + { + break; } - return false; } + return false; + } - private static bool IsPrimitive(Type t) => + private static bool IsPrimitive(Type t) => #if NET45 - return t.IsPrimitive; + return t.IsPrimitive; #else - t.GetTypeInfo().IsPrimitive; + t.GetTypeInfo().IsPrimitive; #endif - } } \ No newline at end of file diff --git a/01-Core/Jinget.Core/ExtensionMethods/Reflection/TypeExtensions.cs b/01-Core/Jinget.Core/ExtensionMethods/Reflection/TypeExtensions.cs index 69508c7..6608ecd 100644 --- a/01-Core/Jinget.Core/ExtensionMethods/Reflection/TypeExtensions.cs +++ b/01-Core/Jinget.Core/ExtensionMethods/Reflection/TypeExtensions.cs @@ -7,122 +7,121 @@ using System.Reflection; using System.Runtime.CompilerServices; -namespace Jinget.Core.ExtensionMethods.Reflection +namespace Jinget.Core.ExtensionMethods.Reflection; + +public static class TypeExtensions { - public static class TypeExtensions + /// + /// Check if given type is an anonymous type or not + /// + /// + /// + /// + /// + public static bool IsAnonymousType(this Type type) { - /// - /// Check if given type is an anonymous type or not - /// - /// - /// - /// - /// - public static bool IsAnonymousType(this Type type) - { - var markedWithAttribute = type.GetCustomAttributes(typeof(CompilerGeneratedAttribute), inherit: false).Any(); - var typeName = type.Name; + var markedWithAttribute = type.GetCustomAttributes(typeof(CompilerGeneratedAttribute), inherit: false).Any(); + var typeName = type.Name; - return markedWithAttribute - && (typeName.StartsWith("<>") || type.Name.StartsWith("VB$")) - && typeName.Contains("AnonymousType"); - } + return markedWithAttribute + && (typeName.StartsWith("<>") || type.Name.StartsWith("VB$")) + && typeName.Contains("AnonymousType"); + } - /// - /// Call method dynamically at runtime. - /// This overload used to call the public instance method - /// - public static object? Call(this Type type, object? caller, string name, object?[] parameters, params Type[] generics) - => type.Call(caller, name, BindingFlags.Public | BindingFlags.Instance, parameters, generics); + /// + /// Call method dynamically at runtime. + /// This overload used to call the public instance method + /// + public static object? Call(this Type type, object? caller, string name, object?[] parameters, params Type[] generics) + => type.Call(caller, name, BindingFlags.Public | BindingFlags.Instance, parameters, generics); - /// - /// Call method dynamically at runtime. - /// This overload used to call the public static method - /// - public static object? Call(this Type type, string name, object?[] parameters, params Type[] generics) - => type.Call(null, name, BindingFlags.Public | BindingFlags.Static, parameters, generics); + /// + /// Call method dynamically at runtime. + /// This overload used to call the public static method + /// + public static object? Call(this Type type, string name, object?[] parameters, params Type[] generics) + => type.Call(null, name, BindingFlags.Public | BindingFlags.Static, parameters, generics); - /// - /// Call method dynamically at runtime. - /// - /// object used to call the method. if the method is static, then set this as `null` - /// method name - /// - /// parameters used to pass to the method - /// if the mthod is a generic method, then generic types should be specified - /// Invoke the method and return the method's return value - public static object? Call(this Type type, object? caller, string name, BindingFlags bindingFlags, object?[] parameters, params Type[] generics) + /// + /// Call method dynamically at runtime. + /// + /// object used to call the method. if the method is static, then set this as `null` + /// method name + /// + /// parameters used to pass to the method + /// if the mthod is a generic method, then generic types should be specified + /// Invoke the method and return the method's return value + public static object? Call(this Type type, object? caller, string name, BindingFlags bindingFlags, object?[] parameters, params Type[] generics) + { + var method = type.GetMethod(name, bindingFlags); + if (method == null) + return null; + if (generics != null) + method = method.MakeGenericMethod(generics); + try { - var method = type.GetMethod(name, bindingFlags); - if (method == null) - return null; - if (generics != null) - method = method.MakeGenericMethod(generics); - try - { - return method.Invoke(caller, parameters); - } - catch (Exception ex) when (ex.InnerException is JingetException) - { - throw new JingetException("Jinget Says: " + ex.InnerException.Message, ex.InnerException); - } + return method.Invoke(caller, parameters); } - - /// - /// Get reference-type properties of the given type. - /// By default string properties will be ignored. - /// - public static List GetReferenceTypeProperties( - this Type type, - BindingFlags bindingFlags, - Expression>? filter = null, - bool includeStringTypes = false) + catch (Exception ex) when (ex.InnerException is JingetException) { - Expression> defaultFilter = x => - !x.PropertyType.IsValueType && (includeStringTypes == true || x.PropertyType != typeof(string)); + throw new JingetException("Jinget Says: " + ex.InnerException.Message, ex.InnerException); + } + } - if (filter != null) - return type.GetProperties(bindingFlags) - .Where(filter.AndAlso(defaultFilter).Compile()) - .ToList(); - else - return type.GetProperties(bindingFlags) - .Where(defaultFilter.Compile()) + /// + /// Get reference-type properties of the given type. + /// By default string properties will be ignored. + /// + public static List GetReferenceTypeProperties( + this Type type, + BindingFlags bindingFlags, + Expression>? filter = null, + bool includeStringTypes = false) + { + Expression> defaultFilter = x => + !x.PropertyType.IsValueType && (includeStringTypes == true || x.PropertyType != typeof(string)); + + if (filter != null) + return type.GetProperties(bindingFlags) + .Where(filter.AndAlso(defaultFilter).Compile()) .ToList(); - } + else + return type.GetProperties(bindingFlags) + .Where(defaultFilter.Compile()) + .ToList(); + } - /// - /// Get reference-type properties of the given type. - /// By default string properties will be ignored. - /// - public static List GetReferenceTypeProperties( - this Type type, - Expression>? filter = null, - bool includeStringTypes = false) - => type.GetReferenceTypeProperties( - BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public, filter, includeStringTypes); + /// + /// Get reference-type properties of the given type. + /// By default string properties will be ignored. + /// + public static List GetReferenceTypeProperties( + this Type type, + Expression>? filter = null, + bool includeStringTypes = false) + => type.GetReferenceTypeProperties( + BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public, filter, includeStringTypes); - /// - /// Get the default value for the calling type - /// - public static object GetDefaultValue(this Type type) - { - // Validate parameters. - if (type == null) - ArgumentNullException.ThrowIfNull(type, nameof(type)); + /// + /// Get the default value for the calling type + /// + public static object GetDefaultValue(this Type type) + { + // Validate parameters. + if (type == null) + ArgumentNullException.ThrowIfNull(type, nameof(type)); - // We want an Func which returns the default. - // Create that expression here. - Expression> e = Expression.Lambda>( - // Have to convert to object. - Expression.Convert( - // The default value, always get what the *code* tells us. - Expression.Default(type), typeof(object) - ) - ); + // We want an Func which returns the default. + // Create that expression here. + Expression> e = Expression.Lambda>( + // Have to convert to object. + Expression.Convert( + // The default value, always get what the *code* tells us. + Expression.Default(type), typeof(object) + ) + ); - // Compile and return the value. - return e.Compile()(); - } + // Compile and return the value. + return e.Compile()(); } } diff --git a/01-Core/Jinget.Core/ExtensionMethods/StringExtensions.cs b/01-Core/Jinget.Core/ExtensionMethods/StringExtensions.cs index f085db1..291fcdc 100644 --- a/01-Core/Jinget.Core/ExtensionMethods/StringExtensions.cs +++ b/01-Core/Jinget.Core/ExtensionMethods/StringExtensions.cs @@ -1,38 +1,37 @@ using System.Linq; -namespace Jinget.Core.ExtensionMethods +namespace Jinget.Core.ExtensionMethods; + +public static class StringExtensions { - public static class StringExtensions + static readonly char[] ArabicYeChar = [(char)1610, 'ي']; + const char PersianYeChar = (char)1740; + + static readonly char[] ArabicKeChar = [(char)1603, 'ك']; + const char PersianKeChar = (char)1705; + + /// + /// Replace Arabic ي and ك characters with their Farsi equalivants + /// + public static string ApplyCorrectYeKe(this string? data) + { + if (string.IsNullOrWhiteSpace(data)) + return string.Empty; + + data = ArabicYeChar.Aggregate(data, (current, ye) => current.Replace(ye, PersianYeChar).Trim()); + + data = ArabicKeChar.Aggregate(data, (current, ke) => current.Replace(ke, PersianKeChar).Trim()); + + return data; + } + + /// + /// Convert string to camelCase string + /// + public static string ToCamelCase(this string value) { - static readonly char[] ArabicYeChar = [(char)1610, 'ي']; - const char PersianYeChar = (char)1740; - - static readonly char[] ArabicKeChar = [(char)1603, 'ك']; - const char PersianKeChar = (char)1705; - - /// - /// Replace Arabic ي and ك characters with their Farsi equalivants - /// - public static string ApplyCorrectYeKe(this string? data) - { - if (string.IsNullOrWhiteSpace(data)) - return string.Empty; - - data = ArabicYeChar.Aggregate(data, (current, ye) => current.Replace(ye, PersianYeChar).Trim()); - - data = ArabicKeChar.Aggregate(data, (current, ke) => current.Replace(ke, PersianKeChar).Trim()); - - return data; - } - - /// - /// Convert string to camelCase string - /// - public static string ToCamelCase(this string value) - { - if (string.IsNullOrEmpty(value)) - return value; - return char.ToLowerInvariant(value[0]) + value[1..]; - } + if (string.IsNullOrEmpty(value)) + return value; + return char.ToLowerInvariant(value[0]) + value[1..]; } } \ No newline at end of file diff --git a/01-Core/Jinget.Core/Filters/SwaggerExcludeModelFilter.cs b/01-Core/Jinget.Core/Filters/SwaggerExcludeModelFilter.cs index ef5f841..8874e20 100644 --- a/01-Core/Jinget.Core/Filters/SwaggerExcludeModelFilter.cs +++ b/01-Core/Jinget.Core/Filters/SwaggerExcludeModelFilter.cs @@ -6,48 +6,47 @@ using System.Linq; using System.Reflection; -namespace Jinget.Core.Filters +namespace Jinget.Core.Filters; + +public class SwaggerExcludeTypeFilter : IDocumentFilter { - public class SwaggerExcludeTypeFilter : IDocumentFilter + /// + /// When applied on a model, + /// then that model will be ignored while working with swagger + /// + public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) { - /// - /// When applied on a model, - /// then that model will be ignored while working with swagger - /// - public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) + foreach (var assembly in + AppDomain.CurrentDomain.GetAssemblies() + .Where(ass => ass.GetTypes() + .Any(type => type + .GetCustomAttributes(typeof(SwaggerExcludeAttribute), true) + .Length > 0))) { - foreach (var assembly in - AppDomain.CurrentDomain.GetAssemblies() - .Where(ass => ass.GetTypes() - .Any(type => type - .GetCustomAttributes(typeof(SwaggerExcludeAttribute), true) - .Length > 0))) + // Get all models that are decorated with SwaggerExcludeAttribute + // This will only work for models that are under current Assembly + var excludedTypes = GetTypesWithExcludeAttribute(assembly); + // Loop through them + foreach (var _type in excludedTypes) { - // Get all models that are decorated with SwaggerExcludeAttribute - // This will only work for models that are under current Assembly - var excludedTypes = GetTypesWithExcludeAttribute(assembly); - // Loop through them - foreach (var _type in excludedTypes) + // Check if that type exists in SchemaRepository + if (context.SchemaRepository.TryLookupByType(_type, out _)) { - // Check if that type exists in SchemaRepository - if (context.SchemaRepository.TryLookupByType(_type, out _)) + // If the type exists in SchemaRepository, check if name exists in the dictionary + if (swaggerDoc.Components.Schemas.ContainsKey(_type.Name)) { - // If the type exists in SchemaRepository, check if name exists in the dictionary - if (swaggerDoc.Components.Schemas.ContainsKey(_type.Name)) - { - // Remove the schema - swaggerDoc.Components.Schemas.Remove(_type.Name); - } + // Remove the schema + swaggerDoc.Components.Schemas.Remove(_type.Name); } } } } + } - // Get all types in assembly that contains SwaggerExcludeAttribute - public static IEnumerable GetTypesWithExcludeAttribute(Assembly assembly) - { - return assembly.GetTypes() - .Where(type => type.GetCustomAttributes(typeof(SwaggerExcludeAttribute), true).Length > 0); - } + // Get all types in assembly that contains SwaggerExcludeAttribute + public static IEnumerable GetTypesWithExcludeAttribute(Assembly assembly) + { + return assembly.GetTypes() + .Where(type => type.GetCustomAttributes(typeof(SwaggerExcludeAttribute), true).Length > 0); } } diff --git a/01-Core/Jinget.Core/Filters/SwaggerExcludePropertyFilter.cs b/01-Core/Jinget.Core/Filters/SwaggerExcludePropertyFilter.cs index dbdb07a..dde5627 100644 --- a/01-Core/Jinget.Core/Filters/SwaggerExcludePropertyFilter.cs +++ b/01-Core/Jinget.Core/Filters/SwaggerExcludePropertyFilter.cs @@ -5,28 +5,27 @@ using System.Linq; using System.Reflection; -namespace Jinget.Core.Filters +namespace Jinget.Core.Filters; + +public class SwaggerExcludePropertyFilter : ISchemaFilter { - public class SwaggerExcludePropertyFilter : ISchemaFilter + /// + /// When applied on a proprty in model, + /// then that property will be ignored while working with swagger + /// + public void Apply(OpenApiSchema schema, SchemaFilterContext context) { - /// - /// When applied on a proprty in model, - /// then that property will be ignored while working with swagger - /// - public void Apply(OpenApiSchema schema, SchemaFilterContext context) - { - if (schema.Properties.Count == 0) - return; + if (schema.Properties.Count == 0) + return; - var excludedList = context.Type.GetProperties() - .Where(t => t.GetCustomAttribute() != null) - .Select(m => m.Name.ToCamelCase()); + var excludedList = context.Type.GetProperties() + .Where(t => t.GetCustomAttribute() != null) + .Select(m => m.Name.ToCamelCase()); - foreach (var excludedName in excludedList) - { - if (schema.Properties.ContainsKey(excludedName)) - schema.Properties.Remove(excludedName); - } + foreach (var excludedName in excludedList) + { + if (schema.Properties.ContainsKey(excludedName)) + schema.Properties.Remove(excludedName); } } } diff --git a/01-Core/Jinget.Core/GlobalUsings.cs b/01-Core/Jinget.Core/GlobalUsings.cs new file mode 100644 index 0000000..f41d5fe --- /dev/null +++ b/01-Core/Jinget.Core/GlobalUsings.cs @@ -0,0 +1,24 @@ +global using System.Xml.Serialization; +global using System; +global using Microsoft.AspNetCore.Authorization; +global using System.CodeDom; +global using System.CodeDom.Compiler; +global using System.Collections.Generic; +global using System.IO; +global using System.Linq; +global using System.Reflection; +global using System.Runtime.CompilerServices; +global using System.Text; +global using Microsoft.CodeAnalysis; +global using Microsoft.CodeAnalysis.CSharp; +global using Microsoft.CodeAnalysis.Text; +global using Microsoft.CSharp; +global using Jinget.Core.ExpressionToSql.Internal; +global using System.Linq.Expressions; +global using System.Security.Principal; +global using System.Threading.Tasks; +global using Jinget.Core.Enumerations; +global using System.Collections; +global using System.Data; +global using Dapper; +global using Jinget.Core.ExtensionMethods.Enums; \ No newline at end of file diff --git a/01-Core/Jinget.Core/IOptionTypes/ConnectionString/ApplicationDBConnectionString.cs b/01-Core/Jinget.Core/IOptionTypes/ConnectionString/ApplicationDBConnectionString.cs index 6f81ea9..ffe919a 100644 --- a/01-Core/Jinget.Core/IOptionTypes/ConnectionString/ApplicationDBConnectionString.cs +++ b/01-Core/Jinget.Core/IOptionTypes/ConnectionString/ApplicationDBConnectionString.cs @@ -1,8 +1,7 @@ -namespace Jinget.Core.IOptionTypes.ConnectionString -{ - /// - /// If you need to use multiple databases(principal db, log db, app db etc) - /// then you can define a class for each type and make it inherit from `BaseDBConnectionString` - /// - public class ApplicationDBConnectionString : BaseDBConnectionString { } -} +namespace Jinget.Core.IOptionTypes.ConnectionString; + +/// +/// If you need to use multiple databases(principal db, log db, app db etc) +/// then you can define a class for each type and make it inherit from `BaseDBConnectionString` +/// +public class ApplicationDBConnectionString : BaseDBConnectionString { } diff --git a/01-Core/Jinget.Core/IOptionTypes/ConnectionString/BaseDBConnectionString.cs b/01-Core/Jinget.Core/IOptionTypes/ConnectionString/BaseDBConnectionString.cs index 2635761..b885196 100644 --- a/01-Core/Jinget.Core/IOptionTypes/ConnectionString/BaseDBConnectionString.cs +++ b/01-Core/Jinget.Core/IOptionTypes/ConnectionString/BaseDBConnectionString.cs @@ -1,20 +1,19 @@ -namespace Jinget.Core.IOptionTypes.ConnectionString -{ +namespace Jinget.Core.IOptionTypes.ConnectionString; + #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - public class BaseDBConnectionString - { - /// - /// queries using this connection string can change data - /// - public string CommandDatabase { get; set; } +public class BaseDBConnectionString +{ + /// + /// queries using this connection string can change data + /// + public string CommandDatabase { get; set; } - /// - /// queries using this connection string should not change data - /// If Always On is used, then `ApplicationIntent=ReadOnly` can be added to this connection string - /// - public string QueryDatabase { get; set; } - } + /// + /// queries using this connection string should not change data + /// If Always On is used, then `ApplicationIntent=ReadOnly` can be added to this connection string + /// + public string QueryDatabase { get; set; } +} #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. -} diff --git a/01-Core/Jinget.Core/IOptionTypes/ConnectionString/LogDBConnectionString.cs b/01-Core/Jinget.Core/IOptionTypes/ConnectionString/LogDBConnectionString.cs index 345bd69..f95024f 100644 --- a/01-Core/Jinget.Core/IOptionTypes/ConnectionString/LogDBConnectionString.cs +++ b/01-Core/Jinget.Core/IOptionTypes/ConnectionString/LogDBConnectionString.cs @@ -1,11 +1,10 @@ -namespace Jinget.Core.IOptionTypes.ConnectionString +namespace Jinget.Core.IOptionTypes.ConnectionString; + +/// +/// If you need to use multiple databases(principal db, log db, app db etc) +/// then you can define a class for each type and make it inherit from `BaseDBConnectionString` +/// +public class LogDBConnectionString: BaseDBConnectionString { - /// - /// If you need to use multiple databases(principal db, log db, app db etc) - /// then you can define a class for each type and make it inherit from `BaseDBConnectionString` - /// - public class LogDBConnectionString: BaseDBConnectionString - { - - } + } diff --git a/01-Core/Jinget.Core/IOptionTypes/ConnectionString/PrincipalDBConnectionString.cs b/01-Core/Jinget.Core/IOptionTypes/ConnectionString/PrincipalDBConnectionString.cs index 718db46..90fd8bb 100644 --- a/01-Core/Jinget.Core/IOptionTypes/ConnectionString/PrincipalDBConnectionString.cs +++ b/01-Core/Jinget.Core/IOptionTypes/ConnectionString/PrincipalDBConnectionString.cs @@ -1,10 +1,9 @@ -namespace Jinget.Core.IOptionTypes.ConnectionString +namespace Jinget.Core.IOptionTypes.ConnectionString; + +/// +/// If you need to use multiple databases(principal db, log db, app db etc) +/// then you can define a class for each type and make it inherit from `BaseDBConnectionString` +/// +public class PrincipalDBConnectionString: BaseDBConnectionString { - /// - /// If you need to use multiple databases(principal db, log db, app db etc) - /// then you can define a class for each type and make it inherit from `BaseDBConnectionString` - /// - public class PrincipalDBConnectionString: BaseDBConnectionString - { - } } diff --git a/01-Core/Jinget.Core/IOptionTypes/Log/BlackListHeader.cs b/01-Core/Jinget.Core/IOptionTypes/Log/BlackListHeader.cs index ad88317..445fc8f 100644 --- a/01-Core/Jinget.Core/IOptionTypes/Log/BlackListHeader.cs +++ b/01-Core/Jinget.Core/IOptionTypes/Log/BlackListHeader.cs @@ -1,9 +1,9 @@ -namespace Jinget.Core.IOptionTypes.Log -{ +namespace Jinget.Core.IOptionTypes.Log; + #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - public class BlackListHeader - { - public string[] Headers { get; set; } - } -#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. +public class BlackListHeader +{ + public string[] Headers { get; set; } } +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + diff --git a/01-Core/Jinget.Core/IOptionTypes/Log/WhiteListHeader.cs b/01-Core/Jinget.Core/IOptionTypes/Log/WhiteListHeader.cs index d5500e6..f62d34e 100644 --- a/01-Core/Jinget.Core/IOptionTypes/Log/WhiteListHeader.cs +++ b/01-Core/Jinget.Core/IOptionTypes/Log/WhiteListHeader.cs @@ -1,9 +1,9 @@ -namespace Jinget.Core.IOptionTypes.Log -{ +namespace Jinget.Core.IOptionTypes.Log; + #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - public class WhiteListHeader - { - public string[] Headers { get; set; } - } -#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. +public class WhiteListHeader +{ + public string[] Headers { get; set; } } +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + diff --git a/01-Core/Jinget.Core/Jinget.Core.csproj b/01-Core/Jinget.Core/Jinget.Core.csproj index 6394ccf..dc78f5d 100644 --- a/01-Core/Jinget.Core/Jinget.Core.csproj +++ b/01-Core/Jinget.Core/Jinget.Core.csproj @@ -16,7 +16,6 @@ jinget, extension, xml, expression, utility, codedom - diff --git a/01-Core/Jinget.Core/Operators/GenericEqualityOperator.cs b/01-Core/Jinget.Core/Operators/GenericEqualityOperator.cs index ea8033d..2160332 100644 --- a/01-Core/Jinget.Core/Operators/GenericEqualityOperator.cs +++ b/01-Core/Jinget.Core/Operators/GenericEqualityOperator.cs @@ -1,12 +1,11 @@ using System.Collections.Generic; -namespace Jinget.Core.Operators +namespace Jinget.Core.Operators; + +public static class GenericEqualityOperator { - public static class GenericEqualityOperator - { - /// - /// Check whether two generic type properties are equal or not. - /// - public static bool AreEqual(T t1, T t2) => EqualityComparer.Default.Equals(t1, t2); - } + /// + /// Check whether two generic type properties are equal or not. + /// + public static bool AreEqual(T t1, T t2) => EqualityComparer.Default.Equals(t1, t2); } diff --git a/01-Core/Jinget.Core/ResponseResults/JingetForbiddenResult.cs b/01-Core/Jinget.Core/ResponseResults/JingetForbiddenResult.cs index b87140c..6849727 100644 --- a/01-Core/Jinget.Core/ResponseResults/JingetForbiddenResult.cs +++ b/01-Core/Jinget.Core/ResponseResults/JingetForbiddenResult.cs @@ -2,11 +2,10 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -namespace Jinget.Core.ResponseResults +namespace Jinget.Core.ResponseResults; + +public class JingetForbiddenResult : JsonResult { - public class JingetForbiddenResult : JsonResult - { - public JingetForbiddenResult(string message) : base(new CustomMessageModel(message)) => - StatusCode = StatusCodes.Status403Forbidden; - } + public JingetForbiddenResult(string message) : base(new CustomMessageModel(message)) => + StatusCode = StatusCodes.Status403Forbidden; } \ No newline at end of file diff --git a/01-Core/Jinget.Core/ResponseResults/JingetUnauthorizedResult.cs b/01-Core/Jinget.Core/ResponseResults/JingetUnauthorizedResult.cs index 86a1373..b1e074a 100644 --- a/01-Core/Jinget.Core/ResponseResults/JingetUnauthorizedResult.cs +++ b/01-Core/Jinget.Core/ResponseResults/JingetUnauthorizedResult.cs @@ -2,11 +2,10 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -namespace Jinget.Core.ResponseResults +namespace Jinget.Core.ResponseResults; + +public class JingetUnauthorizedResult : JsonResult { - public class JingetUnauthorizedResult : JsonResult - { - public JingetUnauthorizedResult(string message) : base(new CustomMessageModel(message)) => - StatusCode = StatusCodes.Status401Unauthorized; - } + public JingetUnauthorizedResult(string message) : base(new CustomMessageModel(message)) => + StatusCode = StatusCodes.Status401Unauthorized; } \ No newline at end of file diff --git a/01-Core/Jinget.Core/ResponseResults/Messages/CustomMessageModel.cs b/01-Core/Jinget.Core/ResponseResults/Messages/CustomMessageModel.cs index 06631fa..8ae0d14 100644 --- a/01-Core/Jinget.Core/ResponseResults/Messages/CustomMessageModel.cs +++ b/01-Core/Jinget.Core/ResponseResults/Messages/CustomMessageModel.cs @@ -1,7 +1,6 @@ -namespace Jinget.Core.ResponseResults.Messages +namespace Jinget.Core.ResponseResults.Messages; + +public class CustomMessageModel(string message) { - public class CustomMessageModel(string message) - { - public string Error { get; } = message; - } + public string Error { get; } = message; } \ No newline at end of file diff --git a/01-Core/Jinget.Core/Security/AES/AESManager.cs b/01-Core/Jinget.Core/Security/AES/AESManager.cs index 89ff780..fa73d6d 100644 --- a/01-Core/Jinget.Core/Security/AES/AESManager.cs +++ b/01-Core/Jinget.Core/Security/AES/AESManager.cs @@ -4,112 +4,111 @@ using System.Text; using Jinget.Core.Exceptions; -namespace Jinget.Core.Security.AES +namespace Jinget.Core.Security.AES; + +/// +/// Encrypt & Decrypt string using System.Security.Cryptography.RijndaelManaged algorithm +/// +public static class AESManager { /// - /// Encrypt & Decrypt string using System.Security.Cryptography.RijndaelManaged algorithm + /// Encrypts the specified plain text. /// - public static class AESManager + /// Jinget Says: {nameof(plainText)} cannot be null or empty - 1000 + /// Jinget Says: {nameof(key)} cannot be null or empty - 1000 + /// Jinget Says: {nameof(iv)} cannot be null or empty - 1000 + public static string Encrypt(string plainText, string key, string iv) { - /// - /// Encrypts the specified plain text. - /// - /// Jinget Says: {nameof(plainText)} cannot be null or empty - 1000 - /// Jinget Says: {nameof(key)} cannot be null or empty - 1000 - /// Jinget Says: {nameof(iv)} cannot be null or empty - 1000 - public static string Encrypt(string plainText, string key, string iv) - { - var keyBytes = Encoding.UTF8.GetBytes(key); - var ivBytes = Encoding.UTF8.GetBytes(iv); + var keyBytes = Encoding.UTF8.GetBytes(key); + var ivBytes = Encoding.UTF8.GetBytes(iv); - if (plainText == null || plainText.Length <= 0) - throw new JingetException($"Jinget Says: {nameof(plainText)} cannot be null or empty", 1000); - if (keyBytes == null || keyBytes.Length <= 0 || key.Length < 32) - throw new JingetException($"Jinget Says: {nameof(key)} cannot be null or empty and should have at least 32 chars", 1000); - if (ivBytes == null || ivBytes.Length <= 0 || iv.Length != 16) - throw new JingetException($"Jinget Says: {nameof(iv)} cannot be null or empty and should have 16 chars", 1000); + if (plainText == null || plainText.Length <= 0) + throw new JingetException($"Jinget Says: {nameof(plainText)} cannot be null or empty", 1000); + if (keyBytes == null || keyBytes.Length <= 0 || key.Length < 32) + throw new JingetException($"Jinget Says: {nameof(key)} cannot be null or empty and should have at least 32 chars", 1000); + if (ivBytes == null || ivBytes.Length <= 0 || iv.Length != 16) + throw new JingetException($"Jinget Says: {nameof(iv)} cannot be null or empty and should have 16 chars", 1000); - byte[] encrypted; + byte[] encrypted; - using (var rijAlg = Aes.Create()) - { - rijAlg.Key = keyBytes; - rijAlg.IV = ivBytes; + using (var rijAlg = Aes.Create()) + { + rijAlg.Key = keyBytes; + rijAlg.IV = ivBytes; - // Create a decryptor to perform the stream transform. - ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV); + // Create a decryptor to perform the stream transform. + ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV); - // Create the streams used for encryption. - using MemoryStream msEncrypt = new(); - using CryptoStream csEncrypt = new(msEncrypt, encryptor, CryptoStreamMode.Write); - using (StreamWriter swEncrypt = new(csEncrypt)) - { - //Write all data to the stream. - swEncrypt.Write(plainText); - } - encrypted = msEncrypt.ToArray(); + // Create the streams used for encryption. + using MemoryStream msEncrypt = new(); + using CryptoStream csEncrypt = new(msEncrypt, encryptor, CryptoStreamMode.Write); + using (StreamWriter swEncrypt = new(csEncrypt)) + { + //Write all data to the stream. + swEncrypt.Write(plainText); } - // Return the encrypted bytes from the memory stream. - return Convert.ToBase64String(encrypted); + encrypted = msEncrypt.ToArray(); } + // Return the encrypted bytes from the memory stream. + return Convert.ToBase64String(encrypted); + } - /// - /// Decrypts the specified input. - /// - /// Jinget Says: {nameof(input)} is not a valid base64 string - 1000 - /// Jinget Says: {nameof(input)} cannot be null or empty, or has invalid value - 1000 - /// Jinget Says: {nameof(key)} cannot be null or empty - 1000 - /// Jinget Says: {nameof(iv)} cannot be null or empty - 1000 - /// Jinget Says: {nameof(key)}/{nameof(iv)} is not a valid key/iv - 1000 - public static string Decrypt(string input, string key, string iv) - { - var keyBytes = Encoding.UTF8.GetBytes(key); - var ivBytes = Encoding.UTF8.GetBytes(iv); + /// + /// Decrypts the specified input. + /// + /// Jinget Says: {nameof(input)} is not a valid base64 string - 1000 + /// Jinget Says: {nameof(input)} cannot be null or empty, or has invalid value - 1000 + /// Jinget Says: {nameof(key)} cannot be null or empty - 1000 + /// Jinget Says: {nameof(iv)} cannot be null or empty - 1000 + /// Jinget Says: {nameof(key)}/{nameof(iv)} is not a valid key/iv - 1000 + public static string Decrypt(string input, string key, string iv) + { + var keyBytes = Encoding.UTF8.GetBytes(key); + var ivBytes = Encoding.UTF8.GetBytes(iv); - byte[] cipherText; - try - { - cipherText = Convert.FromBase64String(input); - } - catch (FormatException ex) - { - throw new JingetException($"Jinget Says: {nameof(input)} is not a valid base64 string", ex, 1000); - } + byte[] cipherText; + try + { + cipherText = Convert.FromBase64String(input); + } + catch (FormatException ex) + { + throw new JingetException($"Jinget Says: {nameof(input)} is not a valid base64 string", ex, 1000); + } - // Check arguments. - if (cipherText == null || cipherText.Length <= 0) - throw new JingetException($"Jinget Says: {nameof(input)} cannot be null or empty, or has invalid value", 1000); - if (key == null || key.Length <= 0) - throw new JingetException($"Jinget Says: {nameof(key)} cannot be null or empty", 1000); - if (iv == null || iv.Length <= 0) - throw new JingetException($"Jinget Says: {nameof(iv)} cannot be null or empty", 1000); + // Check arguments. + if (cipherText == null || cipherText.Length <= 0) + throw new JingetException($"Jinget Says: {nameof(input)} cannot be null or empty, or has invalid value", 1000); + if (key == null || key.Length <= 0) + throw new JingetException($"Jinget Says: {nameof(key)} cannot be null or empty", 1000); + if (iv == null || iv.Length <= 0) + throw new JingetException($"Jinget Says: {nameof(iv)} cannot be null or empty", 1000); - string plaintext; + string plaintext; - using (var rijAlg = Aes.Create()) + using (var rijAlg = Aes.Create()) + { + try { - try - { - rijAlg.Mode = CipherMode.CBC; - rijAlg.Padding = PaddingMode.PKCS7; - rijAlg.FeedbackSize = 128; - rijAlg.Key = keyBytes; - rijAlg.IV = ivBytes; + rijAlg.Mode = CipherMode.CBC; + rijAlg.Padding = PaddingMode.PKCS7; + rijAlg.FeedbackSize = 128; + rijAlg.Key = keyBytes; + rijAlg.IV = ivBytes; - var decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV); + var decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV); - using var msDecrypt = new MemoryStream(cipherText); - using var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read); - using var srDecrypt = new StreamReader(csDecrypt); - plaintext = srDecrypt.ReadToEnd(); - } - catch (CryptographicException ex) - { - throw new JingetException($"Jinget Says: {nameof(key)}/{nameof(iv)} is not a valid key/iv", ex, 1000); - } + using var msDecrypt = new MemoryStream(cipherText); + using var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read); + using var srDecrypt = new StreamReader(csDecrypt); + plaintext = srDecrypt.ReadToEnd(); + } + catch (CryptographicException ex) + { + throw new JingetException($"Jinget Says: {nameof(key)}/{nameof(iv)} is not a valid key/iv", ex, 1000); } - - return plaintext; } + + return plaintext; } } \ No newline at end of file diff --git a/01-Core/Jinget.Core/Security/Hashing/HashManager.cs b/01-Core/Jinget.Core/Security/Hashing/HashManager.cs index f9c9dcb..ab7d626 100644 --- a/01-Core/Jinget.Core/Security/Hashing/HashManager.cs +++ b/01-Core/Jinget.Core/Security/Hashing/HashManager.cs @@ -4,95 +4,94 @@ using Jinget.Core.Security.Hashing.Model; using Microsoft.AspNetCore.Cryptography.KeyDerivation; -namespace Jinget.Core.Security.Hashing +namespace Jinget.Core.Security.Hashing; + +/// +/// Hash string using Pbkdf2 algorithm. This class cannot be inherited. +/// Implements the +/// more about this algorithm: https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/consumer-apis/password-hashing?view=aspnetcore-2.1 +/// +/// +public sealed class HashManager : IHashManager { /// - /// Hash string using Pbkdf2 algorithm. This class cannot be inherited. - /// Implements the - /// more about this algorithm: https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/consumer-apis/password-hashing?view=aspnetcore-2.1 + /// Ares the equal. /// - /// - public sealed class HashManager : IHashManager + /// result in this model is currently hashed using it's salt value + /// string to be hashed using hashModel's salt value + /// if the hashModel's Result property and the result of the destString hashing process are same then true will be + /// returned + /// Jinget Says: {nameof(hashModel.Salt)} can not be null or empty - 1000 + /// Jinget Says: source hashed value can not be null or empty - 1000 + /// Jinget Says: {nameof(destString)} can not be null or empty - 1000 + /// Jinget Says: given {nameof(hashModel.Salt)} is not a valid base64 string - 1000 + public bool AreEqual(HashModel hashModel, string destString) { - /// - /// Ares the equal. - /// - /// result in this model is currently hashed using it's salt value - /// string to be hashed using hashModel's salt value - /// if the hashModel's Result property and the result of the destString hashing process are same then true will be - /// returned - /// Jinget Says: {nameof(hashModel.Salt)} can not be null or empty - 1000 - /// Jinget Says: source hashed value can not be null or empty - 1000 - /// Jinget Says: {nameof(destString)} can not be null or empty - 1000 - /// Jinget Says: given {nameof(hashModel.Salt)} is not a valid base64 string - 1000 - public bool AreEqual(HashModel hashModel, string destString) + if (string.IsNullOrEmpty(hashModel.Salt)) + throw new JingetException($"Jinget Says: {nameof(hashModel.Salt)} can not be null or empty", 1000); + if (string.IsNullOrEmpty(hashModel.HashedValue)) + throw new JingetException("Jinget Says: source hashed value can not be null or empty", 1000); + if (string.IsNullOrEmpty(destString)) + throw new JingetException($"Jinget Says: {nameof(destString)} can not be null or empty", 1000); + + byte[] originalSalt; + try + { + originalSalt = Convert.FromBase64String(hashModel.Salt); + } + catch (FormatException ex) { - if (string.IsNullOrEmpty(hashModel.Salt)) - throw new JingetException($"Jinget Says: {nameof(hashModel.Salt)} can not be null or empty", 1000); - if (string.IsNullOrEmpty(hashModel.HashedValue)) - throw new JingetException("Jinget Says: source hashed value can not be null or empty", 1000); - if (string.IsNullOrEmpty(destString)) - throw new JingetException($"Jinget Says: {nameof(destString)} can not be null or empty", 1000); + throw new JingetException($"Jinget Says: given {nameof(hashModel.Salt)} is not a valid base64 string", ex, 1000); + } - byte[] originalSalt; - try - { - originalSalt = Convert.FromBase64String(hashModel.Salt); - } - catch (FormatException ex) - { - throw new JingetException($"Jinget Says: given {nameof(hashModel.Salt)} is not a valid base64 string", ex, 1000); - } + var destHashResult = Hash(originalSalt, destString); - var destHashResult = Hash(originalSalt, destString); + return hashModel.HashedValue.Equals(Convert.ToBase64String(destHashResult)); + } - return hashModel.HashedValue.Equals(Convert.ToBase64String(destHashResult)); - } + /// + /// Hashes the specified input. + /// + public HashModel Hash(string input) + { + var salt = GenerateSalt(); - /// - /// Hashes the specified input. - /// - public HashModel Hash(string input) + var hashed = Hash(salt, input); + + return new HashModel { - var salt = GenerateSalt(); + Salt = Convert.ToBase64String(salt), + HashedValue = Convert.ToBase64String(hashed) + }; + } - var hashed = Hash(salt, input); + /// + /// Hashes the specified input. + /// + public string Hash(string input, string salt) + { + byte[] decryptedSalt = Convert.FromBase64String(salt); + byte[] unhashedInput = Hash(decryptedSalt, input); + string hashedInput = Convert.ToBase64String(unhashedInput); + return hashedInput; + } - return new HashModel - { - Salt = Convert.ToBase64String(salt), - HashedValue = Convert.ToBase64String(hashed) - }; - } + /// + /// Hashes the specified input with givent salt. + /// + private byte[] Hash(byte[] salt, string input) => KeyDerivation.Pbkdf2(input, salt, KeyDerivationPrf.HMACSHA256, 10000, 256 / 8); - /// - /// Hashes the specified input. - /// - public string Hash(string input, string salt) + /// + /// Generates random salt value + /// + private byte[] GenerateSalt() + { + var salt = new byte[128 / 8]; + using (var rng = RandomNumberGenerator.Create()) { - byte[] decryptedSalt = Convert.FromBase64String(salt); - byte[] unhashedInput = Hash(decryptedSalt, input); - string hashedInput = Convert.ToBase64String(unhashedInput); - return hashedInput; + rng.GetBytes(salt); } - /// - /// Hashes the specified input with givent salt. - /// - private byte[] Hash(byte[] salt, string input) => KeyDerivation.Pbkdf2(input, salt, KeyDerivationPrf.HMACSHA256, 10000, 256 / 8); - - /// - /// Generates random salt value - /// - private byte[] GenerateSalt() - { - var salt = new byte[128 / 8]; - using (var rng = RandomNumberGenerator.Create()) - { - rng.GetBytes(salt); - } - - return salt; - } + return salt; } } \ No newline at end of file diff --git a/01-Core/Jinget.Core/Security/Hashing/IHashManager.cs b/01-Core/Jinget.Core/Security/Hashing/IHashManager.cs index 4d71593..2283e04 100644 --- a/01-Core/Jinget.Core/Security/Hashing/IHashManager.cs +++ b/01-Core/Jinget.Core/Security/Hashing/IHashManager.cs @@ -1,19 +1,18 @@ using Jinget.Core.Security.Hashing.Model; -namespace Jinget.Core.Security.Hashing +namespace Jinget.Core.Security.Hashing; + +public interface IHashManager { - public interface IHashManager - { - HashModel Hash(string input); + HashModel Hash(string input); - string Hash(string input, string salt); + string Hash(string input, string salt); - /// result in this model is currently hashed using it's salt value - /// string to be hashed using hashModel's salt value - /// - /// if the hashModel's Result property and the result of the destString hashing process are same then true will be - /// returned - /// - bool AreEqual(HashModel hashModel, string destString); - } + /// result in this model is currently hashed using it's salt value + /// string to be hashed using hashModel's salt value + /// + /// if the hashModel's Result property and the result of the destString hashing process are same then true will be + /// returned + /// + bool AreEqual(HashModel hashModel, string destString); } \ No newline at end of file diff --git a/01-Core/Jinget.Core/Security/Hashing/Model/HashModel.cs b/01-Core/Jinget.Core/Security/Hashing/Model/HashModel.cs index 6b100dd..01877d5 100644 --- a/01-Core/Jinget.Core/Security/Hashing/Model/HashModel.cs +++ b/01-Core/Jinget.Core/Security/Hashing/Model/HashModel.cs @@ -1,12 +1,10 @@ -namespace Jinget.Core.Security.Hashing.Model -{ +namespace Jinget.Core.Security.Hashing.Model; + #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - public class HashModel - { - public string Salt { get; set; } - public string HashedValue { get; set; } - } +public class HashModel +{ + public string Salt { get; set; } + public string HashedValue { get; set; } +} #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - -} \ No newline at end of file diff --git a/01-Core/Jinget.Core/Security/SqlInjection/SqlInjection.cs b/01-Core/Jinget.Core/Security/SqlInjection/SqlInjection.cs index 43e2827..e5e1dbc 100644 --- a/01-Core/Jinget.Core/Security/SqlInjection/SqlInjection.cs +++ b/01-Core/Jinget.Core/Security/SqlInjection/SqlInjection.cs @@ -2,38 +2,37 @@ using System.Text; using System.Text.RegularExpressions; -namespace Jinget.Core.Security.SqlInjection +namespace Jinget.Core.Security.SqlInjection; + +/// +/// SqlInjection preventation class +/// +public static class SqlInjection { /// - /// SqlInjection preventation class + /// Immunize the given string and remove the dangerouse characters from this string /// - public static class SqlInjection + /// if set to true tag quote and semicolon characters will be removed from the input string + /// if set to true html tags will be removed from the input string + public static string SecureString(this string insecureString, bool replaceTagQuoteAndSemiColon = true, bool removeHtmlTags = true) { - /// - /// Immunize the given string and remove the dangerouse characters from this string - /// - /// if set to true tag quote and semicolon characters will be removed from the input string - /// if set to true html tags will be removed from the input string - public static string SecureString(this string insecureString, bool replaceTagQuoteAndSemiColon = true, bool removeHtmlTags = true) - { - StringBuilder sb = new(insecureString); + StringBuilder sb = new(insecureString); - if (replaceTagQuoteAndSemiColon) - { - sb.Replace("'", "''") - .Replace(";", string.Empty); - } - - if (removeHtmlTags) - { - Regex regex = new("<.*?>"); - var tags = regex.Matches(sb.ToString()).ToList(); - tags.ForEach(p => sb.Replace(p.Value, string.Empty)); - } + if (replaceTagQuoteAndSemiColon) + { + sb.Replace("'", "''") + .Replace(";", string.Empty); + } - return sb - .Replace("--", string.Empty).ToString() - .Trim(); + if (removeHtmlTags) + { + Regex regex = new("<.*?>"); + var tags = regex.Matches(sb.ToString()).ToList(); + tags.ForEach(p => sb.Replace(p.Value, string.Empty)); } + + return sb + .Replace("--", string.Empty).ToString() + .Trim(); } } \ No newline at end of file diff --git a/01-Core/Jinget.Core/Types/AESModel.cs b/01-Core/Jinget.Core/Types/AESModel.cs index fc0463a..acb2874 100644 --- a/01-Core/Jinget.Core/Types/AESModel.cs +++ b/01-Core/Jinget.Core/Types/AESModel.cs @@ -1,10 +1,10 @@ -namespace Jinget.Core.Types -{ +namespace Jinget.Core.Types; + #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - public class AESModel - { - public string Key { get; set; } - public string IV { get; set; } - } -#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. +public class AESModel +{ + public string Key { get; set; } + public string IV { get; set; } } +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + diff --git a/01-Core/Jinget.Core/Types/FilterCriteria.cs b/01-Core/Jinget.Core/Types/FilterCriteria.cs index fea8d5b..a3ca12b 100644 --- a/01-Core/Jinget.Core/Types/FilterCriteria.cs +++ b/01-Core/Jinget.Core/Types/FilterCriteria.cs @@ -1,22 +1,22 @@ using Jinget.Core.Enumerations; -namespace Jinget.Core.Types -{ - /// - /// represents a filter criteria. if no operator specified, then "=" operator will be used by default - /// +namespace Jinget.Core.Types; + +/// +/// represents a filter criteria. if no operator specified, then "=" operator will be used by default +/// #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - public class FilterCriteria - { - public string Operand { get; set; } - public object Value { get; set; } - public Operator Operator { get; set; } = Operator.Equal; +public class FilterCriteria +{ + public string Operand { get; set; } + public object Value { get; set; } + public Operator Operator { get; set; } = Operator.Equal; - /// - /// Combine current criteria with next criteria - /// - public ConditionCombiningType NextConditionCombination { get; set; } - } -#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + /// + /// Combine current criteria with next criteria + /// + public ConditionCombiningType NextConditionCombination { get; set; } } +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + diff --git a/01-Core/Jinget.Core/Types/HealthCheckModel.cs b/01-Core/Jinget.Core/Types/HealthCheckModel.cs index eca163d..d7c3e20 100644 --- a/01-Core/Jinget.Core/Types/HealthCheckModel.cs +++ b/01-Core/Jinget.Core/Types/HealthCheckModel.cs @@ -1,24 +1,23 @@ using System.Collections.Generic; -namespace Jinget.Core.Types -{ +namespace Jinget.Core.Types; + #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - public class HealthCheckResponseModel +public class HealthCheckResponseModel +{ + public string Status { get; set; } + public string Duration { get; set; } + public ICollection Entries { get; set; } + + public class Entry { - public string Status { get; set; } + public string Key { get; set; } + public string Description { get; set; } + public string Value { get; set; } + public string[] Tags { get; set; } public string Duration { get; set; } - public ICollection Entries { get; set; } - - public class Entry - { - public string Key { get; set; } - public string Description { get; set; } - public string Value { get; set; } - public string[] Tags { get; set; } - public string Duration { get; set; } - public string Exception { get; set; } - } + public string Exception { get; set; } } +} #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. -} \ No newline at end of file diff --git a/01-Core/Jinget.Core/Types/JwtModel.cs b/01-Core/Jinget.Core/Types/JwtModel.cs index 2e899a5..6f045a1 100644 --- a/01-Core/Jinget.Core/Types/JwtModel.cs +++ b/01-Core/Jinget.Core/Types/JwtModel.cs @@ -1,14 +1,14 @@ using System; -namespace Jinget.Core.Types -{ +namespace Jinget.Core.Types; + #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - public class JwtModel - { - public string SecretKey { get; set; } - public string Issuer { get; set; } - public string Audience { get; set; } - public DateTime NotBefore { get; set; } = DateTime.Now; - } -#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. +public class JwtModel +{ + public string SecretKey { get; set; } + public string Issuer { get; set; } + public string Audience { get; set; } + public DateTime NotBefore { get; set; } = DateTime.Now; } +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + diff --git a/01-Core/Jinget.Core/Types/PaginationModel.cs b/01-Core/Jinget.Core/Types/PaginationModel.cs index 908cb87..674852f 100644 --- a/01-Core/Jinget.Core/Types/PaginationModel.cs +++ b/01-Core/Jinget.Core/Types/PaginationModel.cs @@ -1,16 +1,15 @@ -namespace Jinget.Core.Types +namespace Jinget.Core.Types; + +/// +/// represents a filter criteria. if no operator specified, then "=" operator will be used by default +/// +public class PaginationModel { - /// - /// represents a filter criteria. if no operator specified, then "=" operator will be used by default - /// - public class PaginationModel - { - private int page; - private int pageSize; + private int page; + private int pageSize; - public required int Page { get => page < 0 ? 1 : page; set => page = value; } - public required int PageSize { get => pageSize <= 0 || pageSize > 50 ? 10 : pageSize; set => pageSize = value; } - public string? SearchString { get; set; } + public required int Page { get => page < 0 ? 1 : page; set => page = value; } + public required int PageSize { get => pageSize <= 0 || pageSize > 50 ? 10 : pageSize; set => pageSize = value; } + public string? SearchString { get; set; } - } } diff --git a/01-Core/Jinget.Core/Types/ResponseResult.cs b/01-Core/Jinget.Core/Types/ResponseResult.cs index 3d6c958..e0f21c8 100644 --- a/01-Core/Jinget.Core/Types/ResponseResult.cs +++ b/01-Core/Jinget.Core/Types/ResponseResult.cs @@ -1,23 +1,22 @@ using System.Collections.Generic; -namespace Jinget.Core.Types +namespace Jinget.Core.Types; + +public class ResponseResult { - public class ResponseResult - { - private static ResponseResult? _instance; - public static ResponseResult Empty => _instance ??= new ResponseResult(); - public long EffectedRowsCount { get; } + private static ResponseResult? _instance; + public static ResponseResult Empty => _instance ??= new ResponseResult(); + public long EffectedRowsCount { get; } - public List Data { get; } + public List Data { get; } - public ResponseResult() { Data = []; } + public ResponseResult() { Data = []; } - public ResponseResult(TResponseModel data) : this() => Data.Add(data); - public ResponseResult(IEnumerable data) : this() => Data.AddRange(data); + public ResponseResult(TResponseModel data) : this() => Data.Add(data); + public ResponseResult(IEnumerable data) : this() => Data.AddRange(data); - public ResponseResult(TResponseModel data, long effectedRowsCount) : this(data) => EffectedRowsCount = effectedRowsCount; - public ResponseResult(IEnumerable data, long effectedRowsCount) : this(data) => EffectedRowsCount = effectedRowsCount; + public ResponseResult(TResponseModel data, long effectedRowsCount) : this(data) => EffectedRowsCount = effectedRowsCount; + public ResponseResult(IEnumerable data, long effectedRowsCount) : this(data) => EffectedRowsCount = effectedRowsCount; - } } diff --git a/01-Core/Jinget.Core/Utilities/BooleanUtility.cs b/01-Core/Jinget.Core/Utilities/BooleanUtility.cs index bdc8b21..3c58eae 100644 --- a/01-Core/Jinget.Core/Utilities/BooleanUtility.cs +++ b/01-Core/Jinget.Core/Utilities/BooleanUtility.cs @@ -1,12 +1,11 @@ using System; using System.Linq.Expressions; -namespace Jinget.Core.Utilities +namespace Jinget.Core.Utilities; + +public static class BooleanUtility { - public static class BooleanUtility - { - public static Expression> TrueCondition() => x => 1 == 1; + public static Expression> TrueCondition() => x => 1 == 1; - public static Expression> FalseCondition() => x => 1 == 0; - } + public static Expression> FalseCondition() => x => 1 == 0; } \ No newline at end of file diff --git a/01-Core/Jinget.Core/Utilities/Compression/ZipUtility.cs b/01-Core/Jinget.Core/Utilities/Compression/ZipUtility.cs index 895e19a..7d352f9 100644 --- a/01-Core/Jinget.Core/Utilities/Compression/ZipUtility.cs +++ b/01-Core/Jinget.Core/Utilities/Compression/ZipUtility.cs @@ -5,99 +5,98 @@ using System.Threading; using System.Threading.Tasks; -namespace Jinget.Core.Utilities.Compression +namespace Jinget.Core.Utilities.Compression; + +public class ZipUtility { - public class ZipUtility + /// each file will be compressed idependently + /// max degree of parallelism + /// each file will be compressed and then chunked based on this parameter. eachFileMaxSize is in MB + /// location to store compressed files + /// compressed files can also become password protected + /// It is up to you to choose between best speed to high compression + /// compressed files can also become encrypted too! + public async Task CompressAsync( + FileInfo[] files, + string path, + int maxDOP = 1, + int eachFileMaxSize = 5, + string password = "", + CompressionLevel compressionLevel = CompressionLevel.BestSpeed, + EncryptionAlgorithm encryption = EncryptionAlgorithm.None + ) { - /// each file will be compressed idependently - /// max degree of parallelism - /// each file will be compressed and then chunked based on this parameter. eachFileMaxSize is in MB - /// location to store compressed files - /// compressed files can also become password protected - /// It is up to you to choose between best speed to high compression - /// compressed files can also become encrypted too! - public async Task CompressAsync( - FileInfo[] files, - string path, - int maxDOP = 1, - int eachFileMaxSize = 5, - string password = "", - CompressionLevel compressionLevel = CompressionLevel.BestSpeed, - EncryptionAlgorithm encryption = EncryptionAlgorithm.None - ) - { - if (eachFileMaxSize < 1) - eachFileMaxSize = 5; + if (eachFileMaxSize < 1) + eachFileMaxSize = 5; - var allTasks = new List(); + var allTasks = new List(); - var threadCount = files.Length < maxDOP ? files.Length : maxDOP; - var throttler = new SemaphoreSlim(threadCount); - CancellationToken token = new(); - foreach (var file in files) + var threadCount = files.Length < maxDOP ? files.Length : maxDOP; + var throttler = new SemaphoreSlim(threadCount); + CancellationToken token = new(); + foreach (var file in files) + { + await throttler.WaitAsync(); + allTasks.Add(Task.Factory.StartNew(() => { - await throttler.WaitAsync(); - allTasks.Add(Task.Factory.StartNew(() => - { - var fileName = Path.GetFileNameWithoutExtension(file.Name); - - using ZipFile zip = new(); + var fileName = Path.GetFileNameWithoutExtension(file.Name); - if (!string.IsNullOrWhiteSpace(password)) - zip.Password = password; + using ZipFile zip = new(); - zip.BufferSize = eachFileMaxSize * 1024 * 1024; - zip.MaxOutputSegmentSize64 = eachFileMaxSize * 1024 * 1024; - zip.UseZip64WhenSaving = Zip64Option.AsNecessary; - zip.Encryption = encryption; - zip.CompressionLevel = compressionLevel; + if (!string.IsNullOrWhiteSpace(password)) + zip.Password = password; - zip.AddFile(file.FullName); - zip.Save(Path.Combine(path, $"{file.Name}.zip")); + zip.BufferSize = eachFileMaxSize * 1024 * 1024; + zip.MaxOutputSegmentSize64 = eachFileMaxSize * 1024 * 1024; + zip.UseZip64WhenSaving = Zip64Option.AsNecessary; + zip.Encryption = encryption; + zip.CompressionLevel = compressionLevel; - throttler.Release(); - }, token, TaskCreationOptions.LongRunning, TaskScheduler.Default)); - } + zip.AddFile(file.FullName); + zip.Save(Path.Combine(path, $"{file.Name}.zip")); - Task.WaitAll([.. allTasks]); + throttler.Release(); + }, token, TaskCreationOptions.LongRunning, TaskScheduler.Default)); } - /// list of files to extract - /// max degree of parallelism - /// location to extract the files - /// password used to extract the compressed files - public async Task DecompressAsync( - FileInfo[] files, - string path, - int maxDOP = 1, - string password = "") + Task.WaitAll([.. allTasks]); + } + + /// list of files to extract + /// max degree of parallelism + /// location to extract the files + /// password used to extract the compressed files + public async Task DecompressAsync( + FileInfo[] files, + string path, + int maxDOP = 1, + string password = "") + { + var allTasks = new List(); + var threadCount = files.Length < maxDOP ? files.Length : maxDOP; + var throttler = new SemaphoreSlim(threadCount); + var token = new CancellationToken(); + foreach (var file in files) { - var allTasks = new List(); - var threadCount = files.Length < maxDOP ? files.Length : maxDOP; - var throttler = new SemaphoreSlim(threadCount); - var token = new CancellationToken(); - foreach (var file in files) - { - await throttler.WaitAsync(); + await throttler.WaitAsync(); - allTasks.Add(Task.Factory.StartNew(() => + allTasks.Add(Task.Factory.StartNew(() => + { + using ZipFile zip1 = ZipFile.Read(file.FullName); + zip1.FlattenFoldersOnExtract = true; + foreach (ZipEntry e in zip1) { - using ZipFile zip1 = ZipFile.Read(file.FullName); - zip1.FlattenFoldersOnExtract = true; - foreach (ZipEntry e in zip1) + if (string.IsNullOrWhiteSpace(password)) { - if (string.IsNullOrWhiteSpace(password)) - { - e.Extract(path, ExtractExistingFileAction.OverwriteSilently); - } - else - e.ExtractWithPassword(path, ExtractExistingFileAction.OverwriteSilently, password); - + e.Extract(path, ExtractExistingFileAction.OverwriteSilently); } - throttler.Release(); - }, token, TaskCreationOptions.LongRunning, TaskScheduler.Default)); - } - Task.WaitAll([.. allTasks]); + else + e.ExtractWithPassword(path, ExtractExistingFileAction.OverwriteSilently, password); + + } + throttler.Release(); + }, token, TaskCreationOptions.LongRunning, TaskScheduler.Default)); } + Task.WaitAll([.. allTasks]); } } diff --git a/01-Core/Jinget.Core/Utilities/DateTimeUtility.cs b/01-Core/Jinget.Core/Utilities/DateTimeUtility.cs index 0fd9624..d501bd8 100644 --- a/01-Core/Jinget.Core/Utilities/DateTimeUtility.cs +++ b/01-Core/Jinget.Core/Utilities/DateTimeUtility.cs @@ -1,100 +1,99 @@ using System; using System.Globalization; -namespace Jinget.Core.Utilities +namespace Jinget.Core.Utilities; + +public static class DateTimeUtility { - public static class DateTimeUtility + /// + /// Converts given Gregorian date to its Solar equalivant. + /// Minimum supported Gregorian date is: year: 622,month: 3,day: 22. + /// See also: + /// + public static string ToSolarDate(DateTime gregorianDate) { - /// - /// Converts given Gregorian date to its Solar equalivant. - /// Minimum supported Gregorian date is: year: 622,month: 3,day: 22. - /// See also: - /// - public static string ToSolarDate(DateTime gregorianDate) - { - var calendar = new PersianCalendar(); - if (gregorianDate < calendar.MinSupportedDateTime) - throw new ArgumentOutOfRangeException($"Date should be after {calendar.MinSupportedDateTime} "); - return - $"{calendar.GetYear(gregorianDate)}/{calendar.GetMonth(gregorianDate):D2}/{calendar.GetDayOfMonth(gregorianDate):D2}"; - } + var calendar = new PersianCalendar(); + if (gregorianDate < calendar.MinSupportedDateTime) + throw new ArgumentOutOfRangeException($"Date should be after {calendar.MinSupportedDateTime} "); + return + $"{calendar.GetYear(gregorianDate)}/{calendar.GetMonth(gregorianDate):D2}/{calendar.GetDayOfMonth(gregorianDate):D2}"; + } - /// - /// Converts given Solar date to its Gregorian equalivant - /// - public static DateTime ToGregorianDate(string persianDate) - { - if (persianDate.Length == 8 && !persianDate.Contains('/')) - persianDate = $"{persianDate[..4]}/{persianDate.Substring(4, 2)}/{persianDate.Substring(6, 2)}"; - return DateTime.Parse(persianDate, new CultureInfo("fa-IR")); - } + /// + /// Converts given Solar date to its Gregorian equalivant + /// + public static DateTime ToGregorianDate(string persianDate) + { + if (persianDate.Length == 8 && !persianDate.Contains('/')) + persianDate = $"{persianDate[..4]}/{persianDate.Substring(4, 2)}/{persianDate.Substring(6, 2)}"; + return DateTime.Parse(persianDate, new CultureInfo("fa-IR")); + } - /// - /// convert minute to hour and minute representation. for example 150 minutes is equal to 2 hours and 30 minutes - /// - public static TimeSpan ParseToTime(int minute) => TimeSpan.FromMinutes(minute); + /// + /// convert minute to hour and minute representation. for example 150 minutes is equal to 2 hours and 30 minutes + /// + public static TimeSpan ParseToTime(int minute) => TimeSpan.FromMinutes(minute); - /// - /// check if given persian date is a valid date or not. - /// should have exactly 8 numerical characters - /// and it should be also greater than the zero - /// You can check the date validity using minimum acceptable date nad maximum accptable date ranges - /// - public static bool IsValidPersianDate(string persianDate, string minAcceptableDate = "", string maxAcceptableDate = "") - { - if (!StringUtility.IsDigitOnly(persianDate) || Convert.ToInt32(persianDate) < 0 || persianDate.Length != 8) - return false; + /// + /// check if given persian date is a valid date or not. + /// should have exactly 8 numerical characters + /// and it should be also greater than the zero + /// You can check the date validity using minimum acceptable date nad maximum accptable date ranges + /// + public static bool IsValidPersianDate(string persianDate, string minAcceptableDate = "", string maxAcceptableDate = "") + { + if (!StringUtility.IsDigitOnly(persianDate) || Convert.ToInt32(persianDate) < 0 || persianDate.Length != 8) + return false; - DateTime givenDate = ToGregorianDate(persianDate); - DateTime? minDate = null; - DateTime? maxDate = null; - if (minAcceptableDate != "") - minDate = ToGregorianDate(minAcceptableDate); - if (maxAcceptableDate != "") - maxDate = ToGregorianDate(maxAcceptableDate); - if ((minDate == null || givenDate >= minDate) && (maxDate == null || givenDate <= maxDate)) - return true; + DateTime givenDate = ToGregorianDate(persianDate); + DateTime? minDate = null; + DateTime? maxDate = null; + if (minAcceptableDate != "") + minDate = ToGregorianDate(minAcceptableDate); + if (maxAcceptableDate != "") + maxDate = ToGregorianDate(maxAcceptableDate); + if ((minDate == null || givenDate >= minDate) && (maxDate == null || givenDate <= maxDate)) + return true; - else return false; - } + else return false; + } - /// - /// format given input based on the given format string. - /// - public static string Format(string input, string currentFormat = "yyyyMMdd", string newFormat = "yyyy/MM/dd") - { - var isDate = DateTime.TryParseExact( - input.ToString(), - currentFormat, - CultureInfo.InvariantCulture, - DateTimeStyles.None, - out DateTime date); + /// + /// format given input based on the given format string. + /// + public static string Format(string input, string currentFormat = "yyyyMMdd", string newFormat = "yyyy/MM/dd") + { + var isDate = DateTime.TryParseExact( + input.ToString(), + currentFormat, + CultureInfo.InvariantCulture, + DateTimeStyles.None, + out DateTime date); - return isDate ? date.ToString(newFormat) : input.ToString(); - } + return isDate ? date.ToString(newFormat) : input.ToString(); + } - public static string[] GetJalaliDayNames() => ["یکشنبه", "دوشنبه", "سه شنبه", "چهارشنبه", "پنجشنبه", "جمعه", "شنبه"]; + public static string[] GetJalaliDayNames() => ["یکشنبه", "دوشنبه", "سه شنبه", "چهارشنبه", "پنجشنبه", "جمعه", "شنبه"]; - public static string[] GetJalaliDayAbbrNames() => ["ی", "د", "س", "چ", "پ", "ج", "ش"]; + public static string[] GetJalaliDayAbbrNames() => ["ی", "د", "س", "چ", "پ", "ج", "ش"]; - public static string[] GetJalaliMonthNames() => [ - "فروردین","اردیبهشت","خرداد", - "تیر","مرداد","شهریور", - "مهر","آبان","آذر", - "دی","بهمن","اسفند", - "", - ]; + public static string[] GetJalaliMonthNames() => [ + "فروردین","اردیبهشت","خرداد", + "تیر","مرداد","شهریور", + "مهر","آبان","آذر", + "دی","بهمن","اسفند", + "", + ]; - public static string[] GetArabicDayNames() => ["الأحَد", "الإثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت"]; + public static string[] GetArabicDayNames() => ["الأحَد", "الإثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت"]; - public static string[] GetArabicDayAbbrNames() => ["أح", "إث", "ث", "أر", "خ", "ج", "س"]; + public static string[] GetArabicDayAbbrNames() => ["أح", "إث", "ث", "أر", "خ", "ج", "س"]; - public static string[] GetArabicMonthNames() => [ - "ٱلْمُحَرَّم","صَفَر","رَبِيع ٱلْأَوَّل", - "رَبِيع ٱلثَّانِي","جُمَادَىٰ ٱلْأُولَىٰ","جُمَادَىٰ ٱلثَّانِيَة", - "رَجَب","شَعْبَان","رَمَضَان", - "شَوَّال","ذُو ٱلْقَعْدَة","ذُو ٱلْحِجَّة", - "", - ]; - } + public static string[] GetArabicMonthNames() => [ + "ٱلْمُحَرَّم","صَفَر","رَبِيع ٱلْأَوَّل", + "رَبِيع ٱلثَّانِي","جُمَادَىٰ ٱلْأُولَىٰ","جُمَادَىٰ ٱلثَّانِيَة", + "رَجَب","شَعْبَان","رَمَضَان", + "شَوَّال","ذُو ٱلْقَعْدَة","ذُو ٱلْحِجَّة", + "", + ]; } \ No newline at end of file diff --git a/01-Core/Jinget.Core/Utilities/Expressions/ExpressionUtility.cs b/01-Core/Jinget.Core/Utilities/Expressions/ExpressionUtility.cs index 0e44ff5..6158a0c 100644 --- a/01-Core/Jinget.Core/Utilities/Expressions/ExpressionUtility.cs +++ b/01-Core/Jinget.Core/Utilities/Expressions/ExpressionUtility.cs @@ -10,349 +10,348 @@ using System.Reflection; using Jinget.Core.ExtensionMethods.Collections; -namespace Jinget.Core.Utilities.Expressions +namespace Jinget.Core.Utilities.Expressions; + +public static class ExpressionUtility { - public static class ExpressionUtility + /// + /// Transform anonymouse expression to non-anonymouse expression + /// This method is useful wherever the class's default constructor is not accessable due to its access level + /// but you need to use this constructor to define your expression + /// + internal static Expression Transform(Expression source, Type type) { - /// - /// Transform anonymouse expression to non-anonymouse expression - /// This method is useful wherever the class's default constructor is not accessable due to its access level - /// but you need to use this constructor to define your expression - /// - internal static Expression Transform(Expression source, Type type) + if (source.Type != type && source is NewExpression newExpr && newExpr.Members.Count > 0) { - if (source.Type != type && source is NewExpression newExpr && newExpr.Members.Count > 0) - { #pragma warning disable CS8604 // Possible null reference argument. #pragma warning disable CS8602 // Dereference of a possibly null reference. - return Expression.MemberInit(Expression.New(type), newExpr.Members - .Select(m => type.GetProperty(m.Name)) - .Zip(newExpr.Arguments, (m, e) => Expression.Bind(m, Transform(e, m.PropertyType)))); + return Expression.MemberInit(Expression.New(type), newExpr.Members + .Select(m => type.GetProperty(m.Name)) + .Zip(newExpr.Arguments, (m, e) => Expression.Bind(m, Transform(e, m.PropertyType)))); #pragma warning restore CS8602 // Dereference of a possibly null reference. #pragma warning restore CS8604 // Possible null reference argument. - } - else if (source.Type != type && source is MethodCallExpression listCall && listCall.Method.IsStatic - && listCall.Method.DeclaringType == typeof(Enumerable) && - listCall.Method.Name == nameof(Enumerable.ToList)) - { - return Transform(listCall.Arguments[0], type); - } - else if (source.Type != type && source is MethodCallExpression call && call.Method.IsStatic - && call.Method.DeclaringType == typeof(Enumerable) && - call.Method.Name == nameof(Enumerable.Select)) - { - var sourceEnumerable = call.Arguments[0]; - var sourceSelector = (LambdaExpression)call.Arguments[1]; - var sourceElementType = sourceSelector.Parameters[0].Type; - var targetElementType = type.GetGenericArguments()[0]; - var targetSelector = Expression.Lambda(Transform(sourceSelector.Body, targetElementType), sourceSelector.Parameters); - var targetMethod = call.Method.GetGenericMethodDefinition().MakeGenericMethod(sourceElementType, targetElementType); - var result = Expression.Call(targetMethod, sourceEnumerable, targetSelector); - if (type.IsAssignableFrom(result.Type)) - return result; - return Expression.Call( - typeof(Enumerable), nameof(Enumerable.ToList), [targetElementType], - result); - } - return source; } - - /// - /// Try parse an expression and return a string representation of the expression in form of 'A.B.C.etc' - /// - /// - internal static bool TryParseExpression(Expression? expression, out string? path) + else if (source.Type != type && source is MethodCallExpression listCall && listCall.Method.IsStatic + && listCall.Method.DeclaringType == typeof(Enumerable) && + listCall.Method.Name == nameof(Enumerable.ToList)) { - path = null; - if (expression == null) - return true; - var withoutConvert = RemoveConvert(expression); + return Transform(listCall.Arguments[0], type); + } + else if (source.Type != type && source is MethodCallExpression call && call.Method.IsStatic + && call.Method.DeclaringType == typeof(Enumerable) && + call.Method.Name == nameof(Enumerable.Select)) + { + var sourceEnumerable = call.Arguments[0]; + var sourceSelector = (LambdaExpression)call.Arguments[1]; + var sourceElementType = sourceSelector.Parameters[0].Type; + var targetElementType = type.GetGenericArguments()[0]; + var targetSelector = Expression.Lambda(Transform(sourceSelector.Body, targetElementType), sourceSelector.Parameters); + var targetMethod = call.Method.GetGenericMethodDefinition().MakeGenericMethod(sourceElementType, targetElementType); + var result = Expression.Call(targetMethod, sourceEnumerable, targetSelector); + if (type.IsAssignableFrom(result.Type)) + return result; + return Expression.Call( + typeof(Enumerable), nameof(Enumerable.ToList), [targetElementType], + result); + } + return source; + } - if (withoutConvert is ConstantExpression constant) + /// + /// Try parse an expression and return a string representation of the expression in form of 'A.B.C.etc' + /// + /// + internal static bool TryParseExpression(Expression? expression, out string? path) + { + path = null; + if (expression == null) + return true; + var withoutConvert = RemoveConvert(expression); + + if (withoutConvert is ConstantExpression constant) + { + path = constant.Value?.ToString(); + } + else if (withoutConvert is MemberExpression memberExpression) + { + var thisPart = memberExpression.Member.Name; + if (!TryParseExpression(memberExpression.Expression, out var parentPart)) { - path = constant.Value?.ToString(); + return false; } - else if (withoutConvert is MemberExpression memberExpression) + path = parentPart is null ? thisPart : $"{parentPart}.{thisPart}"; + } + else if (withoutConvert is MethodCallExpression callExpression) + { + if (callExpression.Method.Name == "Select" + && callExpression.Arguments.Count == 2) { - var thisPart = memberExpression.Member.Name; - if (!TryParseExpression(memberExpression.Expression, out var parentPart)) + if (!TryParseExpression(callExpression.Arguments[0], out var parentPart)) { return false; } - path = parentPart is null ? thisPart : $"{parentPart}.{thisPart}"; - } - else if (withoutConvert is MethodCallExpression callExpression) - { - if (callExpression.Method.Name == "Select" - && callExpression.Arguments.Count == 2) + if (parentPart != null) { - if (!TryParseExpression(callExpression.Arguments[0], out var parentPart)) + if (callExpression.Arguments[1] is LambdaExpression subExpression) { - return false; - } - if (parentPart != null) - { - if (callExpression.Arguments[1] is LambdaExpression subExpression) + if (!TryParseExpression(subExpression.Body, out var thisPart)) + { + return false; + } + if (thisPart != null) { - if (!TryParseExpression(subExpression.Body, out var thisPart)) - { - return false; - } - if (thisPart != null) - { - path = parentPart + "." + thisPart; - return true; - } + path = parentPart + "." + thisPart; + return true; } } } - else if (callExpression.Method.Name == "ToString") - { - return TryParseExpression( - callExpression.Arguments.Any() ? callExpression.Arguments.First() : callExpression.Object, out path); - } - else if (new[] { "ToLower", "ToUpper" }.Contains(callExpression.Method.Name)) - { - return TryParseExpression(callExpression.Object, out path); - } - else if (callExpression.Method.Name == "Where") - { - throw new JingetException("Jinget Says: Filtering an Include expression is not supported", type: ExceptionType.JingetInternal, ex: new NotSupportedException()); - } - else if (callExpression.Method.Name == "OrderBy" || callExpression.Method.Name == "OrderByDescending") - { - throw new JingetException("Jinget Says: Ordering an Include expression is not supported", type: ExceptionType.JingetInternal, ex: new NotSupportedException()); - } - return false; } - - return true; - } - - /// - /// Removes boxing - /// - internal static Expression RemoveConvert(Expression expression) - { - while (expression.NodeType == ExpressionType.Convert - || expression.NodeType == ExpressionType.ConvertChecked) + else if (callExpression.Method.Name == "ToString") + { + return TryParseExpression( + callExpression.Arguments.Any() ? callExpression.Arguments.First() : callExpression.Object, out path); + } + else if (new[] { "ToLower", "ToUpper" }.Contains(callExpression.Method.Name)) + { + return TryParseExpression(callExpression.Object, out path); + } + else if (callExpression.Method.Name == "Where") + { + throw new JingetException("Jinget Says: Filtering an Include expression is not supported", type: ExceptionType.JingetInternal, ex: new NotSupportedException()); + } + else if (callExpression.Method.Name == "OrderBy" || callExpression.Method.Name == "OrderByDescending") { - expression = ((UnaryExpression)expression).Operand; + throw new JingetException("Jinget Says: Ordering an Include expression is not supported", type: ExceptionType.JingetInternal, ex: new NotSupportedException()); } - return expression; + return false; } - /// - /// example return: x=>"id" - /// - public static Expression> ToExpression(string property, string parameterName = "Param_0") + return true; + } + + /// + /// Removes boxing + /// + internal static Expression RemoveConvert(Expression expression) + { + while (expression.NodeType == ExpressionType.Convert + || expression.NodeType == ExpressionType.ConvertChecked) { + expression = ((UnaryExpression)expression).Operand; + } + return expression; + } - var paramExpression = Expression.Parameter(typeof(T), parameterName); + /// + /// example return: x=>"id" + /// + public static Expression> ToExpression(string property, string parameterName = "Param_0") + { - var memberExpression = Expression.Constant(property); + var paramExpression = Expression.Parameter(typeof(T), parameterName); - return Expression.Lambda>(memberExpression, paramExpression); - } + var memberExpression = Expression.Constant(property); - /// - /// example return: x=>x.id - /// - public static Func ToSelectorExpression(string property, string parameterName = "Param_0") - { - var item = Expression.Parameter(typeof(T), parameterName); - var body = property.Split('.').Aggregate((Expression)item, Expression.PropertyOrField); - var lambda = Expression.Lambda(body, item); + return Expression.Lambda>(memberExpression, paramExpression); + } - return Expression.Lambda>(lambda, item).Compile(); - } + /// + /// example return: x=>x.id + /// + public static Func ToSelectorExpression(string property, string parameterName = "Param_0") + { + var item = Expression.Parameter(typeof(T), parameterName); + var body = property.Split('.').Aggregate((Expression)item, Expression.PropertyOrField); + var lambda = Expression.Lambda(body, item); - /// - /// iterates throw the and create a member init expression - /// - /// type of expression parameter - /// an array of member init expression properties name - public static Expression> CreateMemberInitExpression(string parameterName = "Param_0", params string[] properties) - { - var paramExpression = Expression.Parameter(typeof(T), parameterName); + return Expression.Lambda>(lambda, item).Compile(); + } - List bindings = []; + /// + /// iterates throw the and create a member init expression + /// + /// type of expression parameter + /// an array of member init expression properties name + public static Expression> CreateMemberInitExpression(string parameterName = "Param_0", params string[] properties) + { + var paramExpression = Expression.Parameter(typeof(T), parameterName); - foreach (var property in properties) - { + List bindings = []; + + foreach (var property in properties) + { #pragma warning disable CS8604 // Possible null reference argument. - bindings.Add(Expression.Bind( - member: typeof(T).GetProperty(property), - expression: Expression.Property(paramExpression, property) - )); + bindings.Add(Expression.Bind( + member: typeof(T).GetProperty(property), + expression: Expression.Property(paramExpression, property) + )); #pragma warning restore CS8604 // Possible null reference argument. - } + } - var ctor = typeof(T).GetDefaultConstructor() - ?? throw new Exception($"Default conxtructor not found on type {typeof(T).Name}"); - var memberinit = Expression.MemberInit(Expression.New(ctor), bindings); + var ctor = typeof(T).GetDefaultConstructor() + ?? throw new Exception($"Default conxtructor not found on type {typeof(T).Name}"); + var memberinit = Expression.MemberInit(Expression.New(ctor), bindings); - return Expression.Lambda>(memberinit, paramExpression); - } + return Expression.Lambda>(memberinit, paramExpression); + } - /// - /// Construct a boolean expression based on a json input - /// - /// - /// a key/value structured json string/object, where keys are types property and values are their value - /// When is null or empty, then a default condition will be returned. - /// if this parameter's value is set to true the a default true condition will be returned otherwise a defaule false condition will be returned - /// + /// + /// Construct a boolean expression based on a json input + /// + /// + /// a key/value structured json string/object, where keys are types property and values are their value + /// When is null or empty, then a default condition will be returned. + /// if this parameter's value is set to true the a default true condition will be returned otherwise a defaule false condition will be returned + /// #nullable enable - public static Expression> ConstructBinaryExpression(object? json, bool treatNullOrEmptyAsTrueCondition = true) + public static Expression> ConstructBinaryExpression(object? json, bool treatNullOrEmptyAsTrueCondition = true) #nullable disable + { + //if there is no json object specified, then return the default true/false condition + if (json is null) { - //if there is no json object specified, then return the default true/false condition - if (json is null) - { - return treatNullOrEmptyAsTrueCondition ? BooleanUtility.TrueCondition() : BooleanUtility.FalseCondition(); - } - else - { - return json is IList - ? ConstructBinaryExpression(JsonConvert.DeserializeObject>(JsonConvert.SerializeObject(json)), treatNullOrEmptyAsTrueCondition) - : ConstructBinaryExpression(json.ToString(), treatNullOrEmptyAsTrueCondition); - } + return treatNullOrEmptyAsTrueCondition ? BooleanUtility.TrueCondition() : BooleanUtility.FalseCondition(); } + else + { + return json is IList + ? ConstructBinaryExpression(JsonConvert.DeserializeObject>(JsonConvert.SerializeObject(json)), treatNullOrEmptyAsTrueCondition) + : ConstructBinaryExpression(json.ToString(), treatNullOrEmptyAsTrueCondition); + } + } - /// - /// Construct a boolean expression based on a json input - /// - /// - /// a key/value structured json string/object, where keys are types property and values are their value. - /// for example:{'name':'vahid','age':'34'} which translates to a dictionary where 'name' and 'age' are keys and their values are 'vahid' and '34' - /// When is null or empty, then a default condition will be returned. - /// if this parameters value is set to true the a default true condition will be returned otherwise a defaule false condition will be returned - /// - public static Expression> ConstructBinaryExpression(string json, bool treatNullOrEmptyAsTrueCondition = true) + /// + /// Construct a boolean expression based on a json input + /// + /// + /// a key/value structured json string/object, where keys are types property and values are their value. + /// for example:{'name':'vahid','age':'34'} which translates to a dictionary where 'name' and 'age' are keys and their values are 'vahid' and '34' + /// When is null or empty, then a default condition will be returned. + /// if this parameters value is set to true the a default true condition will be returned otherwise a defaule false condition will be returned + /// + public static Expression> ConstructBinaryExpression(string json, bool treatNullOrEmptyAsTrueCondition = true) + { + //if there empty json string specified, then return the default true/false condition + if (string.IsNullOrWhiteSpace(json.ToString())) { - //if there empty json string specified, then return the default true/false condition - if (string.IsNullOrWhiteSpace(json.ToString())) - { - return treatNullOrEmptyAsTrueCondition ? BooleanUtility.TrueCondition() : BooleanUtility.FalseCondition(); - } + return treatNullOrEmptyAsTrueCondition ? BooleanUtility.TrueCondition() : BooleanUtility.FalseCondition(); + } - var filters = JsonConvert.DeserializeObject>(json).ToFilterCriteria(); - return ConstructBinaryExpression(filters, treatNullOrEmptyAsTrueCondition); + var filters = JsonConvert.DeserializeObject>(json).ToFilterCriteria(); + return ConstructBinaryExpression(filters, treatNullOrEmptyAsTrueCondition); - } + } - public static Expression> ConstructBinaryExpression(IList filters, bool treatNullOrEmptyAsTrueCondition = true) + public static Expression> ConstructBinaryExpression(IList filters, bool treatNullOrEmptyAsTrueCondition = true) + { + //if there is no filter specified, then return the default true/false condition + if (filters is null || !filters.Any()) { - //if there is no filter specified, then return the default true/false condition - if (filters is null || !filters.Any()) - { - return treatNullOrEmptyAsTrueCondition ? BooleanUtility.TrueCondition() : BooleanUtility.FalseCondition(); - } - - var type = typeof(T); - var exprVariable = Expression.Parameter(type, "x"); + return treatNullOrEmptyAsTrueCondition ? BooleanUtility.TrueCondition() : BooleanUtility.FalseCondition(); + } - //construct queries - IDictionary filterExpressions = new Dictionary(); - foreach (var filter in filters) - { - var property = type.GetProperty(filter.Operand, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public); - var propertyType = property.PropertyType; - var propertyExpression = Expression.Property(exprVariable, property); + var type = typeof(T); + var exprVariable = Expression.Parameter(type, "x"); - var value = Convert.ChangeType(filter.Value, propertyType); + //construct queries + IDictionary filterExpressions = new Dictionary(); + foreach (var filter in filters) + { + var property = type.GetProperty(filter.Operand, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public); + var propertyType = property.PropertyType; + var propertyExpression = Expression.Property(exprVariable, property); - filterExpressions.Add(GetBinaryExpression(propertyExpression, Expression.Constant(value), filter.Operator), filter.NextConditionCombination); - } + var value = Convert.ChangeType(filter.Value, propertyType); - return Expression.Lambda>(MergeFilterExpressions(filterExpressions), exprVariable); + filterExpressions.Add(GetBinaryExpression(propertyExpression, Expression.Constant(value), filter.Operator), filter.NextConditionCombination); } - private static Expression MergeFilterExpressions(IDictionary filterExpressions) - { - Expression JoinExpressions(Expression left, ConditionCombiningType join, Expression right) - { - return join switch - { - ConditionCombiningType.Unknown => Expression.AndAlso(left, right), - ConditionCombiningType.AndAlso => Expression.AndAlso(left, right), - ConditionCombiningType.OrElse => Expression.OrElse(left, right), - _ => throw new JingetException($"Conditional join of type {filterExpressions.ElementAt(0).Value} is not supported by Jinget!") - }; - } - Expression query = filterExpressions.Count > 1 - ? JoinExpressions(filterExpressions.ElementAt(0).Key, filterExpressions.ElementAt(0).Value, filterExpressions.ElementAt(1).Key) - : filterExpressions.First().Key; + return Expression.Lambda>(MergeFilterExpressions(filterExpressions), exprVariable); + } - for (int i = 2; i < filterExpressions.Count; i++) + private static Expression MergeFilterExpressions(IDictionary filterExpressions) + { + Expression JoinExpressions(Expression left, ConditionCombiningType join, Expression right) + { + return join switch { - query = JoinExpressions(query, filterExpressions.ElementAt(i - 1).Value, filterExpressions.ElementAt(i).Key); - } - return query; + ConditionCombiningType.Unknown => Expression.AndAlso(left, right), + ConditionCombiningType.AndAlso => Expression.AndAlso(left, right), + ConditionCombiningType.OrElse => Expression.OrElse(left, right), + _ => throw new JingetException($"Conditional join of type {filterExpressions.ElementAt(0).Value} is not supported by Jinget!") + }; } + Expression query = filterExpressions.Count > 1 + ? JoinExpressions(filterExpressions.ElementAt(0).Key, filterExpressions.ElementAt(0).Value, filterExpressions.ElementAt(1).Key) + : filterExpressions.First().Key; - private static Expression GetBinaryExpression(MemberExpression left, ConstantExpression right, Operator @operator) + for (int i = 2; i < filterExpressions.Count; i++) { - return @operator switch - { - Operator.Equal => Expression.Equal(left, right), - Operator.GreaterThan => Expression.GreaterThan(left, right), - Operator.LowerThan => Expression.LessThan(left, right), - Operator.GreaterThanOrEqual => Expression.GreaterThanOrEqual(left, right), - Operator.LowerThanOrEqual => Expression.LessThanOrEqual(left, right), - Operator.NotEqual => Expression.NotEqual(left, right), - Operator.Contains => Expression.Call(left, typeof(string).GetMethod("Contains", [typeof(string)]), right), - _ => throw new JingetException($"Operator of type {@operator} is not supported by Jinget!"), - }; + query = JoinExpressions(query, filterExpressions.ElementAt(i - 1).Value, filterExpressions.ElementAt(i).Key); } + return query; + } - public static Expression> CreateEqualCondition(string propertyName, object value, string parameterName = "Param_0") + private static Expression GetBinaryExpression(MemberExpression left, ConstantExpression right, Operator @operator) + { + return @operator switch { - ParameterExpression parameter = Expression.Parameter(typeof(T), parameterName); + Operator.Equal => Expression.Equal(left, right), + Operator.GreaterThan => Expression.GreaterThan(left, right), + Operator.LowerThan => Expression.LessThan(left, right), + Operator.GreaterThanOrEqual => Expression.GreaterThanOrEqual(left, right), + Operator.LowerThanOrEqual => Expression.LessThanOrEqual(left, right), + Operator.NotEqual => Expression.NotEqual(left, right), + Operator.Contains => Expression.Call(left, typeof(string).GetMethod("Contains", [typeof(string)]), right), + _ => throw new JingetException($"Operator of type {@operator} is not supported by Jinget!"), + }; + } - Type valueType = typeof(TValueType); + public static Expression> CreateEqualCondition(string propertyName, object value, string parameterName = "Param_0") + { + ParameterExpression parameter = Expression.Parameter(typeof(T), parameterName); - var rightExpression = Expression.Constant(value, valueType.IsNullable() ? Nullable.GetUnderlyingType(valueType) : valueType); + Type valueType = typeof(TValueType); - MemberExpression propertyAccess = GetMemberAccessExpression(parameter, propertyName, typeof(T)); - if (valueType.IsNullable()) - { - MemberExpression propertyValueAccess = GetMemberAccessExpression(parameter, $"{propertyName}.Value", typeof(T)); - MemberExpression hasValueAccess = GetMemberAccessExpression(parameter, $"{propertyName}.HasValue", typeof(T)); - return Expression.Lambda>( - Expression.Condition(hasValueAccess, Expression.Equal(propertyValueAccess, rightExpression), Expression.Constant(false)), parameter); - } + var rightExpression = Expression.Constant(value, valueType.IsNullable() ? Nullable.GetUnderlyingType(valueType) : valueType); - return Expression.Lambda>(Expression.Equal(propertyAccess, rightExpression), parameter); + MemberExpression propertyAccess = GetMemberAccessExpression(parameter, propertyName, typeof(T)); + if (valueType.IsNullable()) + { + MemberExpression propertyValueAccess = GetMemberAccessExpression(parameter, $"{propertyName}.Value", typeof(T)); + MemberExpression hasValueAccess = GetMemberAccessExpression(parameter, $"{propertyName}.HasValue", typeof(T)); + return Expression.Lambda>( + Expression.Condition(hasValueAccess, Expression.Equal(propertyValueAccess, rightExpression), Expression.Constant(false)), parameter); } - private static MemberExpression GetMemberAccessExpression(Expression expression, string members, Type type) - { - List memberList = [.. members.Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries)]; - string firstMember = memberList.First(); - MemberExpression memberExpression = CreateMemberAccessExpression(type, expression, firstMember); + return Expression.Lambda>(Expression.Equal(propertyAccess, rightExpression), parameter); + } - foreach (var item in memberList.Skip(1)) - { - memberExpression = CreateMemberAccessExpression(((PropertyInfo)memberExpression.Member).PropertyType, memberExpression, item); - } - return memberExpression; - } + private static MemberExpression GetMemberAccessExpression(Expression expression, string members, Type type) + { + List memberList = [.. members.Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries)]; + string firstMember = memberList.First(); + MemberExpression memberExpression = CreateMemberAccessExpression(type, expression, firstMember); - private static MemberExpression CreateMemberAccessExpression(Type type, Expression expression, string member) + foreach (var item in memberList.Skip(1)) { - var membersInfo = type.GetMember(member); - if (membersInfo.Any()) - { - MemberInfo memberInfo = membersInfo.FirstOrDefault(); - if (memberInfo != null) - return Expression.MakeMemberAccess(expression, memberInfo); + memberExpression = CreateMemberAccessExpression(((PropertyInfo)memberExpression.Member).PropertyType, memberExpression, item); + } + return memberExpression; + } - throw new JingetException($"Jinget Says: {type.Name} does not {member} member.", 1000); - } + private static MemberExpression CreateMemberAccessExpression(Type type, Expression expression, string member) + { + var membersInfo = type.GetMember(member); + if (membersInfo.Any()) + { + MemberInfo memberInfo = membersInfo.FirstOrDefault(); + if (memberInfo != null) + return Expression.MakeMemberAccess(expression, memberInfo); throw new JingetException($"Jinget Says: {type.Name} does not {member} member.", 1000); } + + throw new JingetException($"Jinget Says: {type.Name} does not {member} member.", 1000); } } \ No newline at end of file diff --git a/01-Core/Jinget.Core/Utilities/Expressions/ReplaceExpressionVisitor.cs b/01-Core/Jinget.Core/Utilities/Expressions/ReplaceExpressionVisitor.cs index 6c19dd3..f689981 100644 --- a/01-Core/Jinget.Core/Utilities/Expressions/ReplaceExpressionVisitor.cs +++ b/01-Core/Jinget.Core/Utilities/Expressions/ReplaceExpressionVisitor.cs @@ -2,28 +2,27 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("Jinget.Core.Tests")] -namespace Jinget.Core.Utilities.Expressions +namespace Jinget.Core.Utilities.Expressions; + +/// +/// Replaces one expression with another in given expression tree. +/// +/// The parameter is to be replaced by a new parameter() +/// The parameter is to replace the old parameter() +internal class ReplaceExpressionVisitor(Expression oldValue, Expression newValue) : ExpressionVisitor { + private readonly Expression? _oldValue = oldValue; + private readonly Expression? _newValue = newValue; + /// - /// Replaces one expression with another in given expression tree. + /// Traverse the expression tree untill current node is equal to _oldValue, then it will swip _newValue with node /// - /// The parameter is to be replaced by a new parameter() - /// The parameter is to replace the old parameter() - internal class ReplaceExpressionVisitor(Expression oldValue, Expression newValue) : ExpressionVisitor - { - private readonly Expression? _oldValue = oldValue; - private readonly Expression? _newValue = newValue; - - /// - /// Traverse the expression tree untill current node is equal to _oldValue, then it will swip _newValue with node - /// - /// - /// given _oldValue = x, _newValue = y, node = x=>x.Id>0 - /// then it will traverse this expression and replace the x with y - /// so the result will be y=>y.Id>0 - /// - /// Expression tree that should be traversed - /// - public override Expression? Visit(Expression? node) => node == _oldValue ? _newValue : base.Visit(node); - } + /// + /// given _oldValue = x, _newValue = y, node = x=>x.Id>0 + /// then it will traverse this expression and replace the x with y + /// so the result will be y=>y.Id>0 + /// + /// Expression tree that should be traversed + /// + public override Expression? Visit(Expression? node) => node == _oldValue ? _newValue : base.Visit(node); } diff --git a/01-Core/Jinget.Core/Utilities/Http/HeaderUtility.cs b/01-Core/Jinget.Core/Utilities/Http/HeaderUtility.cs index 0886467..dd43ecb 100644 --- a/01-Core/Jinget.Core/Utilities/Http/HeaderUtility.cs +++ b/01-Core/Jinget.Core/Utilities/Http/HeaderUtility.cs @@ -3,67 +3,66 @@ using System.Linq; using System.Net.Mime; -namespace Jinget.Core.Utilities.Http +namespace Jinget.Core.Utilities.Http; + +public class HeaderUtility { - public class HeaderUtility - { - /// - /// check if content type header presents in the given collection or not. - /// This method does serch for the key using - /// - public static bool HasContentType(Dictionary headers) - => - headers != null && - headers.Keys.Any(x => string.Equals(x, "Content-Type", StringComparison.OrdinalIgnoreCase)); + /// + /// check if content type header presents in the given collection or not. + /// This method does serch for the key using + /// + public static bool HasContentType(Dictionary headers) + => + headers != null && + headers.Keys.Any(x => string.Equals(x, "Content-Type", StringComparison.OrdinalIgnoreCase)); - /// - /// searches for content-type header and if presents, return its value. - /// This method searches for the content-type header using - /// - public static string GetContentTypeValue(Dictionary headers) + /// + /// searches for content-type header and if presents, return its value. + /// This method searches for the content-type header using + /// + public static string GetContentTypeValue(Dictionary headers) + { + if (headers != null && HasContentType(headers)) { - if (headers != null && HasContentType(headers)) - { - return headers.FirstOrDefault(x => string.Equals(x.Key, "Content-Type", StringComparison.OrdinalIgnoreCase)).Value; - } - return ""; + return headers.FirstOrDefault(x => string.Equals(x.Key, "Content-Type", StringComparison.OrdinalIgnoreCase)).Value; } + return ""; + } - /// - /// searches for content-type header and if presents, return its key. - /// This method searches for the content-type header using - /// - public static string GetContentTypeHeaderName(Dictionary headers) - { - if (headers != null && HasContentType(headers)) - return headers.FirstOrDefault(x => string.Equals(x.Key, "Content-Type", StringComparison.OrdinalIgnoreCase)).Key; - return ""; - } + /// + /// searches for content-type header and if presents, return its key. + /// This method searches for the content-type header using + /// + public static string GetContentTypeHeaderName(Dictionary headers) + { + if (headers != null && HasContentType(headers)) + return headers.FirstOrDefault(x => string.Equals(x.Key, "Content-Type", StringComparison.OrdinalIgnoreCase)).Key; + return ""; + } - /// - /// check if - /// or exists in the given header collection - /// - public static bool IsXmlContentType(Dictionary headers) - => - HasContentType(headers) && - (string.Equals(GetContentTypeValue(headers), MediaTypeNames.Text.Xml, StringComparison.OrdinalIgnoreCase) || - GetContentTypeValue(headers).StartsWith(MediaTypeNames.Application.Xml, StringComparison.OrdinalIgnoreCase)); + /// + /// check if + /// or exists in the given header collection + /// + public static bool IsXmlContentType(Dictionary headers) + => + HasContentType(headers) && + (string.Equals(GetContentTypeValue(headers), MediaTypeNames.Text.Xml, StringComparison.OrdinalIgnoreCase) || + GetContentTypeValue(headers).StartsWith(MediaTypeNames.Application.Xml, StringComparison.OrdinalIgnoreCase)); - /// - /// check if exists in the given header collection - /// - public static bool IsJsonContentType(Dictionary headers) - => - HasContentType(headers) && - GetContentTypeValue(headers).StartsWith(MediaTypeNames.Application.Json, StringComparison.OrdinalIgnoreCase); + /// + /// check if exists in the given header collection + /// + public static bool IsJsonContentType(Dictionary headers) + => + HasContentType(headers) && + GetContentTypeValue(headers).StartsWith(MediaTypeNames.Application.Json, StringComparison.OrdinalIgnoreCase); - /// - /// check if exists in the given header collection - /// - public static bool IsMultiPartFormDataContentType(Dictionary headers) - => - HasContentType(headers) && - GetContentTypeValue(headers).StartsWith(MediaTypeNames.Application.Json, StringComparison.OrdinalIgnoreCase); - } + /// + /// check if exists in the given header collection + /// + public static bool IsMultiPartFormDataContentType(Dictionary headers) + => + HasContentType(headers) && + GetContentTypeValue(headers).StartsWith(MediaTypeNames.Application.Json, StringComparison.OrdinalIgnoreCase); } diff --git a/01-Core/Jinget.Core/Utilities/Http/MimeTypeMap.cs b/01-Core/Jinget.Core/Utilities/Http/MimeTypeMap.cs index 566c35c..99fc185 100644 --- a/01-Core/Jinget.Core/Utilities/Http/MimeTypeMap.cs +++ b/01-Core/Jinget.Core/Utilities/Http/MimeTypeMap.cs @@ -3,806 +3,805 @@ using System.Linq; using System.Net.Mime; -namespace Jinget.Core.Utilities.Http +namespace Jinget.Core.Utilities.Http; + +public static class MimeTypeMap { - public static class MimeTypeMap - { - private const string Dot = "."; - private const string QuestionMark = "?"; - private const string DefaultMimeType = MediaTypeNames.Application.Octet; - private static readonly Lazy> _mappings = new(BuildMappings); + private const string Dot = "."; + private const string QuestionMark = "?"; + private const string DefaultMimeType = MediaTypeNames.Application.Octet; + private static readonly Lazy> _mappings = new(BuildMappings); - private static IDictionary BuildMappings() - { - var mappings = new Dictionary(StringComparer.OrdinalIgnoreCase) { - {".323", "text/h323"}, - {".3g2", "video/3gpp2"}, - {".3gp", "video/3gpp"}, - {".3gp2", "video/3gpp2"}, - {".3gpp", "video/3gpp"}, - {".7z", "application/x-7z-compressed"}, - {".aa", "audio/audible"}, - {".AAC", "audio/aac"}, - {".aaf", "application/octet-stream"}, - {".aax", "audio/vnd.audible.aax"}, - {".ac3", "audio/ac3"}, - {".aca", "application/octet-stream"}, - {".accda", "application/msaccess.addin"}, - {".accdb", "application/msaccess"}, - {".accdc", "application/msaccess.cab"}, - {".accde", "application/msaccess"}, - {".accdr", "application/msaccess.runtime"}, - {".accdt", "application/msaccess"}, - {".accdw", "application/msaccess.webapplication"}, - {".accft", "application/msaccess.ftemplate"}, - {".acx", "application/internet-property-stream"}, - {".AddIn", "text/xml"}, - {".ade", "application/msaccess"}, - {".adobebridge", "application/x-bridge-url"}, - {".adp", "application/msaccess"}, - {".ADT", "audio/vnd.dlna.adts"}, - {".ADTS", "audio/aac"}, - {".afm", "application/octet-stream"}, - {".ai", "application/postscript"}, - {".aif", "audio/aiff"}, - {".aifc", "audio/aiff"}, - {".aiff", "audio/aiff"}, - {".air", "application/vnd.adobe.air-application-installer-package+zip"}, - {".amc", "application/mpeg"}, - {".anx", "application/annodex"}, - {".apk", "application/vnd.android.package-archive"}, - {".apng", "image/apng"}, - {".application", "application/x-ms-application"}, - {".art", "image/x-jg"}, - {".asa", "application/xml"}, - {".asax", "application/xml"}, - {".ascx", "application/xml"}, - {".asd", "application/octet-stream"}, - {".asf", "video/x-ms-asf"}, - {".ashx", "application/xml"}, - {".asi", "application/octet-stream"}, - {".asm", "text/plain"}, - {".asmx", "application/xml"}, - {".aspx", "application/xml"}, - {".asr", "video/x-ms-asf"}, - {".asx", "video/x-ms-asf"}, - {".atom", "application/atom+xml"}, - {".au", "audio/basic"}, - {".avci", "image/avci"}, - {".avcs", "image/avcs"}, - {".avi", "video/x-msvideo"}, - {".avif", "image/avif"}, - {".avifs", "image/avif-sequence"}, - {".axa", "audio/annodex"}, - {".axs", "application/olescript"}, - {".axv", "video/annodex"}, - {".bas", "text/plain"}, - {".bcpio", "application/x-bcpio"}, - {".bin", "application/octet-stream"}, - {".bmp", "image/bmp"}, - {".c", "text/plain"}, - {".cab", "application/octet-stream"}, - {".caf", "audio/x-caf"}, - {".calx", "application/vnd.ms-office.calx"}, - {".cat", "application/vnd.ms-pki.seccat"}, - {".cc", "text/plain"}, - {".cd", "text/plain"}, - {".cdda", "audio/aiff"}, - {".cdf", "application/x-cdf"}, - {".cer", "application/x-x509-ca-cert"}, - {".cfg", "text/plain"}, - {".chm", "application/octet-stream"}, - {".class", "application/x-java-applet"}, - {".clp", "application/x-msclip"}, - {".cmd", "text/plain"}, - {".cmx", "image/x-cmx"}, - {".cnf", "text/plain"}, - {".cod", "image/cis-cod"}, - {".config", "application/xml"}, - {".contact", "text/x-ms-contact"}, - {".coverage", "application/xml"}, - {".cpio", "application/x-cpio"}, - {".cpp", "text/plain"}, - {".crd", "application/x-mscardfile"}, - {".crl", "application/pkix-crl"}, - {".crt", "application/x-x509-ca-cert"}, - {".cs", "text/plain"}, - {".csdproj", "text/plain"}, - {".csh", "application/x-csh"}, - {".csproj", "text/plain"}, - {".css", "text/css"}, - {".csv", "text/csv"}, - {".cur", "application/octet-stream"}, - {".czx", "application/x-czx"}, - {".cxx", "text/plain"}, - {".dat", "application/octet-stream"}, - {".datasource", "application/xml"}, - {".dbproj", "text/plain"}, - {".dcr", "application/x-director"}, - {".def", "text/plain"}, - {".deploy", "application/octet-stream"}, - {".der", "application/x-x509-ca-cert"}, - {".dgml", "application/xml"}, - {".dib", "image/bmp"}, - {".dif", "video/x-dv"}, - {".dir", "application/x-director"}, - {".disco", "text/xml"}, - {".divx", "video/divx"}, - {".dll", "application/x-msdownload"}, - {".dll.config", "text/xml"}, - {".dlm", "text/dlm"}, - {".doc", "application/msword"}, - {".docm", "application/vnd.ms-word.document.macroEnabled.12"}, - {".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"}, - {".dot", "application/msword"}, - {".dotm", "application/vnd.ms-word.template.macroEnabled.12"}, - {".dotx", "application/vnd.openxmlformats-officedocument.wordprocessingml.template"}, - {".dsp", "application/octet-stream"}, - {".dsw", "text/plain"}, - {".dtd", "text/xml"}, - {".dtsConfig", "text/xml"}, - {".dv", "video/x-dv"}, - {".dvi", "application/x-dvi"}, - {".dwf", "drawing/x-dwf"}, - {".dwg", "application/acad"}, - {".dwp", "application/octet-stream"}, - {".dxf", "application/x-dxf"}, - {".dxr", "application/x-director"}, - {".eml", "message/rfc822"}, - {".emf", "image/emf"}, - {".emz", "application/octet-stream"}, - {".eot", "application/vnd.ms-fontobject"}, - {".eps", "application/postscript"}, - {".es", "application/ecmascript"}, - {".etl", "application/etl"}, - {".etx", "text/x-setext"}, - {".evy", "application/envoy"}, - {".exe", "application/vnd.microsoft.portable-executable"}, - {".exe.config", "text/xml"}, - {".f4v", "video/mp4"}, - {".fdf", "application/vnd.fdf"}, - {".fif", "application/fractals"}, - {".filters", "application/xml"}, - {".fla", "application/octet-stream"}, - {".flac", "audio/flac"}, - {".flr", "x-world/x-vrml"}, - {".flv", "video/x-flv"}, - {".fsscript", "application/fsharp-script"}, - {".fsx", "application/fsharp-script"}, - {".generictest", "application/xml"}, - {".geojson", "application/geo+json"}, - {".gif", "image/gif"}, - {".gpx", "application/gpx+xml"}, - {".group", "text/x-ms-group"}, - {".gsm", "audio/x-gsm"}, - {".gtar", "application/x-gtar"}, - {".gz", "application/x-gzip"}, - {".h", "text/plain"}, - {".hdf", "application/x-hdf"}, - {".hdml", "text/x-hdml"}, - {".heic", "image/heic"}, - {".heics", "image/heic-sequence"}, - {".heif", "image/heif"}, - {".heifs", "image/heif-sequence"}, - {".hhc", "application/x-oleobject"}, - {".hhk", "application/octet-stream"}, - {".hhp", "application/octet-stream"}, - {".hlp", "application/winhlp"}, - {".hpp", "text/plain"}, - {".hqx", "application/mac-binhex40"}, - {".hta", "application/hta"}, - {".htc", "text/x-component"}, - {".htm", "text/html"}, - {".html", "text/html"}, - {".htt", "text/webviewhtml"}, - {".hxa", "application/xml"}, - {".hxc", "application/xml"}, - {".hxd", "application/octet-stream"}, - {".hxe", "application/xml"}, - {".hxf", "application/xml"}, - {".hxh", "application/octet-stream"}, - {".hxi", "application/octet-stream"}, - {".hxk", "application/xml"}, - {".hxq", "application/octet-stream"}, - {".hxr", "application/octet-stream"}, - {".hxs", "application/octet-stream"}, - {".hxt", "text/html"}, - {".hxv", "application/xml"}, - {".hxw", "application/octet-stream"}, - {".hxx", "text/plain"}, - {".i", "text/plain"}, - {".ical", "text/calendar"}, - {".icalendar", "text/calendar"}, - {".ico", "image/x-icon"}, - {".ics", "text/calendar"}, - {".idl", "text/plain"}, - {".ief", "image/ief"}, - {".ifb", "text/calendar"}, - {".iii", "application/x-iphone"}, - {".inc", "text/plain"}, - {".inf", "application/octet-stream"}, - {".ini", "text/plain"}, - {".inl", "text/plain"}, - {".ins", "application/x-internet-signup"}, - {".ipa", "application/x-itunes-ipa"}, - {".ipg", "application/x-itunes-ipg"}, - {".ipproj", "text/plain"}, - {".ipsw", "application/x-itunes-ipsw"}, - {".iqy", "text/x-ms-iqy"}, - {".isp", "application/x-internet-signup"}, - {".isma", "application/octet-stream"}, - {".ismv", "application/octet-stream"}, - {".ite", "application/x-itunes-ite"}, - {".itlp", "application/x-itunes-itlp"}, - {".itms", "application/x-itunes-itms"}, - {".itpc", "application/x-itunes-itpc"}, - {".IVF", "video/x-ivf"}, - {".jar", "application/java-archive"}, - {".java", "application/octet-stream"}, - {".jck", "application/liquidmotion"}, - {".jcz", "application/liquidmotion"}, - {".jfif", "image/pjpeg"}, - {".jnlp", "application/x-java-jnlp-file"}, - {".jpb", "application/octet-stream"}, - {".jpe", "image/jpeg"}, - {".jpeg", "image/jpeg"}, - {".jpg", "image/jpeg"}, - {".js", "application/javascript"}, - {".json", "application/json"}, - {".jsx", "text/jscript"}, - {".jsxbin", "text/plain"}, - {".key", "application/vnd.apple.keynote"}, - {".latex", "application/x-latex"}, - {".library-ms", "application/windows-library+xml"}, - {".lit", "application/x-ms-reader"}, - {".loadtest", "application/xml"}, - {".lpk", "application/octet-stream"}, - {".lsf", "video/x-la-asf"}, - {".lst", "text/plain"}, - {".lsx", "video/x-la-asf"}, - {".lzh", "application/octet-stream"}, - {".m13", "application/x-msmediaview"}, - {".m14", "application/x-msmediaview"}, - {".m1v", "video/mpeg"}, - {".m2t", "video/vnd.dlna.mpeg-tts"}, - {".m2ts", "video/vnd.dlna.mpeg-tts"}, - {".m2v", "video/mpeg"}, - {".m3u", "audio/x-mpegurl"}, - {".m3u8", "audio/x-mpegurl"}, - {".m4a", "audio/m4a"}, - {".m4b", "audio/m4b"}, - {".m4p", "audio/m4p"}, - {".m4r", "audio/x-m4r"}, - {".m4v", "video/x-m4v"}, - {".mac", "image/x-macpaint"}, - {".mak", "text/plain"}, - {".man", "application/x-troff-man"}, - {".manifest", "application/x-ms-manifest"}, - {".map", "text/plain"}, - {".master", "application/xml"}, - {".mbox", "application/mbox"}, - {".mda", "application/msaccess"}, - {".mdb", "application/x-msaccess"}, - {".mde", "application/msaccess"}, - {".mdp", "application/octet-stream"}, - {".me", "application/x-troff-me"}, - {".mfp", "application/x-shockwave-flash"}, - {".mht", "message/rfc822"}, - {".mhtml", "message/rfc822"}, - {".mid", "audio/mid"}, - {".midi", "audio/mid"}, - {".mix", "application/octet-stream"}, - {".mk", "text/plain"}, - {".mk3d", "video/x-matroska-3d"}, - {".mka", "audio/x-matroska"}, - {".mkv", "video/x-matroska"}, - {".mmf", "application/x-smaf"}, - {".mno", "text/xml"}, - {".mny", "application/x-msmoney"}, - {".mod", "video/mpeg"}, - {".mov", "video/quicktime"}, - {".movie", "video/x-sgi-movie"}, - {".mp2", "video/mpeg"}, - {".mp2v", "video/mpeg"}, - {".mp3", "audio/mpeg"}, - {".mp4", "video/mp4"}, - {".mp4v", "video/mp4"}, - {".mpa", "video/mpeg"}, - {".mpe", "video/mpeg"}, - {".mpeg", "video/mpeg"}, - {".mpf", "application/vnd.ms-mediapackage"}, - {".mpg", "video/mpeg"}, - {".mpp", "application/vnd.ms-project"}, - {".mpv2", "video/mpeg"}, - {".mqv", "video/quicktime"}, - {".ms", "application/x-troff-ms"}, - {".msg", "application/vnd.ms-outlook"}, - {".msi", "application/octet-stream"}, - {".mso", "application/octet-stream"}, - {".mts", "video/vnd.dlna.mpeg-tts"}, - {".mtx", "application/xml"}, - {".mvb", "application/x-msmediaview"}, - {".mvc", "application/x-miva-compiled"}, - {".mxf", "application/mxf"}, - {".mxp", "application/x-mmxp"}, - {".nc", "application/x-netcdf"}, - {".nsc", "video/x-ms-asf"}, - {".numbers", "application/vnd.apple.numbers"}, - {".nws", "message/rfc822"}, - {".ocx", "application/octet-stream"}, - {".oda", "application/oda"}, - {".odb", "application/vnd.oasis.opendocument.database"}, - {".odc", "application/vnd.oasis.opendocument.chart"}, - {".odf", "application/vnd.oasis.opendocument.formula"}, - {".odg", "application/vnd.oasis.opendocument.graphics"}, - {".odh", "text/plain"}, - {".odi", "application/vnd.oasis.opendocument.image"}, - {".odl", "text/plain"}, - {".odm", "application/vnd.oasis.opendocument.text-master"}, - {".odp", "application/vnd.oasis.opendocument.presentation"}, - {".ods", "application/vnd.oasis.opendocument.spreadsheet"}, - {".odt", "application/vnd.oasis.opendocument.text"}, - {".oga", "audio/ogg"}, - {".ogg", "audio/ogg"}, - {".ogv", "video/ogg"}, - {".ogx", "application/ogg"}, - {".one", "application/onenote"}, - {".onea", "application/onenote"}, - {".onepkg", "application/onenote"}, - {".onetmp", "application/onenote"}, - {".onetoc", "application/onenote"}, - {".onetoc2", "application/onenote"}, - {".opus", "audio/ogg"}, - {".orderedtest", "application/xml"}, - {".osdx", "application/opensearchdescription+xml"}, - {".otf", "application/font-sfnt"}, - {".otg", "application/vnd.oasis.opendocument.graphics-template"}, - {".oth", "application/vnd.oasis.opendocument.text-web"}, - {".otp", "application/vnd.oasis.opendocument.presentation-template"}, - {".ots", "application/vnd.oasis.opendocument.spreadsheet-template"}, - {".ott", "application/vnd.oasis.opendocument.text-template"}, - {".oxps", "application/oxps"}, - {".oxt", "application/vnd.openofficeorg.extension"}, - {".p10", "application/pkcs10"}, - {".p12", "application/x-pkcs12"}, - {".p7b", "application/x-pkcs7-certificates"}, - {".p7c", "application/pkcs7-mime"}, - {".p7m", "application/pkcs7-mime"}, - {".p7r", "application/x-pkcs7-certreqresp"}, - {".p7s", "application/pkcs7-signature"}, - {".pages", "application/vnd.apple.pages"}, - {".pbm", "image/x-portable-bitmap"}, - {".pcast", "application/x-podcast"}, - {".pct", "image/pict"}, - {".pcx", "application/octet-stream"}, - {".pcz", "application/octet-stream"}, - {".pdf", "application/pdf"}, - {".pfb", "application/octet-stream"}, - {".pfm", "application/octet-stream"}, - {".pfx", "application/x-pkcs12"}, - {".pgm", "image/x-portable-graymap"}, - {".pic", "image/pict"}, - {".pict", "image/pict"}, - {".pkgdef", "text/plain"}, - {".pkgundef", "text/plain"}, - {".pko", "application/vnd.ms-pki.pko"}, - {".pls", "audio/scpls"}, - {".pma", "application/x-perfmon"}, - {".pmc", "application/x-perfmon"}, - {".pml", "application/x-perfmon"}, - {".pmr", "application/x-perfmon"}, - {".pmw", "application/x-perfmon"}, - {".png", "image/png"}, - {".pnm", "image/x-portable-anymap"}, - {".pnt", "image/x-macpaint"}, - {".pntg", "image/x-macpaint"}, - {".pnz", "image/png"}, - {".pot", "application/vnd.ms-powerpoint"}, - {".potm", "application/vnd.ms-powerpoint.template.macroEnabled.12"}, - {".potx", "application/vnd.openxmlformats-officedocument.presentationml.template"}, - {".ppa", "application/vnd.ms-powerpoint"}, - {".ppam", "application/vnd.ms-powerpoint.addin.macroEnabled.12"}, - {".ppm", "image/x-portable-pixmap"}, - {".pps", "application/vnd.ms-powerpoint"}, - {".ppsm", "application/vnd.ms-powerpoint.slideshow.macroEnabled.12"}, - {".ppsx", "application/vnd.openxmlformats-officedocument.presentationml.slideshow"}, - {".ppt", "application/vnd.ms-powerpoint"}, - {".pptm", "application/vnd.ms-powerpoint.presentation.macroEnabled.12"}, - {".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"}, - {".prf", "application/pics-rules"}, - {".prm", "application/octet-stream"}, - {".prx", "application/octet-stream"}, - {".ps", "application/postscript"}, - {".psc1", "application/PowerShell"}, - {".psd", "application/octet-stream"}, - {".psess", "application/xml"}, - {".psm", "application/octet-stream"}, - {".psp", "application/octet-stream"}, - {".pst", "application/vnd.ms-outlook"}, - {".pub", "application/x-mspublisher"}, - {".pwz", "application/vnd.ms-powerpoint"}, - {".qht", "text/x-html-insertion"}, - {".qhtm", "text/x-html-insertion"}, - {".qt", "video/quicktime"}, - {".qti", "image/x-quicktime"}, - {".qtif", "image/x-quicktime"}, - {".qtl", "application/x-quicktimeplayer"}, - {".qxd", "application/octet-stream"}, - {".ra", "audio/x-pn-realaudio"}, - {".ram", "audio/x-pn-realaudio"}, - {".rar", "application/x-rar-compressed"}, - {".ras", "image/x-cmu-raster"}, - {".rat", "application/rat-file"}, - {".rc", "text/plain"}, - {".rc2", "text/plain"}, - {".rct", "text/plain"}, - {".rdlc", "application/xml"}, - {".reg", "text/plain"}, - {".resx", "application/xml"}, - {".rf", "image/vnd.rn-realflash"}, - {".rgb", "image/x-rgb"}, - {".rgs", "text/plain"}, - {".rm", "application/vnd.rn-realmedia"}, - {".rmi", "audio/mid"}, - {".rmp", "application/vnd.rn-rn_music_package"}, - {".rmvb", "application/vnd.rn-realmedia-vbr"}, - {".roff", "application/x-troff"}, - {".rpm", "audio/x-pn-realaudio-plugin"}, - {".rqy", "text/x-ms-rqy"}, - {".rtf", "application/rtf"}, - {".rtx", "text/richtext"}, - {".rvt", "application/octet-stream"}, - {".ruleset", "application/xml"}, - {".s", "text/plain"}, - {".safariextz", "application/x-safari-safariextz"}, - {".scd", "application/x-msschedule"}, - {".scr", "text/plain"}, - {".sct", "text/scriptlet"}, - {".sd2", "audio/x-sd2"}, - {".sdp", "application/sdp"}, - {".sea", "application/octet-stream"}, - {".searchConnector-ms", "application/windows-search-connector+xml"}, - {".setpay", "application/set-payment-initiation"}, - {".setreg", "application/set-registration-initiation"}, - {".settings", "application/xml"}, - {".sgimb", "application/x-sgimb"}, - {".sgml", "text/sgml"}, - {".sh", "application/x-sh"}, - {".shar", "application/x-shar"}, - {".shtml", "text/html"}, - {".sit", "application/x-stuffit"}, - {".sitemap", "application/xml"}, - {".skin", "application/xml"}, - {".skp", "application/x-koan"}, - {".sldm", "application/vnd.ms-powerpoint.slide.macroEnabled.12"}, - {".sldx", "application/vnd.openxmlformats-officedocument.presentationml.slide"}, - {".slk", "application/vnd.ms-excel"}, - {".sln", "text/plain"}, - {".slupkg-ms", "application/x-ms-license"}, - {".smd", "audio/x-smd"}, - {".smi", "application/octet-stream"}, - {".smx", "audio/x-smd"}, - {".smz", "audio/x-smd"}, - {".snd", "audio/basic"}, - {".snippet", "application/xml"}, - {".snp", "application/octet-stream"}, - {".sql", "application/sql"}, - {".sol", "text/plain"}, - {".sor", "text/plain"}, - {".spc", "application/x-pkcs7-certificates"}, - {".spl", "application/futuresplash"}, - {".spx", "audio/ogg"}, - {".src", "application/x-wais-source"}, - {".srf", "text/plain"}, - {".SSISDeploymentManifest", "text/xml"}, - {".ssm", "application/streamingmedia"}, - {".sst", "application/vnd.ms-pki.certstore"}, - {".stl", "application/vnd.ms-pki.stl"}, - {".sv4cpio", "application/x-sv4cpio"}, - {".sv4crc", "application/x-sv4crc"}, - {".svc", "application/xml"}, - {".svg", "image/svg+xml"}, - {".swf", "application/x-shockwave-flash"}, - {".step", "application/step"}, - {".stp", "application/step"}, - {".t", "application/x-troff"}, - {".tar", "application/x-tar"}, - {".tcl", "application/x-tcl"}, - {".testrunconfig", "application/xml"}, - {".testsettings", "application/xml"}, - {".tex", "application/x-tex"}, - {".texi", "application/x-texinfo"}, - {".texinfo", "application/x-texinfo"}, - {".tgz", "application/x-compressed"}, - {".thmx", "application/vnd.ms-officetheme"}, - {".thn", "application/octet-stream"}, - {".tif", "image/tiff"}, - {".tiff", "image/tiff"}, - {".tlh", "text/plain"}, - {".tli", "text/plain"}, - {".toc", "application/octet-stream"}, - {".tr", "application/x-troff"}, - {".trm", "application/x-msterminal"}, - {".trx", "application/xml"}, - {".ts", "video/vnd.dlna.mpeg-tts"}, - {".tsv", "text/tab-separated-values"}, - {".ttf", "application/font-sfnt"}, - {".tts", "video/vnd.dlna.mpeg-tts"}, - {".txt", "text/plain"}, - {".u32", "application/octet-stream"}, - {".uls", "text/iuls"}, - {".user", "text/plain"}, - {".ustar", "application/x-ustar"}, - {".vb", "text/plain"}, - {".vbdproj", "text/plain"}, - {".vbk", "video/mpeg"}, - {".vbproj", "text/plain"}, - {".vbs", "text/vbscript"}, - {".vcf", "text/x-vcard"}, - {".vcproj", "application/xml"}, - {".vcs", "text/plain"}, - {".vcxproj", "application/xml"}, - {".vddproj", "text/plain"}, - {".vdp", "text/plain"}, - {".vdproj", "text/plain"}, - {".vdx", "application/vnd.ms-visio.viewer"}, - {".vml", "text/xml"}, - {".vscontent", "application/xml"}, - {".vsct", "text/xml"}, - {".vsd", "application/vnd.visio"}, - {".vsi", "application/ms-vsi"}, - {".vsix", "application/vsix"}, - {".vsixlangpack", "text/xml"}, - {".vsixmanifest", "text/xml"}, - {".vsmdi", "application/xml"}, - {".vspscc", "text/plain"}, - {".vss", "application/vnd.visio"}, - {".vsscc", "text/plain"}, - {".vssettings", "text/xml"}, - {".vssscc", "text/plain"}, - {".vst", "application/vnd.visio"}, - {".vstemplate", "text/xml"}, - {".vsto", "application/x-ms-vsto"}, - {".vsw", "application/vnd.visio"}, - {".vsx", "application/vnd.visio"}, - {".vtt", "text/vtt"}, - {".vtx", "application/vnd.visio"}, - {".wasm", "application/wasm"}, - {".wav", "audio/wav"}, - {".wave", "audio/wav"}, - {".wax", "audio/x-ms-wax"}, - {".wbk", "application/msword"}, - {".wbmp", "image/vnd.wap.wbmp"}, - {".wcm", "application/vnd.ms-works"}, - {".wdb", "application/vnd.ms-works"}, - {".wdp", "image/vnd.ms-photo"}, - {".webarchive", "application/x-safari-webarchive"}, - {".webm", "video/webm"}, - {".webp", "image/webp"}, /* https://en.wikipedia.org/wiki/WebP */ - {".webtest", "application/xml"}, - {".wiq", "application/xml"}, - {".wiz", "application/msword"}, - {".wks", "application/vnd.ms-works"}, - {".WLMP", "application/wlmoviemaker"}, - {".wlpginstall", "application/x-wlpg-detect"}, - {".wlpginstall3", "application/x-wlpg3-detect"}, - {".wm", "video/x-ms-wm"}, - {".wma", "audio/x-ms-wma"}, - {".wmd", "application/x-ms-wmd"}, - {".wmf", "application/x-msmetafile"}, - {".wml", "text/vnd.wap.wml"}, - {".wmlc", "application/vnd.wap.wmlc"}, - {".wmls", "text/vnd.wap.wmlscript"}, - {".wmlsc", "application/vnd.wap.wmlscriptc"}, - {".wmp", "video/x-ms-wmp"}, - {".wmv", "video/x-ms-wmv"}, - {".wmx", "video/x-ms-wmx"}, - {".wmz", "application/x-ms-wmz"}, - {".woff", "application/font-woff"}, - {".woff2", "application/font-woff2"}, - {".wpl", "application/vnd.ms-wpl"}, - {".wps", "application/vnd.ms-works"}, - {".wri", "application/x-mswrite"}, - {".wrl", "x-world/x-vrml"}, - {".wrz", "x-world/x-vrml"}, - {".wsc", "text/scriptlet"}, - {".wsdl", "text/xml"}, - {".wvx", "video/x-ms-wvx"}, - {".x", "application/directx"}, - {".xaf", "x-world/x-vrml"}, - {".xaml", "application/xaml+xml"}, - {".xap", "application/x-silverlight-app"}, - {".xbap", "application/x-ms-xbap"}, - {".xbm", "image/x-xbitmap"}, - {".xdr", "text/plain"}, - {".xht", "application/xhtml+xml"}, - {".xhtml", "application/xhtml+xml"}, - {".xla", "application/vnd.ms-excel"}, - {".xlam", "application/vnd.ms-excel.addin.macroEnabled.12"}, - {".xlc", "application/vnd.ms-excel"}, - {".xld", "application/vnd.ms-excel"}, - {".xlk", "application/vnd.ms-excel"}, - {".xll", "application/vnd.ms-excel"}, - {".xlm", "application/vnd.ms-excel"}, - {".xls", "application/vnd.ms-excel"}, - {".xlsb", "application/vnd.ms-excel.sheet.binary.macroEnabled.12"}, - {".xlsm", "application/vnd.ms-excel.sheet.macroEnabled.12"}, - {".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}, - {".xlt", "application/vnd.ms-excel"}, - {".xltm", "application/vnd.ms-excel.template.macroEnabled.12"}, - {".xltx", "application/vnd.openxmlformats-officedocument.spreadsheetml.template"}, - {".xlw", "application/vnd.ms-excel"}, - {".xml", "text/xml"}, - {".xmp", "application/octet-stream"}, - {".xmta", "application/xml"}, - {".xof", "x-world/x-vrml"}, - {".XOML", "text/plain"}, - {".xpm", "image/x-xpixmap"}, - {".xps", "application/vnd.ms-xpsdocument"}, - {".xrm-ms", "text/xml"}, - {".xsc", "application/xml"}, - {".xsd", "text/xml"}, - {".xsf", "text/xml"}, - {".xsl", "text/xml"}, - {".xslt", "text/xml"}, - {".xsn", "application/octet-stream"}, - {".xss", "application/xml"}, - {".xspf", "application/xspf+xml"}, - {".xtp", "application/octet-stream"}, - {".xwd", "image/x-xwindowdump"}, - {".z", "application/x-compress"}, - {".zip", "application/zip"}, + private static IDictionary BuildMappings() + { + var mappings = new Dictionary(StringComparer.OrdinalIgnoreCase) { + {".323", "text/h323"}, + {".3g2", "video/3gpp2"}, + {".3gp", "video/3gpp"}, + {".3gp2", "video/3gpp2"}, + {".3gpp", "video/3gpp"}, + {".7z", "application/x-7z-compressed"}, + {".aa", "audio/audible"}, + {".AAC", "audio/aac"}, + {".aaf", "application/octet-stream"}, + {".aax", "audio/vnd.audible.aax"}, + {".ac3", "audio/ac3"}, + {".aca", "application/octet-stream"}, + {".accda", "application/msaccess.addin"}, + {".accdb", "application/msaccess"}, + {".accdc", "application/msaccess.cab"}, + {".accde", "application/msaccess"}, + {".accdr", "application/msaccess.runtime"}, + {".accdt", "application/msaccess"}, + {".accdw", "application/msaccess.webapplication"}, + {".accft", "application/msaccess.ftemplate"}, + {".acx", "application/internet-property-stream"}, + {".AddIn", "text/xml"}, + {".ade", "application/msaccess"}, + {".adobebridge", "application/x-bridge-url"}, + {".adp", "application/msaccess"}, + {".ADT", "audio/vnd.dlna.adts"}, + {".ADTS", "audio/aac"}, + {".afm", "application/octet-stream"}, + {".ai", "application/postscript"}, + {".aif", "audio/aiff"}, + {".aifc", "audio/aiff"}, + {".aiff", "audio/aiff"}, + {".air", "application/vnd.adobe.air-application-installer-package+zip"}, + {".amc", "application/mpeg"}, + {".anx", "application/annodex"}, + {".apk", "application/vnd.android.package-archive"}, + {".apng", "image/apng"}, + {".application", "application/x-ms-application"}, + {".art", "image/x-jg"}, + {".asa", "application/xml"}, + {".asax", "application/xml"}, + {".ascx", "application/xml"}, + {".asd", "application/octet-stream"}, + {".asf", "video/x-ms-asf"}, + {".ashx", "application/xml"}, + {".asi", "application/octet-stream"}, + {".asm", "text/plain"}, + {".asmx", "application/xml"}, + {".aspx", "application/xml"}, + {".asr", "video/x-ms-asf"}, + {".asx", "video/x-ms-asf"}, + {".atom", "application/atom+xml"}, + {".au", "audio/basic"}, + {".avci", "image/avci"}, + {".avcs", "image/avcs"}, + {".avi", "video/x-msvideo"}, + {".avif", "image/avif"}, + {".avifs", "image/avif-sequence"}, + {".axa", "audio/annodex"}, + {".axs", "application/olescript"}, + {".axv", "video/annodex"}, + {".bas", "text/plain"}, + {".bcpio", "application/x-bcpio"}, + {".bin", "application/octet-stream"}, + {".bmp", "image/bmp"}, + {".c", "text/plain"}, + {".cab", "application/octet-stream"}, + {".caf", "audio/x-caf"}, + {".calx", "application/vnd.ms-office.calx"}, + {".cat", "application/vnd.ms-pki.seccat"}, + {".cc", "text/plain"}, + {".cd", "text/plain"}, + {".cdda", "audio/aiff"}, + {".cdf", "application/x-cdf"}, + {".cer", "application/x-x509-ca-cert"}, + {".cfg", "text/plain"}, + {".chm", "application/octet-stream"}, + {".class", "application/x-java-applet"}, + {".clp", "application/x-msclip"}, + {".cmd", "text/plain"}, + {".cmx", "image/x-cmx"}, + {".cnf", "text/plain"}, + {".cod", "image/cis-cod"}, + {".config", "application/xml"}, + {".contact", "text/x-ms-contact"}, + {".coverage", "application/xml"}, + {".cpio", "application/x-cpio"}, + {".cpp", "text/plain"}, + {".crd", "application/x-mscardfile"}, + {".crl", "application/pkix-crl"}, + {".crt", "application/x-x509-ca-cert"}, + {".cs", "text/plain"}, + {".csdproj", "text/plain"}, + {".csh", "application/x-csh"}, + {".csproj", "text/plain"}, + {".css", "text/css"}, + {".csv", "text/csv"}, + {".cur", "application/octet-stream"}, + {".czx", "application/x-czx"}, + {".cxx", "text/plain"}, + {".dat", "application/octet-stream"}, + {".datasource", "application/xml"}, + {".dbproj", "text/plain"}, + {".dcr", "application/x-director"}, + {".def", "text/plain"}, + {".deploy", "application/octet-stream"}, + {".der", "application/x-x509-ca-cert"}, + {".dgml", "application/xml"}, + {".dib", "image/bmp"}, + {".dif", "video/x-dv"}, + {".dir", "application/x-director"}, + {".disco", "text/xml"}, + {".divx", "video/divx"}, + {".dll", "application/x-msdownload"}, + {".dll.config", "text/xml"}, + {".dlm", "text/dlm"}, + {".doc", "application/msword"}, + {".docm", "application/vnd.ms-word.document.macroEnabled.12"}, + {".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"}, + {".dot", "application/msword"}, + {".dotm", "application/vnd.ms-word.template.macroEnabled.12"}, + {".dotx", "application/vnd.openxmlformats-officedocument.wordprocessingml.template"}, + {".dsp", "application/octet-stream"}, + {".dsw", "text/plain"}, + {".dtd", "text/xml"}, + {".dtsConfig", "text/xml"}, + {".dv", "video/x-dv"}, + {".dvi", "application/x-dvi"}, + {".dwf", "drawing/x-dwf"}, + {".dwg", "application/acad"}, + {".dwp", "application/octet-stream"}, + {".dxf", "application/x-dxf"}, + {".dxr", "application/x-director"}, + {".eml", "message/rfc822"}, + {".emf", "image/emf"}, + {".emz", "application/octet-stream"}, + {".eot", "application/vnd.ms-fontobject"}, + {".eps", "application/postscript"}, + {".es", "application/ecmascript"}, + {".etl", "application/etl"}, + {".etx", "text/x-setext"}, + {".evy", "application/envoy"}, + {".exe", "application/vnd.microsoft.portable-executable"}, + {".exe.config", "text/xml"}, + {".f4v", "video/mp4"}, + {".fdf", "application/vnd.fdf"}, + {".fif", "application/fractals"}, + {".filters", "application/xml"}, + {".fla", "application/octet-stream"}, + {".flac", "audio/flac"}, + {".flr", "x-world/x-vrml"}, + {".flv", "video/x-flv"}, + {".fsscript", "application/fsharp-script"}, + {".fsx", "application/fsharp-script"}, + {".generictest", "application/xml"}, + {".geojson", "application/geo+json"}, + {".gif", "image/gif"}, + {".gpx", "application/gpx+xml"}, + {".group", "text/x-ms-group"}, + {".gsm", "audio/x-gsm"}, + {".gtar", "application/x-gtar"}, + {".gz", "application/x-gzip"}, + {".h", "text/plain"}, + {".hdf", "application/x-hdf"}, + {".hdml", "text/x-hdml"}, + {".heic", "image/heic"}, + {".heics", "image/heic-sequence"}, + {".heif", "image/heif"}, + {".heifs", "image/heif-sequence"}, + {".hhc", "application/x-oleobject"}, + {".hhk", "application/octet-stream"}, + {".hhp", "application/octet-stream"}, + {".hlp", "application/winhlp"}, + {".hpp", "text/plain"}, + {".hqx", "application/mac-binhex40"}, + {".hta", "application/hta"}, + {".htc", "text/x-component"}, + {".htm", "text/html"}, + {".html", "text/html"}, + {".htt", "text/webviewhtml"}, + {".hxa", "application/xml"}, + {".hxc", "application/xml"}, + {".hxd", "application/octet-stream"}, + {".hxe", "application/xml"}, + {".hxf", "application/xml"}, + {".hxh", "application/octet-stream"}, + {".hxi", "application/octet-stream"}, + {".hxk", "application/xml"}, + {".hxq", "application/octet-stream"}, + {".hxr", "application/octet-stream"}, + {".hxs", "application/octet-stream"}, + {".hxt", "text/html"}, + {".hxv", "application/xml"}, + {".hxw", "application/octet-stream"}, + {".hxx", "text/plain"}, + {".i", "text/plain"}, + {".ical", "text/calendar"}, + {".icalendar", "text/calendar"}, + {".ico", "image/x-icon"}, + {".ics", "text/calendar"}, + {".idl", "text/plain"}, + {".ief", "image/ief"}, + {".ifb", "text/calendar"}, + {".iii", "application/x-iphone"}, + {".inc", "text/plain"}, + {".inf", "application/octet-stream"}, + {".ini", "text/plain"}, + {".inl", "text/plain"}, + {".ins", "application/x-internet-signup"}, + {".ipa", "application/x-itunes-ipa"}, + {".ipg", "application/x-itunes-ipg"}, + {".ipproj", "text/plain"}, + {".ipsw", "application/x-itunes-ipsw"}, + {".iqy", "text/x-ms-iqy"}, + {".isp", "application/x-internet-signup"}, + {".isma", "application/octet-stream"}, + {".ismv", "application/octet-stream"}, + {".ite", "application/x-itunes-ite"}, + {".itlp", "application/x-itunes-itlp"}, + {".itms", "application/x-itunes-itms"}, + {".itpc", "application/x-itunes-itpc"}, + {".IVF", "video/x-ivf"}, + {".jar", "application/java-archive"}, + {".java", "application/octet-stream"}, + {".jck", "application/liquidmotion"}, + {".jcz", "application/liquidmotion"}, + {".jfif", "image/pjpeg"}, + {".jnlp", "application/x-java-jnlp-file"}, + {".jpb", "application/octet-stream"}, + {".jpe", "image/jpeg"}, + {".jpeg", "image/jpeg"}, + {".jpg", "image/jpeg"}, + {".js", "application/javascript"}, + {".json", "application/json"}, + {".jsx", "text/jscript"}, + {".jsxbin", "text/plain"}, + {".key", "application/vnd.apple.keynote"}, + {".latex", "application/x-latex"}, + {".library-ms", "application/windows-library+xml"}, + {".lit", "application/x-ms-reader"}, + {".loadtest", "application/xml"}, + {".lpk", "application/octet-stream"}, + {".lsf", "video/x-la-asf"}, + {".lst", "text/plain"}, + {".lsx", "video/x-la-asf"}, + {".lzh", "application/octet-stream"}, + {".m13", "application/x-msmediaview"}, + {".m14", "application/x-msmediaview"}, + {".m1v", "video/mpeg"}, + {".m2t", "video/vnd.dlna.mpeg-tts"}, + {".m2ts", "video/vnd.dlna.mpeg-tts"}, + {".m2v", "video/mpeg"}, + {".m3u", "audio/x-mpegurl"}, + {".m3u8", "audio/x-mpegurl"}, + {".m4a", "audio/m4a"}, + {".m4b", "audio/m4b"}, + {".m4p", "audio/m4p"}, + {".m4r", "audio/x-m4r"}, + {".m4v", "video/x-m4v"}, + {".mac", "image/x-macpaint"}, + {".mak", "text/plain"}, + {".man", "application/x-troff-man"}, + {".manifest", "application/x-ms-manifest"}, + {".map", "text/plain"}, + {".master", "application/xml"}, + {".mbox", "application/mbox"}, + {".mda", "application/msaccess"}, + {".mdb", "application/x-msaccess"}, + {".mde", "application/msaccess"}, + {".mdp", "application/octet-stream"}, + {".me", "application/x-troff-me"}, + {".mfp", "application/x-shockwave-flash"}, + {".mht", "message/rfc822"}, + {".mhtml", "message/rfc822"}, + {".mid", "audio/mid"}, + {".midi", "audio/mid"}, + {".mix", "application/octet-stream"}, + {".mk", "text/plain"}, + {".mk3d", "video/x-matroska-3d"}, + {".mka", "audio/x-matroska"}, + {".mkv", "video/x-matroska"}, + {".mmf", "application/x-smaf"}, + {".mno", "text/xml"}, + {".mny", "application/x-msmoney"}, + {".mod", "video/mpeg"}, + {".mov", "video/quicktime"}, + {".movie", "video/x-sgi-movie"}, + {".mp2", "video/mpeg"}, + {".mp2v", "video/mpeg"}, + {".mp3", "audio/mpeg"}, + {".mp4", "video/mp4"}, + {".mp4v", "video/mp4"}, + {".mpa", "video/mpeg"}, + {".mpe", "video/mpeg"}, + {".mpeg", "video/mpeg"}, + {".mpf", "application/vnd.ms-mediapackage"}, + {".mpg", "video/mpeg"}, + {".mpp", "application/vnd.ms-project"}, + {".mpv2", "video/mpeg"}, + {".mqv", "video/quicktime"}, + {".ms", "application/x-troff-ms"}, + {".msg", "application/vnd.ms-outlook"}, + {".msi", "application/octet-stream"}, + {".mso", "application/octet-stream"}, + {".mts", "video/vnd.dlna.mpeg-tts"}, + {".mtx", "application/xml"}, + {".mvb", "application/x-msmediaview"}, + {".mvc", "application/x-miva-compiled"}, + {".mxf", "application/mxf"}, + {".mxp", "application/x-mmxp"}, + {".nc", "application/x-netcdf"}, + {".nsc", "video/x-ms-asf"}, + {".numbers", "application/vnd.apple.numbers"}, + {".nws", "message/rfc822"}, + {".ocx", "application/octet-stream"}, + {".oda", "application/oda"}, + {".odb", "application/vnd.oasis.opendocument.database"}, + {".odc", "application/vnd.oasis.opendocument.chart"}, + {".odf", "application/vnd.oasis.opendocument.formula"}, + {".odg", "application/vnd.oasis.opendocument.graphics"}, + {".odh", "text/plain"}, + {".odi", "application/vnd.oasis.opendocument.image"}, + {".odl", "text/plain"}, + {".odm", "application/vnd.oasis.opendocument.text-master"}, + {".odp", "application/vnd.oasis.opendocument.presentation"}, + {".ods", "application/vnd.oasis.opendocument.spreadsheet"}, + {".odt", "application/vnd.oasis.opendocument.text"}, + {".oga", "audio/ogg"}, + {".ogg", "audio/ogg"}, + {".ogv", "video/ogg"}, + {".ogx", "application/ogg"}, + {".one", "application/onenote"}, + {".onea", "application/onenote"}, + {".onepkg", "application/onenote"}, + {".onetmp", "application/onenote"}, + {".onetoc", "application/onenote"}, + {".onetoc2", "application/onenote"}, + {".opus", "audio/ogg"}, + {".orderedtest", "application/xml"}, + {".osdx", "application/opensearchdescription+xml"}, + {".otf", "application/font-sfnt"}, + {".otg", "application/vnd.oasis.opendocument.graphics-template"}, + {".oth", "application/vnd.oasis.opendocument.text-web"}, + {".otp", "application/vnd.oasis.opendocument.presentation-template"}, + {".ots", "application/vnd.oasis.opendocument.spreadsheet-template"}, + {".ott", "application/vnd.oasis.opendocument.text-template"}, + {".oxps", "application/oxps"}, + {".oxt", "application/vnd.openofficeorg.extension"}, + {".p10", "application/pkcs10"}, + {".p12", "application/x-pkcs12"}, + {".p7b", "application/x-pkcs7-certificates"}, + {".p7c", "application/pkcs7-mime"}, + {".p7m", "application/pkcs7-mime"}, + {".p7r", "application/x-pkcs7-certreqresp"}, + {".p7s", "application/pkcs7-signature"}, + {".pages", "application/vnd.apple.pages"}, + {".pbm", "image/x-portable-bitmap"}, + {".pcast", "application/x-podcast"}, + {".pct", "image/pict"}, + {".pcx", "application/octet-stream"}, + {".pcz", "application/octet-stream"}, + {".pdf", "application/pdf"}, + {".pfb", "application/octet-stream"}, + {".pfm", "application/octet-stream"}, + {".pfx", "application/x-pkcs12"}, + {".pgm", "image/x-portable-graymap"}, + {".pic", "image/pict"}, + {".pict", "image/pict"}, + {".pkgdef", "text/plain"}, + {".pkgundef", "text/plain"}, + {".pko", "application/vnd.ms-pki.pko"}, + {".pls", "audio/scpls"}, + {".pma", "application/x-perfmon"}, + {".pmc", "application/x-perfmon"}, + {".pml", "application/x-perfmon"}, + {".pmr", "application/x-perfmon"}, + {".pmw", "application/x-perfmon"}, + {".png", "image/png"}, + {".pnm", "image/x-portable-anymap"}, + {".pnt", "image/x-macpaint"}, + {".pntg", "image/x-macpaint"}, + {".pnz", "image/png"}, + {".pot", "application/vnd.ms-powerpoint"}, + {".potm", "application/vnd.ms-powerpoint.template.macroEnabled.12"}, + {".potx", "application/vnd.openxmlformats-officedocument.presentationml.template"}, + {".ppa", "application/vnd.ms-powerpoint"}, + {".ppam", "application/vnd.ms-powerpoint.addin.macroEnabled.12"}, + {".ppm", "image/x-portable-pixmap"}, + {".pps", "application/vnd.ms-powerpoint"}, + {".ppsm", "application/vnd.ms-powerpoint.slideshow.macroEnabled.12"}, + {".ppsx", "application/vnd.openxmlformats-officedocument.presentationml.slideshow"}, + {".ppt", "application/vnd.ms-powerpoint"}, + {".pptm", "application/vnd.ms-powerpoint.presentation.macroEnabled.12"}, + {".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"}, + {".prf", "application/pics-rules"}, + {".prm", "application/octet-stream"}, + {".prx", "application/octet-stream"}, + {".ps", "application/postscript"}, + {".psc1", "application/PowerShell"}, + {".psd", "application/octet-stream"}, + {".psess", "application/xml"}, + {".psm", "application/octet-stream"}, + {".psp", "application/octet-stream"}, + {".pst", "application/vnd.ms-outlook"}, + {".pub", "application/x-mspublisher"}, + {".pwz", "application/vnd.ms-powerpoint"}, + {".qht", "text/x-html-insertion"}, + {".qhtm", "text/x-html-insertion"}, + {".qt", "video/quicktime"}, + {".qti", "image/x-quicktime"}, + {".qtif", "image/x-quicktime"}, + {".qtl", "application/x-quicktimeplayer"}, + {".qxd", "application/octet-stream"}, + {".ra", "audio/x-pn-realaudio"}, + {".ram", "audio/x-pn-realaudio"}, + {".rar", "application/x-rar-compressed"}, + {".ras", "image/x-cmu-raster"}, + {".rat", "application/rat-file"}, + {".rc", "text/plain"}, + {".rc2", "text/plain"}, + {".rct", "text/plain"}, + {".rdlc", "application/xml"}, + {".reg", "text/plain"}, + {".resx", "application/xml"}, + {".rf", "image/vnd.rn-realflash"}, + {".rgb", "image/x-rgb"}, + {".rgs", "text/plain"}, + {".rm", "application/vnd.rn-realmedia"}, + {".rmi", "audio/mid"}, + {".rmp", "application/vnd.rn-rn_music_package"}, + {".rmvb", "application/vnd.rn-realmedia-vbr"}, + {".roff", "application/x-troff"}, + {".rpm", "audio/x-pn-realaudio-plugin"}, + {".rqy", "text/x-ms-rqy"}, + {".rtf", "application/rtf"}, + {".rtx", "text/richtext"}, + {".rvt", "application/octet-stream"}, + {".ruleset", "application/xml"}, + {".s", "text/plain"}, + {".safariextz", "application/x-safari-safariextz"}, + {".scd", "application/x-msschedule"}, + {".scr", "text/plain"}, + {".sct", "text/scriptlet"}, + {".sd2", "audio/x-sd2"}, + {".sdp", "application/sdp"}, + {".sea", "application/octet-stream"}, + {".searchConnector-ms", "application/windows-search-connector+xml"}, + {".setpay", "application/set-payment-initiation"}, + {".setreg", "application/set-registration-initiation"}, + {".settings", "application/xml"}, + {".sgimb", "application/x-sgimb"}, + {".sgml", "text/sgml"}, + {".sh", "application/x-sh"}, + {".shar", "application/x-shar"}, + {".shtml", "text/html"}, + {".sit", "application/x-stuffit"}, + {".sitemap", "application/xml"}, + {".skin", "application/xml"}, + {".skp", "application/x-koan"}, + {".sldm", "application/vnd.ms-powerpoint.slide.macroEnabled.12"}, + {".sldx", "application/vnd.openxmlformats-officedocument.presentationml.slide"}, + {".slk", "application/vnd.ms-excel"}, + {".sln", "text/plain"}, + {".slupkg-ms", "application/x-ms-license"}, + {".smd", "audio/x-smd"}, + {".smi", "application/octet-stream"}, + {".smx", "audio/x-smd"}, + {".smz", "audio/x-smd"}, + {".snd", "audio/basic"}, + {".snippet", "application/xml"}, + {".snp", "application/octet-stream"}, + {".sql", "application/sql"}, + {".sol", "text/plain"}, + {".sor", "text/plain"}, + {".spc", "application/x-pkcs7-certificates"}, + {".spl", "application/futuresplash"}, + {".spx", "audio/ogg"}, + {".src", "application/x-wais-source"}, + {".srf", "text/plain"}, + {".SSISDeploymentManifest", "text/xml"}, + {".ssm", "application/streamingmedia"}, + {".sst", "application/vnd.ms-pki.certstore"}, + {".stl", "application/vnd.ms-pki.stl"}, + {".sv4cpio", "application/x-sv4cpio"}, + {".sv4crc", "application/x-sv4crc"}, + {".svc", "application/xml"}, + {".svg", "image/svg+xml"}, + {".swf", "application/x-shockwave-flash"}, + {".step", "application/step"}, + {".stp", "application/step"}, + {".t", "application/x-troff"}, + {".tar", "application/x-tar"}, + {".tcl", "application/x-tcl"}, + {".testrunconfig", "application/xml"}, + {".testsettings", "application/xml"}, + {".tex", "application/x-tex"}, + {".texi", "application/x-texinfo"}, + {".texinfo", "application/x-texinfo"}, + {".tgz", "application/x-compressed"}, + {".thmx", "application/vnd.ms-officetheme"}, + {".thn", "application/octet-stream"}, + {".tif", "image/tiff"}, + {".tiff", "image/tiff"}, + {".tlh", "text/plain"}, + {".tli", "text/plain"}, + {".toc", "application/octet-stream"}, + {".tr", "application/x-troff"}, + {".trm", "application/x-msterminal"}, + {".trx", "application/xml"}, + {".ts", "video/vnd.dlna.mpeg-tts"}, + {".tsv", "text/tab-separated-values"}, + {".ttf", "application/font-sfnt"}, + {".tts", "video/vnd.dlna.mpeg-tts"}, + {".txt", "text/plain"}, + {".u32", "application/octet-stream"}, + {".uls", "text/iuls"}, + {".user", "text/plain"}, + {".ustar", "application/x-ustar"}, + {".vb", "text/plain"}, + {".vbdproj", "text/plain"}, + {".vbk", "video/mpeg"}, + {".vbproj", "text/plain"}, + {".vbs", "text/vbscript"}, + {".vcf", "text/x-vcard"}, + {".vcproj", "application/xml"}, + {".vcs", "text/plain"}, + {".vcxproj", "application/xml"}, + {".vddproj", "text/plain"}, + {".vdp", "text/plain"}, + {".vdproj", "text/plain"}, + {".vdx", "application/vnd.ms-visio.viewer"}, + {".vml", "text/xml"}, + {".vscontent", "application/xml"}, + {".vsct", "text/xml"}, + {".vsd", "application/vnd.visio"}, + {".vsi", "application/ms-vsi"}, + {".vsix", "application/vsix"}, + {".vsixlangpack", "text/xml"}, + {".vsixmanifest", "text/xml"}, + {".vsmdi", "application/xml"}, + {".vspscc", "text/plain"}, + {".vss", "application/vnd.visio"}, + {".vsscc", "text/plain"}, + {".vssettings", "text/xml"}, + {".vssscc", "text/plain"}, + {".vst", "application/vnd.visio"}, + {".vstemplate", "text/xml"}, + {".vsto", "application/x-ms-vsto"}, + {".vsw", "application/vnd.visio"}, + {".vsx", "application/vnd.visio"}, + {".vtt", "text/vtt"}, + {".vtx", "application/vnd.visio"}, + {".wasm", "application/wasm"}, + {".wav", "audio/wav"}, + {".wave", "audio/wav"}, + {".wax", "audio/x-ms-wax"}, + {".wbk", "application/msword"}, + {".wbmp", "image/vnd.wap.wbmp"}, + {".wcm", "application/vnd.ms-works"}, + {".wdb", "application/vnd.ms-works"}, + {".wdp", "image/vnd.ms-photo"}, + {".webarchive", "application/x-safari-webarchive"}, + {".webm", "video/webm"}, + {".webp", "image/webp"}, /* https://en.wikipedia.org/wiki/WebP */ + {".webtest", "application/xml"}, + {".wiq", "application/xml"}, + {".wiz", "application/msword"}, + {".wks", "application/vnd.ms-works"}, + {".WLMP", "application/wlmoviemaker"}, + {".wlpginstall", "application/x-wlpg-detect"}, + {".wlpginstall3", "application/x-wlpg3-detect"}, + {".wm", "video/x-ms-wm"}, + {".wma", "audio/x-ms-wma"}, + {".wmd", "application/x-ms-wmd"}, + {".wmf", "application/x-msmetafile"}, + {".wml", "text/vnd.wap.wml"}, + {".wmlc", "application/vnd.wap.wmlc"}, + {".wmls", "text/vnd.wap.wmlscript"}, + {".wmlsc", "application/vnd.wap.wmlscriptc"}, + {".wmp", "video/x-ms-wmp"}, + {".wmv", "video/x-ms-wmv"}, + {".wmx", "video/x-ms-wmx"}, + {".wmz", "application/x-ms-wmz"}, + {".woff", "application/font-woff"}, + {".woff2", "application/font-woff2"}, + {".wpl", "application/vnd.ms-wpl"}, + {".wps", "application/vnd.ms-works"}, + {".wri", "application/x-mswrite"}, + {".wrl", "x-world/x-vrml"}, + {".wrz", "x-world/x-vrml"}, + {".wsc", "text/scriptlet"}, + {".wsdl", "text/xml"}, + {".wvx", "video/x-ms-wvx"}, + {".x", "application/directx"}, + {".xaf", "x-world/x-vrml"}, + {".xaml", "application/xaml+xml"}, + {".xap", "application/x-silverlight-app"}, + {".xbap", "application/x-ms-xbap"}, + {".xbm", "image/x-xbitmap"}, + {".xdr", "text/plain"}, + {".xht", "application/xhtml+xml"}, + {".xhtml", "application/xhtml+xml"}, + {".xla", "application/vnd.ms-excel"}, + {".xlam", "application/vnd.ms-excel.addin.macroEnabled.12"}, + {".xlc", "application/vnd.ms-excel"}, + {".xld", "application/vnd.ms-excel"}, + {".xlk", "application/vnd.ms-excel"}, + {".xll", "application/vnd.ms-excel"}, + {".xlm", "application/vnd.ms-excel"}, + {".xls", "application/vnd.ms-excel"}, + {".xlsb", "application/vnd.ms-excel.sheet.binary.macroEnabled.12"}, + {".xlsm", "application/vnd.ms-excel.sheet.macroEnabled.12"}, + {".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}, + {".xlt", "application/vnd.ms-excel"}, + {".xltm", "application/vnd.ms-excel.template.macroEnabled.12"}, + {".xltx", "application/vnd.openxmlformats-officedocument.spreadsheetml.template"}, + {".xlw", "application/vnd.ms-excel"}, + {".xml", "text/xml"}, + {".xmp", "application/octet-stream"}, + {".xmta", "application/xml"}, + {".xof", "x-world/x-vrml"}, + {".XOML", "text/plain"}, + {".xpm", "image/x-xpixmap"}, + {".xps", "application/vnd.ms-xpsdocument"}, + {".xrm-ms", "text/xml"}, + {".xsc", "application/xml"}, + {".xsd", "text/xml"}, + {".xsf", "text/xml"}, + {".xsl", "text/xml"}, + {".xslt", "text/xml"}, + {".xsn", "application/octet-stream"}, + {".xss", "application/xml"}, + {".xspf", "application/xspf+xml"}, + {".xtp", "application/octet-stream"}, + {".xwd", "image/x-xwindowdump"}, + {".z", "application/x-compress"}, + {".zip", "application/zip"}, - {"application/fsharp-script", ".fsx"}, - {"application/msaccess", ".adp"}, - {"application/msword", ".doc"}, - {"application/octet-stream", ".bin"}, - {"application/onenote", ".one"}, - {"application/postscript", ".eps"}, - {"application/step", ".step"}, - {"application/vnd.apple.keynote", ".key"}, - {"application/vnd.apple.numbers", ".numbers"}, - {"application/vnd.apple.pages", ".pages"}, - {"application/vnd.ms-excel", ".xls"}, - {"application/vnd.ms-powerpoint", ".ppt"}, - {"application/vnd.ms-works", ".wks"}, - {"application/vnd.visio", ".vsd"}, - {"application/x-director", ".dir"}, - {"application/x-msdos-program", ".exe"}, - {"application/x-shockwave-flash", ".swf"}, - {"application/x-x509-ca-cert", ".cer"}, - {"application/x-zip-compressed", ".zip"}, - {"application/xhtml+xml", ".xhtml"}, - {"application/x-iwork-keynote-sffkey", ".key"}, - {"application/x-iwork-numbers-sffnumbers", ".numbers"}, - {"application/x-iwork-pages-sffpages", ".pages"}, - {"application/xml", ".xml"}, // anomaly, .xml -> text/xml, but application/xml -> many things, but all are xml, so safest is .xml - {"audio/aac", ".AAC"}, - {"audio/aiff", ".aiff"}, - {"audio/basic", ".snd"}, - {"audio/mid", ".midi"}, - {"audio/mp4", ".m4a"}, // one way mapping only, mime -> ext - {"audio/ogg", ".ogg"}, - {"audio/ogg; codecs=opus", ".opus"}, - {"audio/wav", ".wav"}, - {"audio/x-m4a", ".m4a"}, - {"audio/x-mpegurl", ".m3u"}, - {"audio/x-pn-realaudio", ".ra"}, - {"audio/x-smd", ".smd"}, - {"image/bmp", ".bmp"}, - {"image/heic", ".heic"}, - {"image/heif", ".heif"}, - {"image/jpeg", ".jpg"}, - {"image/pict", ".pic"}, - {"image/png", ".png"}, // Defined in [RFC-2045], [RFC-2048] - {"image/x-png", ".png"}, // See https://www.w3.org/TR/PNG/#A-Media-type :"It is recommended that implementations also recognize the media type "image/x-png"." - {"image/tiff", ".tiff"}, - {"image/x-macpaint", ".mac"}, - {"image/x-quicktime", ".qti"}, - {"message/rfc822", ".eml"}, - {"text/calendar", ".ics"}, - {"text/html", ".html"}, - {"text/plain", ".txt"}, - {"text/scriptlet", ".wsc"}, - {"text/xml", ".xml"}, - {"video/3gpp", ".3gp"}, - {"video/3gpp2", ".3gp2"}, - {"video/mp4", ".mp4"}, - {"video/mpeg", ".mpg"}, - {"video/quicktime", ".mov"}, - {"video/vnd.dlna.mpeg-tts", ".m2t"}, - {"video/x-dv", ".dv"}, - {"video/x-la-asf", ".lsf"}, - {"video/x-ms-asf", ".asf"}, - {"x-world/x-vrml", ".xof"} - }; + {"application/fsharp-script", ".fsx"}, + {"application/msaccess", ".adp"}, + {"application/msword", ".doc"}, + {"application/octet-stream", ".bin"}, + {"application/onenote", ".one"}, + {"application/postscript", ".eps"}, + {"application/step", ".step"}, + {"application/vnd.apple.keynote", ".key"}, + {"application/vnd.apple.numbers", ".numbers"}, + {"application/vnd.apple.pages", ".pages"}, + {"application/vnd.ms-excel", ".xls"}, + {"application/vnd.ms-powerpoint", ".ppt"}, + {"application/vnd.ms-works", ".wks"}, + {"application/vnd.visio", ".vsd"}, + {"application/x-director", ".dir"}, + {"application/x-msdos-program", ".exe"}, + {"application/x-shockwave-flash", ".swf"}, + {"application/x-x509-ca-cert", ".cer"}, + {"application/x-zip-compressed", ".zip"}, + {"application/xhtml+xml", ".xhtml"}, + {"application/x-iwork-keynote-sffkey", ".key"}, + {"application/x-iwork-numbers-sffnumbers", ".numbers"}, + {"application/x-iwork-pages-sffpages", ".pages"}, + {"application/xml", ".xml"}, // anomaly, .xml -> text/xml, but application/xml -> many things, but all are xml, so safest is .xml + {"audio/aac", ".AAC"}, + {"audio/aiff", ".aiff"}, + {"audio/basic", ".snd"}, + {"audio/mid", ".midi"}, + {"audio/mp4", ".m4a"}, // one way mapping only, mime -> ext + {"audio/ogg", ".ogg"}, + {"audio/ogg; codecs=opus", ".opus"}, + {"audio/wav", ".wav"}, + {"audio/x-m4a", ".m4a"}, + {"audio/x-mpegurl", ".m3u"}, + {"audio/x-pn-realaudio", ".ra"}, + {"audio/x-smd", ".smd"}, + {"image/bmp", ".bmp"}, + {"image/heic", ".heic"}, + {"image/heif", ".heif"}, + {"image/jpeg", ".jpg"}, + {"image/pict", ".pic"}, + {"image/png", ".png"}, // Defined in [RFC-2045], [RFC-2048] + {"image/x-png", ".png"}, // See https://www.w3.org/TR/PNG/#A-Media-type :"It is recommended that implementations also recognize the media type "image/x-png"." + {"image/tiff", ".tiff"}, + {"image/x-macpaint", ".mac"}, + {"image/x-quicktime", ".qti"}, + {"message/rfc822", ".eml"}, + {"text/calendar", ".ics"}, + {"text/html", ".html"}, + {"text/plain", ".txt"}, + {"text/scriptlet", ".wsc"}, + {"text/xml", ".xml"}, + {"video/3gpp", ".3gp"}, + {"video/3gpp2", ".3gp2"}, + {"video/mp4", ".mp4"}, + {"video/mpeg", ".mpg"}, + {"video/quicktime", ".mov"}, + {"video/vnd.dlna.mpeg-tts", ".m2t"}, + {"video/x-dv", ".dv"}, + {"video/x-la-asf", ".lsf"}, + {"video/x-ms-asf", ".asf"}, + {"x-world/x-vrml", ".xof"} + }; - var cache = mappings.ToList(); // need ToList() to avoid modifying while still enumerating + var cache = mappings.ToList(); // need ToList() to avoid modifying while still enumerating - foreach (var mapping in cache) + foreach (var mapping in cache) + { + if (!mappings.ContainsKey(mapping.Value)) { - if (!mappings.ContainsKey(mapping.Value)) - { - mappings.Add(mapping.Value, mapping.Key); - } + mappings.Add(mapping.Value, mapping.Key); } - - return mappings; } - /// - /// Tries to get the type of the MIME from the provided string. - /// - /// The filename or extension. - /// The variable to store the MIME type. - /// The MIME type. - /// - public static bool TryGetMimeType(string name, out string? mimeType) + return mappings; + } + + /// + /// Tries to get the type of the MIME from the provided string. + /// + /// The filename or extension. + /// The variable to store the MIME type. + /// The MIME type. + /// + public static bool TryGetMimeType(string name, out string? mimeType) + { + if (name == null) { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } + throw new ArgumentNullException(nameof(name)); + } - var indexQuestionMark = name.IndexOf(QuestionMark, StringComparison.Ordinal); - if (indexQuestionMark != -1) - { - name = name.Remove(indexQuestionMark); - } + var indexQuestionMark = name.IndexOf(QuestionMark, StringComparison.Ordinal); + if (indexQuestionMark != -1) + { + name = name.Remove(indexQuestionMark); + } - if (!name.StartsWith(Dot)) + if (!name.StartsWith(Dot)) + { + var index = name.LastIndexOf(Dot); + if (index != -1 && name.Length > index + 1) { - var index = name.LastIndexOf(Dot); - if (index != -1 && name.Length > index + 1) - { - name = name[(index + 1)..]; - } - - name = Dot + name; + name = name[(index + 1)..]; } - return _mappings.Value.TryGetValue(name, out mimeType); + name = Dot + name; } - /// - /// Gets the type of the MIME from the provided string. - /// - /// The filename or extension. - /// The MIME type. - /// - public static string? GetMimeType(string str) => TryGetMimeType(str, out string? result) ? result : DefaultMimeType; + return _mappings.Value.TryGetValue(name, out mimeType); + } - /// - /// Gets the extension from the provided MIME type. - /// - /// Type of the MIME. - /// if set to true, throws error if extension's not found. - /// The extension. - /// - /// - public static string GetExtension(string mimeType, bool throwErrorIfNotFound = true) - { - if (mimeType == null) - { - throw new ArgumentNullException(nameof(mimeType)); - } + /// + /// Gets the type of the MIME from the provided string. + /// + /// The filename or extension. + /// The MIME type. + /// + public static string? GetMimeType(string str) => TryGetMimeType(str, out string? result) ? result : DefaultMimeType; - if (mimeType.StartsWith(Dot)) - { - throw new ArgumentException("Requested mime type is not valid: " + mimeType); - } + /// + /// Gets the extension from the provided MIME type. + /// + /// Type of the MIME. + /// if set to true, throws error if extension's not found. + /// The extension. + /// + /// + public static string GetExtension(string mimeType, bool throwErrorIfNotFound = true) + { + if (mimeType == null) + { + throw new ArgumentNullException(nameof(mimeType)); + } - if (_mappings.Value.TryGetValue(mimeType, out string? extension)) - { - return extension; - } + if (mimeType.StartsWith(Dot)) + { + throw new ArgumentException("Requested mime type is not valid: " + mimeType); + } - if (throwErrorIfNotFound) - { - throw new ArgumentException("Requested mime type is not registered: " + mimeType); - } + if (_mappings.Value.TryGetValue(mimeType, out string? extension)) + { + return extension; + } - return string.Empty; + if (throwErrorIfNotFound) + { + throw new ArgumentException("Requested mime type is not registered: " + mimeType); } + + return string.Empty; } } \ No newline at end of file diff --git a/01-Core/Jinget.Core/Utilities/HumanizerUtility.cs b/01-Core/Jinget.Core/Utilities/HumanizerUtility.cs index 41cd041..9771084 100644 --- a/01-Core/Jinget.Core/Utilities/HumanizerUtility.cs +++ b/01-Core/Jinget.Core/Utilities/HumanizerUtility.cs @@ -1,10 +1,9 @@ -namespace Jinget.Core.Utilities +namespace Jinget.Core.Utilities; + +public static class HumanizerUtility { - public static class HumanizerUtility + public static bool Not(bool possibility) { - public static bool Not(bool possibility) - { - return !possibility; - } + return !possibility; } } diff --git a/01-Core/Jinget.Core/Utilities/Json/IgnorePropertiesResolver.cs b/01-Core/Jinget.Core/Utilities/Json/IgnorePropertiesResolver.cs index 872350c..8b36766 100644 --- a/01-Core/Jinget.Core/Utilities/Json/IgnorePropertiesResolver.cs +++ b/01-Core/Jinget.Core/Utilities/Json/IgnorePropertiesResolver.cs @@ -3,24 +3,23 @@ using System.Collections.Generic; using System.Reflection; -namespace Jinget.Core.Utilities.Json +namespace Jinget.Core.Utilities.Json; + +/// +/// ignore the given properties, while serializing an object +/// +public class IgnorePropertiesResolver(IEnumerable propNamesToIgnore) : DefaultContractResolver { - /// - /// ignore the given properties, while serializing an object - /// - public class IgnorePropertiesResolver(IEnumerable propNamesToIgnore) : DefaultContractResolver - { - private readonly HashSet _ignoreProps = new(propNamesToIgnore); + private readonly HashSet _ignoreProps = new(propNamesToIgnore); - protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) + protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) + { + JsonProperty property = base.CreateProperty(member, memberSerialization); + if (!string.IsNullOrWhiteSpace(property.PropertyName) && + _ignoreProps.Contains(property.PropertyName)) { - JsonProperty property = base.CreateProperty(member, memberSerialization); - if (!string.IsNullOrWhiteSpace(property.PropertyName) && - _ignoreProps.Contains(property.PropertyName)) - { - property.ShouldSerialize = _ => false; - } - return property; + property.ShouldSerialize = _ => false; } + return property; } } diff --git a/01-Core/Jinget.Core/Utilities/Json/JsonUtility.cs b/01-Core/Jinget.Core/Utilities/Json/JsonUtility.cs index 7456d45..a7368eb 100644 --- a/01-Core/Jinget.Core/Utilities/Json/JsonUtility.cs +++ b/01-Core/Jinget.Core/Utilities/Json/JsonUtility.cs @@ -1,83 +1,82 @@ using Newtonsoft.Json.Linq; -namespace Jinget.Core.Utilities.Json +namespace Jinget.Core.Utilities.Json; + +public class JsonUtility { - public class JsonUtility + /// + /// check if given string is a valid json string or not. + /// + /// + /// + public static bool IsValid(string input) { - /// - /// check if given string is a valid json string or not. - /// - /// - /// - public static bool IsValid(string input) + if (string.IsNullOrWhiteSpace(input)) { return false; } + input = input.Trim(); + if ((input.StartsWith("{") && input.EndsWith("}")) || //For object + (input.StartsWith("[") && input.EndsWith("]"))) //For array { - if (string.IsNullOrWhiteSpace(input)) { return false; } - input = input.Trim(); - if ((input.StartsWith("{") && input.EndsWith("}")) || //For object - (input.StartsWith("[") && input.EndsWith("]"))) //For array + try { - try - { - var tmpObj = JToken.Parse(input); - return true; - } - catch - { - return false; - } + var tmpObj = JToken.Parse(input); + return true; + } + catch + { + return false; } - - return false; } - /// - /// unescape json string and replace the illegal strings - /// - public static string Unescape(string json, bool removeNewLine = true) - { - json = json - .Replace(@"\\\""", "\"") // ==? \\"" ==> " - .Replace(@"\""", "\"") //==> "" ==> " - .Replace("\"[{\"", "[{\"")//==> "[{" ==> [{" - .Replace("\"}]\"", "\"}]") //==> "}]" ==> "}] - .Replace("\"{", "{")// =="{ ==> { - .Replace("}\"", "}")//==> }" ==> } - .Replace("\"[", "[")//==> "[ ==> [ - .Replace("]\"", "]") //==> ]" ==> ] + return false; + } - //order of the follwoings are matter! - .Replace(":\"\",", ":\"---\",")//==> :"", ==> :"---", - .Replace(":\"\"}", ":\"---\"}")//==> :""} ==> :"---"} - .Replace(":\"\"", ":\"")//==> :"" ==> :" - .Replace("\"\",", "\",");//==> "" ==> " + /// + /// unescape json string and replace the illegal strings + /// + public static string Unescape(string json, bool removeNewLine = true) + { + json = json + .Replace(@"\\\""", "\"") // ==? \\"" ==> " + .Replace(@"\""", "\"") //==> "" ==> " + .Replace("\"[{\"", "[{\"")//==> "[{" ==> [{" + .Replace("\"}]\"", "\"}]") //==> "}]" ==> "}] + .Replace("\"{", "{")// =="{ ==> { + .Replace("}\"", "}")//==> }" ==> } + .Replace("\"[", "[")//==> "[ ==> [ + .Replace("]\"", "]") //==> ]" ==> ] - if (removeNewLine) - { - json = json - .Replace(System.Environment.NewLine, "") - .Replace(@"\r\n", ""); - } + //order of the follwoings are matter! + .Replace(":\"\",", ":\"---\",")//==> :"", ==> :"---", + .Replace(":\"\"}", ":\"---\"}")//==> :""} ==> :"---"} + .Replace(":\"\"", ":\"")//==> :"" ==> :" + .Replace("\"\",", "\",");//==> "" ==> " - return json; + if (removeNewLine) + { + json = json + .Replace(System.Environment.NewLine, "") + .Replace(@"\r\n", ""); } - /// - /// merge with using value - /// - /// - public static string Merge(string json1, string json2, string propertyName, bool unescapeResult = true) + return json; + } + + /// + /// merge with using value + /// + /// + public static string Merge(string json1, string json2, string propertyName, bool unescapeResult = true) + { + var token = JToken.Parse(json1); + if (token is JObject) { - var token = JToken.Parse(json1); - if (token is JObject) - { - var opJson = JObject.Parse(json1); - opJson.Add(propertyName, JToken.Parse(json2)); - if (unescapeResult) - return Unescape(opJson.ToString()); - return opJson.ToString(); - } - else - throw new System.Exception($"{nameof(json1)} should be an object"); + var opJson = JObject.Parse(json1); + opJson.Add(propertyName, JToken.Parse(json2)); + if (unescapeResult) + return Unescape(opJson.ToString()); + return opJson.ToString(); } + else + throw new System.Exception($"{nameof(json1)} should be an object"); } } \ No newline at end of file diff --git a/01-Core/Jinget.Core/Utilities/Json/NonPublicSetterResolver.cs b/01-Core/Jinget.Core/Utilities/Json/NonPublicSetterResolver.cs index 5c1b397..34b2d65 100644 --- a/01-Core/Jinget.Core/Utilities/Json/NonPublicSetterResolver.cs +++ b/01-Core/Jinget.Core/Utilities/Json/NonPublicSetterResolver.cs @@ -2,30 +2,29 @@ using Newtonsoft.Json; using Newtonsoft.Json.Serialization; -namespace Jinget.Core.Utilities.Json +namespace Jinget.Core.Utilities.Json; + +/// +/// Serialize even properties with non public setter +/// +public class NonPublicSetterResolver : DefaultContractResolver { - /// - /// Serialize even properties with non public setter - /// - public class NonPublicSetterResolver : DefaultContractResolver + protected override JsonProperty CreateProperty( + MemberInfo member, + MemberSerialization memberSerialization) { - protected override JsonProperty CreateProperty( - MemberInfo member, - MemberSerialization memberSerialization) - { - var prop = base.CreateProperty(member, memberSerialization); + var prop = base.CreateProperty(member, memberSerialization); - if (!prop.Writable) + if (!prop.Writable) + { + var property = member as PropertyInfo; + if (property != null) { - var property = member as PropertyInfo; - if (property != null) - { - var hasNonPublicSetter = property.GetSetMethod(true) != null; - prop.Writable = hasNonPublicSetter; - } + var hasNonPublicSetter = property.GetSetMethod(true) != null; + prop.Writable = hasNonPublicSetter; } - - return prop; } + + return prop; } } \ No newline at end of file diff --git a/01-Core/Jinget.Core/Utilities/JwtUtility.cs b/01-Core/Jinget.Core/Utilities/JwtUtility.cs index a1ac15c..955a4a6 100644 --- a/01-Core/Jinget.Core/Utilities/JwtUtility.cs +++ b/01-Core/Jinget.Core/Utilities/JwtUtility.cs @@ -9,142 +9,141 @@ using System.Text; using System.Threading.Tasks; -namespace Jinget.Core.Utilities +namespace Jinget.Core.Utilities; + +public class JwtUtility { - public class JwtUtility + public static JwtSecurityToken? Read(string token, string scheme = "Bearer") { - public static JwtSecurityToken? Read(string token, string scheme = "Bearer") + try { - try - { - if (token.StartsWith($"{scheme} ", StringComparison.InvariantCultureIgnoreCase)) - token = token[7..]; - return new JwtSecurityTokenHandler().ReadToken(token) as JwtSecurityToken; - } - catch - { - return null; - } + if (token.StartsWith($"{scheme} ", StringComparison.InvariantCultureIgnoreCase)) + token = token[7..]; + return new JwtSecurityTokenHandler().ReadToken(token) as JwtSecurityToken; } + catch + { + return null; + } + } - /// - /// Check if token is valid or not. This method only checks for the validity of lifetime, audience and issuer - /// - /// Expected list of audiences. It is expected that token was issued for one of these audiences - /// Expected issuer. It is expected that token was issued for this issuer - /// The given token is valid if it is valid for the next minute(s) - public static async Task IsValidAsync(string token, - IEnumerable? validAudiences = null, - string? validissuer = null, - int minuteOffset = 5) + /// + /// Check if token is valid or not. This method only checks for the validity of lifetime, audience and issuer + /// + /// Expected list of audiences. It is expected that token was issued for one of these audiences + /// Expected issuer. It is expected that token was issued for this issuer + /// The given token is valid if it is valid for the next minute(s) + public static async Task IsValidAsync(string token, + IEnumerable? validAudiences = null, + string? validissuer = null, + int minuteOffset = 5) + { + var result = await new JwtSecurityTokenHandler().ValidateTokenAsync(token, new TokenValidationParameters() { - var result = await new JwtSecurityTokenHandler().ValidateTokenAsync(token, new TokenValidationParameters() - { - ClockSkew = TimeSpan.FromMinutes(minuteOffset), + ClockSkew = TimeSpan.FromMinutes(minuteOffset), - ValidateLifetime = true, - LifetimeValidator = (DateTime? notBefore, DateTime? expires, SecurityToken securityToken, TokenValidationParameters validationParameters) => - { - var clonedParameters = validationParameters.Clone(); - clonedParameters.LifetimeValidator = null; - Validators.ValidateLifetime(notBefore, expires, securityToken, clonedParameters); + ValidateLifetime = true, + LifetimeValidator = (DateTime? notBefore, DateTime? expires, SecurityToken securityToken, TokenValidationParameters validationParameters) => + { + var clonedParameters = validationParameters.Clone(); + clonedParameters.LifetimeValidator = null; + Validators.ValidateLifetime(notBefore, expires, securityToken, clonedParameters); - return true; - }, + return true; + }, - ValidateAudience = true, - ValidAudiences = validAudiences, - AudienceValidator = (IEnumerable? audiences, SecurityToken securityToken, TokenValidationParameters validationParameters) => + ValidateAudience = true, + ValidAudiences = validAudiences, + AudienceValidator = (IEnumerable? audiences, SecurityToken securityToken, TokenValidationParameters validationParameters) => + { + if (validAudiences != null && validAudiences.Any()) { - if (validAudiences != null && validAudiences.Any()) - { - var clonedParameters = validationParameters.Clone(); - clonedParameters.AudienceValidator = null; - Validators.ValidateAudience(audiences, securityToken, clonedParameters); - } - return true; - }, + var clonedParameters = validationParameters.Clone(); + clonedParameters.AudienceValidator = null; + Validators.ValidateAudience(audiences, securityToken, clonedParameters); + } + return true; + }, - ValidateIssuer = true, - ValidIssuer = validissuer, - IssuerValidator = (string issuer, SecurityToken securityToken, TokenValidationParameters validationParameters) => + ValidateIssuer = true, + ValidIssuer = validissuer, + IssuerValidator = (string issuer, SecurityToken securityToken, TokenValidationParameters validationParameters) => + { + string resultIssuer = ""; + if (!string.IsNullOrWhiteSpace(validissuer)) { - string resultIssuer = ""; - if (!string.IsNullOrWhiteSpace(validissuer)) - { - var clonedParameters = validationParameters.Clone(); - clonedParameters.IssuerValidator = null; - resultIssuer = Validators.ValidateIssuer(issuer, securityToken, clonedParameters); - } - return resultIssuer; - }, + var clonedParameters = validationParameters.Clone(); + clonedParameters.IssuerValidator = null; + resultIssuer = Validators.ValidateIssuer(issuer, securityToken, clonedParameters); + } + return resultIssuer; + }, - ValidateIssuerSigningKey = false, - SignatureValidator = (string token, TokenValidationParameters parameters) => new JwtSecurityToken(token) - }); - if (result.Exception != null) - throw result.Exception; + ValidateIssuerSigningKey = false, + SignatureValidator = (string token, TokenValidationParameters parameters) => new JwtSecurityToken(token) + }); + if (result.Exception != null) + throw result.Exception; - return result.IsValid; - } + return result.IsValid; + } - /// - /// get given claim info stored inside the given token - /// - /// - public static IEnumerable? GetClaim(string token, string claim) + /// + /// get given claim info stored inside the given token + /// + /// + public static IEnumerable? GetClaim(string token, string claim) + { + try { - try - { - var info = Read(token); - if (info != null) - return info.Claims.Where(x => x.Type == claim); - else - return null; - } - catch - { + var info = Read(token); + if (info != null) + return info.Claims.Where(x => x.Type == claim); + else return null; - } } - - /// - /// Create a new JWT token - /// - public static string Generate(string username, string[] roles, JwtModel options, int expirationInMinute = 15) + catch { - var claims = new List - { - new(ClaimTypes.NameIdentifier,username), - new(ClaimTypes.Name,username), - }; - foreach (var item in roles) - { - claims.Add(new Claim(ClaimTypes.Role, item)); - } - return Generate(claims, options, expirationInMinute); + return null; } + } - /// - /// Create a new JWT token - /// - public static string Generate(IEnumerable claims, JwtModel options, int expirationInMinute = 15) + /// + /// Create a new JWT token + /// + public static string Generate(string username, string[] roles, JwtModel options, int expirationInMinute = 15) + { + var claims = new List { - if (string.IsNullOrWhiteSpace(options.SecretKey) || options.SecretKey.Length < 32) - { - throw new Exception("key should be a string with at least 32 chars"); - } - var token = new JwtSecurityToken( - options.Issuer, - options.Audience, - claims, - options.NotBefore, - DateTime.Now.AddMinutes(expirationInMinute), - new SigningCredentials( - new SymmetricSecurityKey(Encoding.UTF8.GetBytes(options.SecretKey)), - SecurityAlgorithms.HmacSha256)); + new(ClaimTypes.NameIdentifier,username), + new(ClaimTypes.Name,username), + }; + foreach (var item in roles) + { + claims.Add(new Claim(ClaimTypes.Role, item)); + } + return Generate(claims, options, expirationInMinute); + } - return new JwtSecurityTokenHandler().WriteToken(token); + /// + /// Create a new JWT token + /// + public static string Generate(IEnumerable claims, JwtModel options, int expirationInMinute = 15) + { + if (string.IsNullOrWhiteSpace(options.SecretKey) || options.SecretKey.Length < 32) + { + throw new Exception("key should be a string with at least 32 chars"); } + var token = new JwtSecurityToken( + options.Issuer, + options.Audience, + claims, + options.NotBefore, + DateTime.Now.AddMinutes(expirationInMinute), + new SigningCredentials( + new SymmetricSecurityKey(Encoding.UTF8.GetBytes(options.SecretKey)), + SecurityAlgorithms.HmacSha256)); + + return new JwtSecurityTokenHandler().WriteToken(token); } } \ No newline at end of file diff --git a/01-Core/Jinget.Core/Utilities/Parser/DatabaseParser/DatabaseParserUtility.cs b/01-Core/Jinget.Core/Utilities/Parser/DatabaseParser/DatabaseParserUtility.cs index e0e0641..58ed66d 100644 --- a/01-Core/Jinget.Core/Utilities/Parser/DatabaseParser/DatabaseParserUtility.cs +++ b/01-Core/Jinget.Core/Utilities/Parser/DatabaseParser/DatabaseParserUtility.cs @@ -1,20 +1,19 @@ using System.Collections.Generic; -namespace Jinget.Core.Utilities.Parser +namespace Jinget.Core.Utilities.Parser; + +public static class DatabaseParserUtility { - public static class DatabaseParserUtility + public static Dictionary ParseConnectionString(string connectionString) { - public static Dictionary ParseConnectionString(string connectionString) + string[] parts = connectionString.Split(";", System.StringSplitOptions.RemoveEmptyEntries); + var keyValuePairs = new Dictionary(); + foreach (var item in parts) { - string[] parts = connectionString.Split(";", System.StringSplitOptions.RemoveEmptyEntries); - var keyValuePairs = new Dictionary(); - foreach (var item in parts) - { - var keyValues = item.Split('=', System.StringSplitOptions.RemoveEmptyEntries); - if (keyValues.Length == 2) - keyValuePairs.Add(keyValues[0].Trim(), keyValues[1].Trim()); - } - return keyValuePairs; + var keyValues = item.Split('=', System.StringSplitOptions.RemoveEmptyEntries); + if (keyValues.Length == 2) + keyValuePairs.Add(keyValues[0].Trim(), keyValues[1].Trim()); } + return keyValuePairs; } } \ No newline at end of file diff --git a/01-Core/Jinget.Core/Utilities/Parser/DatabaseParser/SqlServer/SqlServerParserUtility.cs b/01-Core/Jinget.Core/Utilities/Parser/DatabaseParser/SqlServer/SqlServerParserUtility.cs index 65e592b..218d803 100644 --- a/01-Core/Jinget.Core/Utilities/Parser/DatabaseParser/SqlServer/SqlServerParserUtility.cs +++ b/01-Core/Jinget.Core/Utilities/Parser/DatabaseParser/SqlServer/SqlServerParserUtility.cs @@ -1,9 +1,8 @@ using System.Collections.Generic; -namespace Jinget.Core.Utilities.Parser.DatabaseParser.SqlServer +namespace Jinget.Core.Utilities.Parser.DatabaseParser.SqlServer; + +public static class SqlServerParserUtility { - public static class SqlServerParserUtility - { - public static Dictionary ParseConnectionString(string connectionString) => DatabaseParserUtility.ParseConnectionString(connectionString); - } + public static Dictionary ParseConnectionString(string connectionString) => DatabaseParserUtility.ParseConnectionString(connectionString); } \ No newline at end of file diff --git a/01-Core/Jinget.Core/Utilities/SOAPUtility.cs b/01-Core/Jinget.Core/Utilities/SOAPUtility.cs index 2880a07..91c08bf 100644 --- a/01-Core/Jinget.Core/Utilities/SOAPUtility.cs +++ b/01-Core/Jinget.Core/Utilities/SOAPUtility.cs @@ -1,40 +1,28 @@ -using AutoMapper; -using System.Xml.Serialization; +namespace Jinget.Core.Utilities; -namespace Jinget.Core.Utilities +public abstract class SOAPRequestBase { -#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - public abstract class SOAPRequestBase - { - protected readonly IMapper Mapper; - - public SOAPRequestBase() { } - public SOAPRequestBase(IMapper mapper) => Mapper = mapper; + public SOAPRequestBase() { } - public abstract (TEnvelope envelope, TRequest request) CreateEnvelope(TViewModel vm); - } - - public abstract class SOAPRequestBase - { - protected readonly IMapper Mapper; + public abstract (TEnvelope envelope, TRequest request) CreateEnvelope(TViewModel vm); +} - public SOAPRequestBase() { } - public SOAPRequestBase(IMapper mapper) => Mapper = mapper; +public abstract class SOAPRequestBase +{ + public SOAPRequestBase() { } - public abstract (TEnvelope envelope, TRequest request) CreateEnvelope(); - } + public abstract (TEnvelope envelope, TRequest request) CreateEnvelope(); +} - public abstract class SOAPEnvelopeBase +public abstract class SOAPEnvelopeBase +{ + public virtual XmlSerializerNamespaces GetRequestNamespaces() { - public virtual XmlSerializerNamespaces GetRequestNamespaces() - { - XmlSerializerNamespaces ns = new(); - ns.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance/"); - ns.Add("xsd", "http://www.w3.org/2001/XMLSchema"); - ns.Add("soap", "http://schemas.xmlsoap.org/soap/envelope/"); + XmlSerializerNamespaces ns = new(); + ns.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance/"); + ns.Add("xsd", "http://www.w3.org/2001/XMLSchema"); + ns.Add("soap", "http://schemas.xmlsoap.org/soap/envelope/"); - return ns; - } + return ns; } -#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. } diff --git a/01-Core/Jinget.Core/Utilities/StringUtility.cs b/01-Core/Jinget.Core/Utilities/StringUtility.cs index 7713d68..113bc9a 100644 --- a/01-Core/Jinget.Core/Utilities/StringUtility.cs +++ b/01-Core/Jinget.Core/Utilities/StringUtility.cs @@ -3,57 +3,56 @@ using System.Linq; using System.Security.Cryptography; -namespace Jinget.Core.Utilities +namespace Jinget.Core.Utilities; + +public static class StringUtility { - public static class StringUtility + /// + /// Create a random string with given using given + /// + public static string GetRandomString(int length, IEnumerable characterSet) { - /// - /// Create a random string with given using given - /// - public static string GetRandomString(int length, IEnumerable characterSet) + if (length < 0) + throw new ArgumentException("Jinget Says: length must not be negative", nameof(length)); + if (length > int.MaxValue / 8) // 250 million chars ought to be enough for anybody + throw new ArgumentException("Jinget Says: length is too big", nameof(length)); + if (characterSet is null) + throw new ArgumentNullException(nameof(characterSet)); + var characterArray = characterSet.Distinct().ToArray(); + if (characterArray.Length == 0) + throw new ArgumentException("Jinget Says: characterSet must not be empty", nameof(characterSet)); + + var bytes = new byte[length * 8]; + var result = new char[length]; + using (var cryptoProvider = RandomNumberGenerator.Create()) { - if (length < 0) - throw new ArgumentException("Jinget Says: length must not be negative", nameof(length)); - if (length > int.MaxValue / 8) // 250 million chars ought to be enough for anybody - throw new ArgumentException("Jinget Says: length is too big", nameof(length)); - if (characterSet is null) - throw new ArgumentNullException(nameof(characterSet)); - var characterArray = characterSet.Distinct().ToArray(); - if (characterArray.Length == 0) - throw new ArgumentException("Jinget Says: characterSet must not be empty", nameof(characterSet)); - - var bytes = new byte[length * 8]; - var result = new char[length]; - using (var cryptoProvider = RandomNumberGenerator.Create()) - { - cryptoProvider.GetBytes(bytes); - } - for (int i = 0; i < length; i++) - { - ulong value = BitConverter.ToUInt64(bytes, i * 8); - result[i] = characterArray[value % (uint)characterArray.Length]; - } - return new string(result); + cryptoProvider.GetBytes(bytes); } - - /// - /// check if given string contains only numeric characters - /// - public static bool IsDigitOnly(string input) + for (int i = 0; i < length; i++) { - foreach (char c in input) - { - if (c < '0' || c > '9') - return false; - } + ulong value = BitConverter.ToUInt64(bytes, i * 8); + result[i] = characterArray[value % (uint)characterArray.Length]; + } + return new string(result); + } - return true; + /// + /// check if given string contains only numeric characters + /// + public static bool IsDigitOnly(string input) + { + foreach (char c in input) + { + if (c < '0' || c > '9') + return false; } - public static string GetEnglishChars(bool lowerCase) => lowerCase ? "abcdefghijklmnopqrstuvwxyz" : "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + return true; + } - public static string GetEnglishDigits() => "1234567890"; + public static string GetEnglishChars(bool lowerCase) => lowerCase ? "abcdefghijklmnopqrstuvwxyz" : "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - public static List GetFarsiChars() => ['ا', 'ب', 'پ', 'ت', 'ث', 'ج', 'چ', 'ح', 'خ', 'د', 'ذ', 'ر', 'ز', 'ژ', 'س', 'ش', 'ص', 'ض', 'ط', 'ظ', 'ع', 'غ', 'ف', 'ق', 'ک', 'گ', 'ل', 'م', 'ن', 'و', 'ه', 'ی']; - } + public static string GetEnglishDigits() => "1234567890"; + + public static List GetFarsiChars() => ['ا', 'ب', 'پ', 'ت', 'ث', 'ج', 'چ', 'ح', 'خ', 'د', 'ذ', 'ر', 'ز', 'ژ', 'س', 'ش', 'ص', 'ض', 'ط', 'ظ', 'ع', 'غ', 'ف', 'ق', 'ک', 'گ', 'ل', 'م', 'ن', 'و', 'ه', 'ی']; } diff --git a/01-Core/Jinget.Core/Utilities/XmlUtility.cs b/01-Core/Jinget.Core/Utilities/XmlUtility.cs index 2d5d76b..1b9e3f3 100644 --- a/01-Core/Jinget.Core/Utilities/XmlUtility.cs +++ b/01-Core/Jinget.Core/Utilities/XmlUtility.cs @@ -8,76 +8,75 @@ using System.Xml.Linq; using System.Xml.Serialization; -namespace Jinget.Core.Utilities +namespace Jinget.Core.Utilities; + +public class XmlUtility { - public class XmlUtility + /// remove ?xml tag + /// if null passed, removes unnecessary xsi and xsd namespaces + /// + public static string SerializeToXml(object input, bool omitXmlDeclaration = false, XmlSerializerNamespaces? ns = null) { - /// remove ?xml tag - /// if null passed, removes unnecessary xsi and xsd namespaces - /// - public static string SerializeToXml(object input, bool omitXmlDeclaration = false, XmlSerializerNamespaces? ns = null) - { - var settings = new XmlWriterSettings { OmitXmlDeclaration = omitXmlDeclaration }; + var settings = new XmlWriterSettings { OmitXmlDeclaration = omitXmlDeclaration }; - XmlSerializer serializer = new(input.GetType()); - using var strWriter = new StringWriter(); - using XmlWriter writer = XmlWriter.Create(strWriter, settings); - serializer.Serialize(writer, input, ns); - return strWriter.ToString(); - } + XmlSerializer serializer = new(input.GetType()); + using var strWriter = new StringWriter(); + using XmlWriter writer = XmlWriter.Create(strWriter, settings); + serializer.Serialize(writer, input, ns); + return strWriter.ToString(); + } - /// - /// Serialize object to SOAP message xml string - /// input type in this serialization method needs to be marked as Serializable - /// - public static string SerializeToSoapXml(object input) + /// + /// Serialize object to SOAP message xml string + /// input type in this serialization method needs to be marked as Serializable + /// + public static string SerializeToSoapXml(object input) + { + using MemoryStream memStream = new(); + SoapFormatter formatter = new() { - using MemoryStream memStream = new(); - SoapFormatter formatter = new() - { - AssemblyFormat = FormatterAssemblyStyle.Simple - }; - formatter.Serialize(memStream, input); - return Encoding.UTF8.GetString(memStream.GetBuffer()); - } + AssemblyFormat = FormatterAssemblyStyle.Simple + }; + formatter.Serialize(memStream, input); + return Encoding.UTF8.GetString(memStream.GetBuffer()); + } - /// - /// Find first descendant which it's local name is equal to T.Name and tries to deserialize that descendant to 'T' type - /// - /// Name of 'T' should equal to a descendant's local name - public static T? DeserializeXmlDescendantsFirst(string xmlInput) - { - XmlSerializer serializer = new(typeof(T)); - string? subXmlString = XDocument.Parse(xmlInput)?.Root?.Descendants().FirstOrDefault(x => x.Name.LocalName.Equals(typeof(T).Name))?.ToString(); + /// + /// Find first descendant which it's local name is equal to T.Name and tries to deserialize that descendant to 'T' type + /// + /// Name of 'T' should equal to a descendant's local name + public static T? DeserializeXmlDescendantsFirst(string xmlInput) + { + XmlSerializer serializer = new(typeof(T)); + string? subXmlString = XDocument.Parse(xmlInput)?.Root?.Descendants().FirstOrDefault(x => x.Name.LocalName.Equals(typeof(T).Name))?.ToString(); - if (subXmlString == null) - return default; - using var reader = new StringReader(subXmlString); - var deserializedResult = serializer.Deserialize(reader); - return deserializedResult == null ? default : (T)deserializedResult; - } + if (subXmlString == null) + return default; + using var reader = new StringReader(subXmlString); + var deserializedResult = serializer.Deserialize(reader); + return deserializedResult == null ? default : (T)deserializedResult; + } - /// - /// Find all descendant which their local names are equal to T.Name and tries to deserialize that descendants to 'T' type - /// - /// Name of 'T' should equal to a descendant's local name - public static List DeserializeXmlDescendantsAll(string xmlInput) - { - XmlSerializer serializer = new(typeof(T)); - List descendants = []; + /// + /// Find all descendant which their local names are equal to T.Name and tries to deserialize that descendants to 'T' type + /// + /// Name of 'T' should equal to a descendant's local name + public static List DeserializeXmlDescendantsAll(string xmlInput) + { + XmlSerializer serializer = new(typeof(T)); + List descendants = []; - var xmlDescendants = XDocument.Parse(xmlInput)?.Root?.Descendants().Where(x => x.Name.LocalName.Equals(typeof(T).Name)); - if (xmlDescendants != null) + var xmlDescendants = XDocument.Parse(xmlInput)?.Root?.Descendants().Where(x => x.Name.LocalName.Equals(typeof(T).Name)); + if (xmlDescendants != null) + { + foreach (var item in xmlDescendants) { - foreach (var item in xmlDescendants) - { - var reader = new StringReader(item.ToString()); - var deserializedResult = serializer.Deserialize(reader); - descendants.Add(deserializedResult == null ? default : (T)deserializedResult); - } + var reader = new StringReader(item.ToString()); + var deserializedResult = serializer.Deserialize(reader); + descendants.Add(deserializedResult == null ? default : (T)deserializedResult); } - - return descendants; } + + return descendants; } } diff --git a/03-Infrastructure/Jinget.Logger/Configuration/ApplicationBuilderExtensions.cs b/03-Infrastructure/Jinget.Logger/Configuration/ApplicationBuilderExtensions.cs index ad3446e..fae49ae 100644 --- a/03-Infrastructure/Jinget.Logger/Configuration/ApplicationBuilderExtensions.cs +++ b/03-Infrastructure/Jinget.Logger/Configuration/ApplicationBuilderExtensions.cs @@ -1,19 +1,18 @@ using Jinget.Logger.Configuration.Middlewares; using Microsoft.AspNetCore.Builder; -namespace Jinget.Logger.Configuration +namespace Jinget.Logger.Configuration; + +public static class ApplicationBuilderExtensions { - public static class ApplicationBuilderExtensions + /// + /// Add logging required middlewares to pipeline + /// + public static IApplicationBuilder UseJingetLogging(this IApplicationBuilder app) { - /// - /// Add logging required middlewares to pipeline - /// - public static IApplicationBuilder UseJingetLogging(this IApplicationBuilder app) - { - app.UseMiddleware(); - app.UseMiddleware(); + app.UseMiddleware(); + app.UseMiddleware(); - return app; - } + return app; } } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/Configuration/BaseConfiguration.cs b/03-Infrastructure/Jinget.Logger/Configuration/BaseConfiguration.cs index b4d06b5..8d4735a 100644 --- a/03-Infrastructure/Jinget.Logger/Configuration/BaseConfiguration.cs +++ b/03-Infrastructure/Jinget.Logger/Configuration/BaseConfiguration.cs @@ -4,14 +4,13 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; -namespace Jinget.Logger.Configuration +namespace Jinget.Logger.Configuration; + +internal static class BaseConfiguration { - internal static class BaseConfiguration + internal static void ConfigurePrerequisites(this IServiceCollection services) { - internal static void ConfigurePrerequisites(this IServiceCollection services) - { - services.TryAddSingleton(); - services.TryAddScoped, ExceptionHandler>(); - } + services.TryAddSingleton(); + services.TryAddScoped, ExceptionHandler>(); } } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/Configuration/ElasticSearch/ElasticSearchConfiguration.cs b/03-Infrastructure/Jinget.Logger/Configuration/ElasticSearch/ElasticSearchConfiguration.cs index b3573dc..d322166 100644 --- a/03-Infrastructure/Jinget.Logger/Configuration/ElasticSearch/ElasticSearchConfiguration.cs +++ b/03-Infrastructure/Jinget.Logger/Configuration/ElasticSearch/ElasticSearchConfiguration.cs @@ -13,116 +13,115 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Nest; -namespace Jinget.Logger.Configuration.Middlewares.ElasticSearch +namespace Jinget.Logger.Configuration.Middlewares.ElasticSearch; + +public static class ElasticSearchConfiguration { - public static class ElasticSearchConfiguration + public static void ConfigureElasticSearchLogger(this IServiceCollection services, ElasticSearchSettingModel elasticSearchSetting = null) + where TOperationalEntity : OperationLog, new() + where TErrorEntity : ErrorLog, new() + where TCustomEntity : CustomLog, new() { - public static void ConfigureElasticSearchLogger(this IServiceCollection services, ElasticSearchSettingModel elasticSearchSetting = null) - where TOperationalEntity : OperationLog, new() - where TErrorEntity : ErrorLog, new() - where TCustomEntity : CustomLog, new() - { - services.ConfigurePrerequisites(); + services.ConfigurePrerequisites(); - services.TryAddScoped, ElasticSearchBaseDomainService>(); - services.TryAddScoped, ElasticSearchBaseDomainService>(); - services.TryAddScoped, ElasticSearchBaseDomainService>(); + services.TryAddScoped, ElasticSearchBaseDomainService>(); + services.TryAddScoped, ElasticSearchBaseDomainService>(); + services.TryAddScoped, ElasticSearchBaseDomainService>(); - services.TryAddScoped, ElasticSearchRepository>(); - services.TryAddScoped, ElasticSearchRepository>(); - services.TryAddScoped, ElasticSearchRepository>(); + services.TryAddScoped, ElasticSearchRepository>(); + services.TryAddScoped, ElasticSearchRepository>(); + services.TryAddScoped, ElasticSearchRepository>(); - if (elasticSearchSetting != null) - { - services.TryAddSingleton(elasticSearchSetting); + if (elasticSearchSetting != null) + { + services.TryAddSingleton(elasticSearchSetting); - var client = CreateClient(elasticSearchSetting); - services.AddSingleton(typeof(IElasticClient), client); - CreateIndexes(client, elasticSearchSetting); - } + var client = CreateClient(elasticSearchSetting); + services.AddSingleton(typeof(IElasticClient), client); + CreateIndexes(client, elasticSearchSetting); } + } - public static void ConfigureElasticSearchLogger(this IServiceCollection services, ElasticSearchSettingModel elasticSearchSetting = null) - { - services.ConfigurePrerequisites(); + public static void ConfigureElasticSearchLogger(this IServiceCollection services, ElasticSearchSettingModel elasticSearchSetting = null) + { + services.ConfigurePrerequisites(); - services.TryAddScoped, ElasticSearchBaseDomainService>(); - services.TryAddScoped, ElasticSearchBaseDomainService>(); - services.TryAddScoped, ElasticSearchBaseDomainService>(); + services.TryAddScoped, ElasticSearchBaseDomainService>(); + services.TryAddScoped, ElasticSearchBaseDomainService>(); + services.TryAddScoped, ElasticSearchBaseDomainService>(); - services.TryAddScoped, ElasticSearchRepository>(); - services.TryAddScoped, ElasticSearchRepository>(); - services.TryAddScoped, ElasticSearchRepository>(); + services.TryAddScoped, ElasticSearchRepository>(); + services.TryAddScoped, ElasticSearchRepository>(); + services.TryAddScoped, ElasticSearchRepository>(); - if (elasticSearchSetting != null) - { - services.TryAddSingleton(elasticSearchSetting); + if (elasticSearchSetting != null) + { + services.TryAddSingleton(elasticSearchSetting); - var client = CreateClient(elasticSearchSetting); - services.AddSingleton(typeof(IElasticClient), client); - CreateIndexes(client, elasticSearchSetting); - } + var client = CreateClient(elasticSearchSetting); + services.AddSingleton(typeof(IElasticClient), client); + CreateIndexes(client, elasticSearchSetting); } + } - static ElasticClient CreateClient(ElasticSearchSettingModel elasticSearchSetting) + static ElasticClient CreateClient(ElasticSearchSettingModel elasticSearchSetting) + { + ConnectionSettings connectionSettings; + string protocol = elasticSearchSetting.UseSsl ? "https" : "http"; + Uri elasticUrl = new($"{protocol}://{elasticSearchSetting.Url}"); + if (string.IsNullOrEmpty(elasticSearchSetting.UserName) && string.IsNullOrEmpty(elasticSearchSetting.Password)) + connectionSettings = new ConnectionSettings(elasticUrl) + .DefaultDisableIdInference(true); + else { - ConnectionSettings connectionSettings; - string protocol = elasticSearchSetting.UseSsl ? "https" : "http"; - Uri elasticUrl = new($"{protocol}://{elasticSearchSetting.Url}"); - if (string.IsNullOrEmpty(elasticSearchSetting.UserName) && string.IsNullOrEmpty(elasticSearchSetting.Password)) - connectionSettings = new ConnectionSettings(elasticUrl) - .DefaultDisableIdInference(true); - else + if (elasticSearchSetting.UseSsl && elasticSearchSetting.BypassCertificateValidation) { - if (elasticSearchSetting.UseSsl && elasticSearchSetting.BypassCertificateValidation) - { - connectionSettings = new ConnectionSettings(elasticUrl) - .BasicAuthentication(elasticSearchSetting.UserName, elasticSearchSetting.Password) - .ServerCertificateValidationCallback(CertificateValidations.AllowAll) - .DefaultDisableIdInference(true); - } - else - connectionSettings = new ConnectionSettings(elasticUrl) - .BasicAuthentication(elasticSearchSetting.UserName, elasticSearchSetting.Password) - .DefaultDisableIdInference(true); + connectionSettings = new ConnectionSettings(elasticUrl) + .BasicAuthentication(elasticSearchSetting.UserName, elasticSearchSetting.Password) + .ServerCertificateValidationCallback(CertificateValidations.AllowAll) + .DefaultDisableIdInference(true); } + else + connectionSettings = new ConnectionSettings(elasticUrl) + .BasicAuthentication(elasticSearchSetting.UserName, elasticSearchSetting.Password) + .DefaultDisableIdInference(true); + } - var client = new ElasticClient(connectionSettings); + var client = new ElasticClient(connectionSettings); - return client; - } + return client; + } - static void CreateIndexes(ElasticClient client, ElasticSearchSettingModel elasticSearchSetting) + static void CreateIndexes(ElasticClient client, ElasticSearchSettingModel elasticSearchSetting) + { + if (!elasticSearchSetting.CreateIndexPerPartition) { - if (!elasticSearchSetting.CreateIndexPerPartition) + List indexes = new(); + if (elasticSearchSetting.RegisterDefaultLogModels) + { + indexes = typeof(BaseEntity<>).Assembly + .GetTypes() + .Where(x => x.GetCustomAttributes(typeof(EntityAttribute), false).Any(y => ((EntityAttribute)y).ElasticSearchEnabled)) + .ToList(); + } + if (elasticSearchSetting.DiscoveryTypes != null && elasticSearchSetting.DiscoveryTypes.Any()) { - List indexes = new(); - if (elasticSearchSetting.RegisterDefaultLogModels) + foreach (var item in elasticSearchSetting.DiscoveryTypes) { - indexes = typeof(BaseEntity<>).Assembly - .GetTypes() + indexes.AddRange(item.Assembly.GetTypes() .Where(x => x.GetCustomAttributes(typeof(EntityAttribute), false).Any(y => ((EntityAttribute)y).ElasticSearchEnabled)) - .ToList(); - } - if (elasticSearchSetting.DiscoveryTypes != null && elasticSearchSetting.DiscoveryTypes.Any()) - { - foreach (var item in elasticSearchSetting.DiscoveryTypes) - { - indexes.AddRange(item.Assembly.GetTypes() - .Where(x => x.GetCustomAttributes(typeof(EntityAttribute), false).Any(y => ((EntityAttribute)y).ElasticSearchEnabled)) - .ToList()); - } + .ToList()); } + } - foreach (var item in indexes) + foreach (var item in indexes) + { + string indexName = $"{AppDomain.CurrentDomain.FriendlyName}.{item.Name}".ToLower(); + if (!client.Indices.Exists(indexName).Exists) { - string indexName = $"{AppDomain.CurrentDomain.FriendlyName}.{item.Name}".ToLower(); - if (!client.Indices.Exists(indexName).Exists) - { - var result = client.Indices.Create(indexName, index => index.Map(m => m.AutoMap(item).NumericDetection(true))); - if (!result.IsValid) - throw new JingetException("Jinget Says: " + result.OriginalException); - } + var result = client.Indices.Create(indexName, index => index.Map(m => m.AutoMap(item).NumericDetection(true))); + if (!result.IsValid) + throw new JingetException("Jinget Says: " + result.OriginalException); } } } diff --git a/03-Infrastructure/Jinget.Logger/Configuration/ElasticSearch/ElasticSearchSettingModel.cs b/03-Infrastructure/Jinget.Logger/Configuration/ElasticSearch/ElasticSearchSettingModel.cs index 163decb..82756b8 100644 --- a/03-Infrastructure/Jinget.Logger/Configuration/ElasticSearch/ElasticSearchSettingModel.cs +++ b/03-Infrastructure/Jinget.Logger/Configuration/ElasticSearch/ElasticSearchSettingModel.cs @@ -1,56 +1,55 @@ using System; using System.Collections.Generic; -namespace Jinget.Logger.Configuration.Middlewares.ElasticSearch +namespace Jinget.Logger.Configuration.Middlewares.ElasticSearch; + +public class ElasticSearchSettingModel { - public class ElasticSearchSettingModel - { - /// - /// Elasticsearch service url. This address should not contains the PROTOCOL itself. Use 'abc.com:9200' instead of 'http://abc.com:9200' - /// - public string Url { get; set; } = "localhost:9200"; - - /// - /// username, if basic authentication enabled on Elasticsearch search service - /// - public string UserName { get; set; } - - /// - /// password, if basic authentication enabled on Elasticsearch search service - /// - public string Password { get; set; } - - /// - /// Set whether to use SSL while connecting to Elasticsearch or not - /// - public bool UseSsl { get; set; } = false; - - /// - /// Set whether to validate ssl certificate or not. - /// - public bool BypassCertificateValidation { get; set; } = true; - - /// - /// foreach type specified in this list, an index in Elasticsearch will be created - /// - public List DiscoveryTypes { get; set; } - - /// - /// check if Elasticsearch default log models such as OperationLog, ErrorLog and CustomLog related domain services and repositories and etc - /// should be registered in DI container or not - /// - public bool RegisterDefaultLogModels { get; set; } - - /// - /// Create index per partition using HttpContext.Items["jinget.log.partitionkey"] value. - /// If this mode is selected, then and also will not be used. - /// If this mode is selected, then index creation will be deferred until the first document insertion. - /// foeach partition key, a separated index will be created. - /// all of the indexes will share the same data model. - /// for request/response logs, will be used. - /// for errors, will be used. - /// for custom logs, will be used. - /// - public bool CreateIndexPerPartition { get; set; } - } + /// + /// Elasticsearch service url. This address should not contains the PROTOCOL itself. Use 'abc.com:9200' instead of 'http://abc.com:9200' + /// + public string Url { get; set; } = "localhost:9200"; + + /// + /// username, if basic authentication enabled on Elasticsearch search service + /// + public string UserName { get; set; } + + /// + /// password, if basic authentication enabled on Elasticsearch search service + /// + public string Password { get; set; } + + /// + /// Set whether to use SSL while connecting to Elasticsearch or not + /// + public bool UseSsl { get; set; } = false; + + /// + /// Set whether to validate ssl certificate or not. + /// + public bool BypassCertificateValidation { get; set; } = true; + + /// + /// foreach type specified in this list, an index in Elasticsearch will be created + /// + public List DiscoveryTypes { get; set; } + + /// + /// check if Elasticsearch default log models such as OperationLog, ErrorLog and CustomLog related domain services and repositories and etc + /// should be registered in DI container or not + /// + public bool RegisterDefaultLogModels { get; set; } + + /// + /// Create index per partition using HttpContext.Items["jinget.log.partitionkey"] value. + /// If this mode is selected, then and also will not be used. + /// If this mode is selected, then index creation will be deferred until the first document insertion. + /// foeach partition key, a separated index will be created. + /// all of the indexes will share the same data model. + /// for request/response logs, will be used. + /// for errors, will be used. + /// for custom logs, will be used. + /// + public bool CreateIndexPerPartition { get; set; } } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/Configuration/File/FileConfiguration.cs b/03-Infrastructure/Jinget.Logger/Configuration/File/FileConfiguration.cs index 6ded046..8e8b6e3 100644 --- a/03-Infrastructure/Jinget.Logger/Configuration/File/FileConfiguration.cs +++ b/03-Infrastructure/Jinget.Logger/Configuration/File/FileConfiguration.cs @@ -1,9 +1,8 @@ using Microsoft.Extensions.DependencyInjection; -namespace Jinget.Logger.Configuration +namespace Jinget.Logger.Configuration; + +public static class FileConfiguration { - public static class FileConfiguration - { - public static void ConfigureFileLogger(this IServiceCollection services) => services.ConfigurePrerequisites(); - } + public static void ConfigureFileLogger(this IServiceCollection services) => services.ConfigurePrerequisites(); } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/Configuration/JingetProgram.cs b/03-Infrastructure/Jinget.Logger/Configuration/JingetProgram.cs index 1880789..af40c32 100644 --- a/03-Infrastructure/Jinget.Logger/Configuration/JingetProgram.cs +++ b/03-Infrastructure/Jinget.Logger/Configuration/JingetProgram.cs @@ -4,55 +4,54 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -namespace Jinget.Logger.Configuration +namespace Jinget.Logger.Configuration; + +public static class JingetProgram { - public static class JingetProgram - { - public static IHostBuilder Configure(string[] args) => - Host.CreateDefaultBuilder(args) - .UseDefaultServiceProvider(provider => provider.ValidateScopes = false); + public static IHostBuilder Configure(string[] args) => + Host.CreateDefaultBuilder(args) + .UseDefaultServiceProvider(provider => provider.ValidateScopes = false); - public static IHostBuilder LogToElasticSearch( - this IHostBuilder webHostBuilder, - string[] blackList, - LogLevel[] allowedLoglevels = null) - where TOperationalEntity : OperationLog, new() - where TErrorEntity : ErrorLog, new() - where TCustomEntity : CustomLog, new() - => - webHostBuilder.ConfigureLogging(builder => builder.AddElasticSearch(f => - { - f.BlackListStrings = blackList; - f.AllowedLogLevels = allowedLoglevels; - })); + public static IHostBuilder LogToElasticSearch( + this IHostBuilder webHostBuilder, + string[] blackList, + LogLevel[] allowedLoglevels = null) + where TOperationalEntity : OperationLog, new() + where TErrorEntity : ErrorLog, new() + where TCustomEntity : CustomLog, new() + => + webHostBuilder.ConfigureLogging(builder => builder.AddElasticSearch(f => + { + f.BlackListStrings = blackList; + f.AllowedLogLevels = allowedLoglevels; + })); - public static IHostBuilder LogToElasticSearch( - this IHostBuilder webHostBuilder, - string[] blackList, - LogLevel[] allowedLoglevels = null) - => - webHostBuilder.ConfigureLogging(builder => builder.AddElasticSearch(f => - { - f.BlackListStrings = blackList; - f.AllowedLogLevels = allowedLoglevels; - })); + public static IHostBuilder LogToElasticSearch( + this IHostBuilder webHostBuilder, + string[] blackList, + LogLevel[] allowedLoglevels = null) + => + webHostBuilder.ConfigureLogging(builder => builder.AddElasticSearch(f => + { + f.BlackListStrings = blackList; + f.AllowedLogLevels = allowedLoglevels; + })); - public static IHostBuilder LogToFile( - this IHostBuilder webHostBuilder, - string[] blackList, - string fileNamePrefix = "Log", - string logDirectory = "Logs", - int retainFileCountLimit = 5, - int fileSizeLimit = 10, - LogLevel[] allowedLoglevels = null) => - webHostBuilder.ConfigureLogging(builder => builder.AddFile(f => - { - f.FileName = fileNamePrefix; - f.LogDirectory = logDirectory; - f.RetainedFileCountLimit = retainFileCountLimit; - f.BlackListStrings = blackList; - f.FileSizeLimit = fileSizeLimit; - f.AllowedLogLevels = allowedLoglevels; - })); - } + public static IHostBuilder LogToFile( + this IHostBuilder webHostBuilder, + string[] blackList, + string fileNamePrefix = "Log", + string logDirectory = "Logs", + int retainFileCountLimit = 5, + int fileSizeLimit = 10, + LogLevel[] allowedLoglevels = null) => + webHostBuilder.ConfigureLogging(builder => builder.AddFile(f => + { + f.FileName = fileNamePrefix; + f.LogDirectory = logDirectory; + f.RetainedFileCountLimit = retainFileCountLimit; + f.BlackListStrings = blackList; + f.FileSizeLimit = fileSizeLimit; + f.AllowedLogLevels = allowedLoglevels; + })); } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/Configuration/Middlewares/LogRequestMiddleware.cs b/03-Infrastructure/Jinget.Logger/Configuration/Middlewares/LogRequestMiddleware.cs index d7174cc..6a6420b 100644 --- a/03-Infrastructure/Jinget.Logger/Configuration/Middlewares/LogRequestMiddleware.cs +++ b/03-Infrastructure/Jinget.Logger/Configuration/Middlewares/LogRequestMiddleware.cs @@ -8,18 +8,17 @@ using Microsoft.Extensions.Options; using Jinget.Core.ExtensionMethods; -namespace Jinget.Logger.Configuration.Middlewares +namespace Jinget.Logger.Configuration.Middlewares; + +public class LogRequestMiddleware { - public class LogRequestMiddleware - { - private readonly ILog _logger; + private readonly ILog _logger; - public LogRequestMiddleware(RequestDelegate next, IServiceProvider serviceProvider, ILogger logger, - IOptions blackListHeaders, - IOptions whiteListHeaders) - => _logger = - new RequestLogger(next, logger, serviceProvider.GetJingetService>(), blackListHeaders, whiteListHeaders); + public LogRequestMiddleware(RequestDelegate next, IServiceProvider serviceProvider, ILogger logger, + IOptions blackListHeaders, + IOptions whiteListHeaders) + => _logger = + new RequestLogger(next, logger, serviceProvider.GetJingetService>(), blackListHeaders, whiteListHeaders); - public async Task InvokeAsync(HttpContext context) => await _logger.LogAsync(context); - } + public async Task InvokeAsync(HttpContext context) => await _logger.LogAsync(context); } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/Configuration/Middlewares/LogResponseMiddleware.cs b/03-Infrastructure/Jinget.Logger/Configuration/Middlewares/LogResponseMiddleware.cs index a60550b..6540400 100644 --- a/03-Infrastructure/Jinget.Logger/Configuration/Middlewares/LogResponseMiddleware.cs +++ b/03-Infrastructure/Jinget.Logger/Configuration/Middlewares/LogResponseMiddleware.cs @@ -5,17 +5,16 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -namespace Jinget.Logger.Configuration.Middlewares +namespace Jinget.Logger.Configuration.Middlewares; + +public class LogResponseMiddleware { - public class LogResponseMiddleware - { - private readonly ILog _logger; + private readonly ILog _logger; - public LogResponseMiddleware(RequestDelegate next, ILogger logger, - IOptions blackListHeaders, - IOptions whiteListHeaders) - => _logger = new ResponseLogger(next, logger, blackListHeaders, whiteListHeaders); + public LogResponseMiddleware(RequestDelegate next, ILogger logger, + IOptions blackListHeaders, + IOptions whiteListHeaders) + => _logger = new ResponseLogger(next, logger, blackListHeaders, whiteListHeaders); - public async Task InvokeAsync(HttpContext context) => await _logger.LogAsync(context); - } + public async Task InvokeAsync(HttpContext context) => await _logger.LogAsync(context); } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/Entities/BaseEntity.cs b/03-Infrastructure/Jinget.Logger/Entities/BaseEntity.cs index 6247b8d..8a93d01 100644 --- a/03-Infrastructure/Jinget.Logger/Entities/BaseEntity.cs +++ b/03-Infrastructure/Jinget.Logger/Entities/BaseEntity.cs @@ -1,28 +1,27 @@ using System.ComponentModel.DataAnnotations; -namespace Jinget.Logger.Entities +namespace Jinget.Logger.Entities; + +public abstract class BaseEntity { - public abstract class BaseEntity - { - protected BaseEntity() { } + protected BaseEntity() { } - protected BaseEntity(TKeyType id) : this() => Id = id; + protected BaseEntity(TKeyType id) : this() => Id = id; - private TKeyType _id; + private TKeyType _id; - [Key] - public virtual TKeyType Id + [Key] + public virtual TKeyType Id + { + get => _id; + protected set { - get => _id; - protected set + if (value != null) { - if (value != null) - { - _id = value; - } + _id = value; } } - - public virtual void SetId(TKeyType id) => Id = id; } + + public virtual void SetId(TKeyType id) => Id = id; } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/Entities/Log/Base/LogBaseEntity.cs b/03-Infrastructure/Jinget.Logger/Entities/Log/Base/LogBaseEntity.cs index 77a7278..b445527 100644 --- a/03-Infrastructure/Jinget.Logger/Entities/Log/Base/LogBaseEntity.cs +++ b/03-Infrastructure/Jinget.Logger/Entities/Log/Base/LogBaseEntity.cs @@ -1,19 +1,18 @@ using System; -namespace Jinget.Logger.Entities.Log.Base +namespace Jinget.Logger.Entities.Log.Base; + +public abstract class LogBaseEntity : BaseEntity { - public abstract class LogBaseEntity : BaseEntity - { - public DateTime When { get; set; } - public string Url { get; set; } - public string Description { get; set; } - public string SubSystem { get; set; } + public DateTime When { get; set; } + public string Url { get; set; } + public string Description { get; set; } + public string SubSystem { get; set; } - /// - /// This is used when the CreateIndexPerPartition is set to true. - /// This property is specific to Elasticsearch logging - /// - public string ParitionKey { get; set; } - public Guid RequestId { get; set; } = Guid.Empty; - } + /// + /// This is used when the CreateIndexPerPartition is set to true. + /// This property is specific to Elasticsearch logging + /// + public string ParitionKey { get; set; } + public Guid RequestId { get; set; } = Guid.Empty; } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/Entities/Log/CustomLog.cs b/03-Infrastructure/Jinget.Logger/Entities/Log/CustomLog.cs index 5a8b8ac..6712444 100644 --- a/03-Infrastructure/Jinget.Logger/Entities/Log/CustomLog.cs +++ b/03-Infrastructure/Jinget.Logger/Entities/Log/CustomLog.cs @@ -1,13 +1,12 @@ using Jinget.Core.Attributes; using Jinget.Logger.Entities.Log.Base; -namespace Jinget.Logger.Entities.Log +namespace Jinget.Logger.Entities.Log; + +[Entity(ElasticSearchEnabled = true)] +public class CustomLog : LogBaseEntity { - [Entity(ElasticSearchEnabled = true)] - public class CustomLog : LogBaseEntity - { - public string CallerFilePath { get; set; } - public long CallerLineNumber { get; set; } - public string CallerMember { get; set; } - } + public string CallerFilePath { get; set; } + public long CallerLineNumber { get; set; } + public string CallerMember { get; set; } } diff --git a/03-Infrastructure/Jinget.Logger/Entities/Log/ErrorLog.cs b/03-Infrastructure/Jinget.Logger/Entities/Log/ErrorLog.cs index 6273ed5..403adb7 100644 --- a/03-Infrastructure/Jinget.Logger/Entities/Log/ErrorLog.cs +++ b/03-Infrastructure/Jinget.Logger/Entities/Log/ErrorLog.cs @@ -1,11 +1,10 @@ using Jinget.Core.Attributes; using Jinget.Logger.Entities.Log.Base; -namespace Jinget.Logger.Entities.Log +namespace Jinget.Logger.Entities.Log; + +[Entity(ElasticSearchEnabled = true)] +public class ErrorLog : LogBaseEntity { - [Entity(ElasticSearchEnabled = true)] - public class ErrorLog : LogBaseEntity - { - public string Severity { get; set; } - } + public string Severity { get; set; } } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/Entities/Log/OperationLog.cs b/03-Infrastructure/Jinget.Logger/Entities/Log/OperationLog.cs index 4e940c9..79c7f4c 100644 --- a/03-Infrastructure/Jinget.Logger/Entities/Log/OperationLog.cs +++ b/03-Infrastructure/Jinget.Logger/Entities/Log/OperationLog.cs @@ -1,27 +1,26 @@ using Jinget.Core.Attributes; using Jinget.Logger.Entities.Log.Base; -namespace Jinget.Logger.Entities.Log +namespace Jinget.Logger.Entities.Log; + +[Entity(ElasticSearchEnabled = true)] +public class OperationLog : LogBaseEntity { - [Entity(ElasticSearchEnabled = true)] - public class OperationLog : LogBaseEntity - { - public string Method { get; set; } + public string Method { get; set; } - public string Body { get; set; } + public string Body { get; set; } - public string Headers { get; set; } + public string Headers { get; set; } - public string IP { get; set; } + public string IP { get; set; } - public bool IsResponse { get; set; } + public bool IsResponse { get; set; } - public string PageUrl { get; set; } + public string PageUrl { get; set; } - public long ContentLength { get; set; } + public long ContentLength { get; set; } - public string Detail { get; set; } + public string Detail { get; set; } - public string UserName { get; set; } - } + public string UserName { get; set; } } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/ExceptionHandler/ExceptionHandler.cs b/03-Infrastructure/Jinget.Logger/ExceptionHandler/ExceptionHandler.cs index f1348c2..54f2bf3 100644 --- a/03-Infrastructure/Jinget.Logger/ExceptionHandler/ExceptionHandler.cs +++ b/03-Infrastructure/Jinget.Logger/ExceptionHandler/ExceptionHandler.cs @@ -5,51 +5,50 @@ using Microsoft.Extensions.Logging; using Newtonsoft.Json; -namespace Jinget.Logger.ExceptionHandler +namespace Jinget.Logger.ExceptionHandler; + +public class ExceptionHandler : IExceptionHandler { - public class ExceptionHandler : IExceptionHandler - { - private readonly ILogger _logger; - private readonly IHttpContextAccessor _accessor; + private readonly ILogger _logger; + private readonly IHttpContextAccessor _accessor; - public ExceptionHandler(ILogger logger, IHttpContextAccessor accessor) - { - _logger = logger; - _accessor = accessor; - } + public ExceptionHandler(ILogger logger, IHttpContextAccessor accessor) + { + _logger = logger; + _accessor = accessor; + } - public void Handle(Exception ex, object details) + public void Handle(Exception ex, object details) + { + ErrorLog logEntity = new() { - ErrorLog logEntity = new() + Description = JsonConvert.SerializeObject(new { - Description = JsonConvert.SerializeObject(new - { - ex.Message, - Details = JsonConvert.SerializeObject(details), - ex.StackTrace - }), + ex.Message, + Details = JsonConvert.SerializeObject(details), + ex.StackTrace + }), - ParitionKey = - _accessor.HttpContext.Items["jinget.log.partitionkey"] != null ? - _accessor.HttpContext.Items["jinget.log.partitionkey"].ToString() : - "", - Severity = LogLevel.Error.ToString() - }; - if (details is LogBaseEntity entity) - { - logEntity.RequestId = entity.RequestId; - logEntity.SubSystem = entity.SubSystem; - logEntity.When = entity.When; - logEntity.Url = entity.Url; - } - else - { - logEntity.RequestId = new Guid(_accessor.HttpContext.Response.Headers["RequestId"].ToString()); - logEntity.SubSystem = AppDomain.CurrentDomain.FriendlyName; - logEntity.When = DateTime.Now; - } - _logger.LogError(JsonConvert.SerializeObject(logEntity)); - return; + ParitionKey = + _accessor.HttpContext.Items["jinget.log.partitionkey"] != null ? + _accessor.HttpContext.Items["jinget.log.partitionkey"].ToString() : + "", + Severity = LogLevel.Error.ToString() + }; + if (details is LogBaseEntity entity) + { + logEntity.RequestId = entity.RequestId; + logEntity.SubSystem = entity.SubSystem; + logEntity.When = entity.When; + logEntity.Url = entity.Url; + } + else + { + logEntity.RequestId = new Guid(_accessor.HttpContext.Response.Headers["RequestId"].ToString()); + logEntity.SubSystem = AppDomain.CurrentDomain.FriendlyName; + logEntity.When = DateTime.Now; } + _logger.LogError(JsonConvert.SerializeObject(logEntity)); + return; } } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/ExceptionHandler/IExceptionHandler.cs b/03-Infrastructure/Jinget.Logger/ExceptionHandler/IExceptionHandler.cs index 58c4e22..e06b1af 100644 --- a/03-Infrastructure/Jinget.Logger/ExceptionHandler/IExceptionHandler.cs +++ b/03-Infrastructure/Jinget.Logger/ExceptionHandler/IExceptionHandler.cs @@ -1,9 +1,8 @@ using System; -namespace Jinget.Logger.ExceptionHandler +namespace Jinget.Logger.ExceptionHandler; + +public interface IExceptionHandler { - public interface IExceptionHandler - { - void Handle(Exception ex, object details); - } + void Handle(Exception ex, object details); } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/Handlers/CommandHandlers/ElasticSearchBaseDomainService.cs b/03-Infrastructure/Jinget.Logger/Handlers/CommandHandlers/ElasticSearchBaseDomainService.cs index adcbab6..e78b834 100644 --- a/03-Infrastructure/Jinget.Logger/Handlers/CommandHandlers/ElasticSearchBaseDomainService.cs +++ b/03-Infrastructure/Jinget.Logger/Handlers/CommandHandlers/ElasticSearchBaseDomainService.cs @@ -3,19 +3,18 @@ using Jinget.Logger.Entities.Log.Base; using Jinget.Logger.ViewModels; -namespace Jinget.Logger.Handlers.CommandHandlers +namespace Jinget.Logger.Handlers.CommandHandlers; + +public class ElasticSearchBaseDomainService : + IElasticSearchBaseDomainService + where TModelType : LogBaseEntity { - public class ElasticSearchBaseDomainService : - IElasticSearchBaseDomainService - where TModelType : LogBaseEntity - { - protected readonly IElasticSearchRepository Repository; + protected readonly IElasticSearchRepository Repository; - public ElasticSearchBaseDomainService(IElasticSearchRepository repository) => Repository = repository; + public ElasticSearchBaseDomainService(IElasticSearchRepository repository) => Repository = repository; - public virtual async Task CreateAsync(TModelType param) => await Repository.IndexAsync(param); - public virtual async Task BulkCreateAsync(IList @params) => await Repository.BulkIndexAsync(@params); - public virtual async Task FetchLatestAsync() => await Repository.GetLatestAsync(); - public virtual async Task> SearchAsync(string partitionKey, string searchString, int pageNumber, int pageSize, string username = "") => await Repository.SearchAsync(partitionKey, searchString, pageNumber, pageSize, username); - } + public virtual async Task CreateAsync(TModelType param) => await Repository.IndexAsync(param); + public virtual async Task BulkCreateAsync(IList @params) => await Repository.BulkIndexAsync(@params); + public virtual async Task FetchLatestAsync() => await Repository.GetLatestAsync(); + public virtual async Task> SearchAsync(string partitionKey, string searchString, int pageNumber, int pageSize, string username = "") => await Repository.SearchAsync(partitionKey, searchString, pageNumber, pageSize, username); } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/Handlers/CommandHandlers/IElasticSearchBaseDomainService.cs b/03-Infrastructure/Jinget.Logger/Handlers/CommandHandlers/IElasticSearchBaseDomainService.cs index b082593..b763fb2 100644 --- a/03-Infrastructure/Jinget.Logger/Handlers/CommandHandlers/IElasticSearchBaseDomainService.cs +++ b/03-Infrastructure/Jinget.Logger/Handlers/CommandHandlers/IElasticSearchBaseDomainService.cs @@ -3,16 +3,15 @@ using Jinget.Logger.Entities.Log.Base; using Jinget.Logger.ViewModels; -namespace Jinget.Logger.Handlers.CommandHandlers +namespace Jinget.Logger.Handlers.CommandHandlers; + +public interface IElasticSearchBaseDomainService + where TModelType : LogBaseEntity { - public interface IElasticSearchBaseDomainService - where TModelType : LogBaseEntity - { - Task FetchLatestAsync(); + Task FetchLatestAsync(); - Task CreateAsync(TModelType param); + Task CreateAsync(TModelType param); - Task BulkCreateAsync(IList @params); - Task> SearchAsync(string partitionKey, string searchString, int pageNumber, int pageSize, string username = ""); - } + Task BulkCreateAsync(IList @params); + Task> SearchAsync(string partitionKey, string searchString, int pageNumber, int pageSize, string username = ""); } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/Handlers/ElasticSearchRepository.cs b/03-Infrastructure/Jinget.Logger/Handlers/ElasticSearchRepository.cs index 93ca84e..b0f735e 100644 --- a/03-Infrastructure/Jinget.Logger/Handlers/ElasticSearchRepository.cs +++ b/03-Infrastructure/Jinget.Logger/Handlers/ElasticSearchRepository.cs @@ -10,188 +10,187 @@ using System.Linq; using System.Threading.Tasks; -namespace Jinget.Logger.Handlers +namespace Jinget.Logger.Handlers; + +public class ElasticSearchRepository : IElasticSearchRepository + where TModelType : LogBaseEntity { - public class ElasticSearchRepository : IElasticSearchRepository - where TModelType : LogBaseEntity + private readonly IElasticClient _elasticClient; + private readonly ElasticSearchSettingModel settings; + + public ElasticSearchRepository(IElasticClient elasticClient, ElasticSearchSettingModel settings) { - private readonly IElasticClient _elasticClient; - private readonly ElasticSearchSettingModel settings; + _elasticClient = elasticClient; + this.settings = settings; + } - public ElasticSearchRepository(IElasticClient elasticClient, ElasticSearchSettingModel settings) + public async Task IndexAsync(TModelType param) + { + if (settings.CreateIndexPerPartition) + await CreateIndexAsync(param.ParitionKey); + string indexName = GetIndexName(param.ParitionKey); + + var result = await _elasticClient.IndexAsync(param, i => i.Index(indexName)); + if (result.IsValid) + return result.IsValid; + throw new JingetException("Jinget Says: " + result.OriginalException.ToString()); + } + string GetIndexName(string partitionKey) + { + if (settings.CreateIndexPerPartition && !string.IsNullOrWhiteSpace(partitionKey)) { - _elasticClient = elasticClient; - this.settings = settings; + if (typeof(TModelType) == typeof(OperationLog)) + return $"op.{partitionKey}".ToLower(); + else if (typeof(TModelType) == typeof(ErrorLog)) + return $"err.{partitionKey}".ToLower(); + else + return $"cus.{partitionKey}".ToLower(); } + return $"{AppDomain.CurrentDomain.FriendlyName}.{typeof(TModelType).Name}".ToLower(); + } - public async Task IndexAsync(TModelType param) - { - if (settings.CreateIndexPerPartition) - await CreateIndexAsync(param.ParitionKey); - string indexName = GetIndexName(param.ParitionKey); - - var result = await _elasticClient.IndexAsync(param, i => i.Index(indexName)); - if (result.IsValid) - return result.IsValid; - throw new JingetException("Jinget Says: " + result.OriginalException.ToString()); - } - string GetIndexName(string partitionKey) - { - if (settings.CreateIndexPerPartition && !string.IsNullOrWhiteSpace(partitionKey)) - { - if (typeof(TModelType) == typeof(OperationLog)) - return $"op.{partitionKey}".ToLower(); - else if (typeof(TModelType) == typeof(ErrorLog)) - return $"err.{partitionKey}".ToLower(); - else - return $"cus.{partitionKey}".ToLower(); - } - return $"{AppDomain.CurrentDomain.FriendlyName}.{typeof(TModelType).Name}".ToLower(); - } + public async Task CreateIndexAsync(string indexName) + { + if (string.IsNullOrWhiteSpace(indexName) && typeof(TModelType) != typeof(CustomLog)) + return false; - public async Task CreateIndexAsync(string indexName) + indexName = GetIndexName(indexName); + if (!_elasticClient.Indices.Exists(indexName.ToLower()).Exists) { - if (string.IsNullOrWhiteSpace(indexName) && typeof(TModelType) != typeof(CustomLog)) - return false; - - indexName = GetIndexName(indexName); - if (!_elasticClient.Indices.Exists(indexName.ToLower()).Exists) - { - var indexCreationResult = await _elasticClient.Indices - .CreateAsync(indexName.ToLower(), index => index.Map(m => m.AutoMap(typeof(TModelType)).NumericDetection(true))); - if (!indexCreationResult.IsValid) - throw new JingetException("Jinget Says: " + indexCreationResult.OriginalException); - } - return true; + var indexCreationResult = await _elasticClient.Indices + .CreateAsync(indexName.ToLower(), index => index.Map(m => m.AutoMap(typeof(TModelType)).NumericDetection(true))); + if (!indexCreationResult.IsValid) + throw new JingetException("Jinget Says: " + indexCreationResult.OriginalException); } + return true; + } - public async Task BulkIndexAsync(IList @params) + public async Task BulkIndexAsync(IList @params) + { + foreach (var item in @params.GroupBy(g => g.ParitionKey)) { - foreach (var item in @params.GroupBy(g => g.ParitionKey)) - { - if (settings.CreateIndexPerPartition) - await CreateIndexAsync(item.Key.ToString()); - string indexName = GetIndexName(item.Key.ToString()); + if (settings.CreateIndexPerPartition) + await CreateIndexAsync(item.Key.ToString()); + string indexName = GetIndexName(item.Key.ToString()); - var result = await _elasticClient.BulkAsync(i => i.Index(indexName).CreateMany(item)); + var result = await _elasticClient.BulkAsync(i => i.Index(indexName).CreateMany(item)); - if (!result.IsValid) - throw new JingetException("Jinget Says: " + result.OriginalException.ToString()); - } - return true; + if (!result.IsValid) + throw new JingetException("Jinget Says: " + result.OriginalException.ToString()); } + return true; + } - public async Task GetLatestAsync(Func, IPromise>> orderBy = null, string partitionKey = "") + public async Task GetLatestAsync(Func, IPromise>> orderBy = null, string partitionKey = "") + { + string indexName = GetIndexName(partitionKey); + var lastRecord = await _elasticClient.SearchAsync(i => { - string indexName = GetIndexName(partitionKey); - var lastRecord = await _elasticClient.SearchAsync(i => - { - var expr = i.Index(indexName).From(0).Take(1).MatchAll(); - return expr.Sort(orderBy ?? (s => s.Descending(d => d.When))); - }); + var expr = i.Index(indexName).From(0).Take(1).MatchAll(); + return expr.Sort(orderBy ?? (s => s.Descending(d => d.When))); + }); - return lastRecord.Documents.FirstOrDefault(); - } + return lastRecord.Documents.FirstOrDefault(); + } - public async Task> SearchAsync( - string partitionKey, - string searchString, - int pageNumber, - int pageSize, - string username = "") + public async Task> SearchAsync( + string partitionKey, + string searchString, + int pageNumber, + int pageSize, + string username = "") + { + string opIndexName = ""; + string errIndexName = ""; + if (settings.CreateIndexPerPartition) { - string opIndexName = ""; - string errIndexName = ""; - if (settings.CreateIndexPerPartition) - { - opIndexName = $"op.{partitionKey}"; - errIndexName = $"err.{partitionKey}"; - } - if (string.IsNullOrWhiteSpace(opIndexName)) - opIndexName = $"{AppDomain.CurrentDomain.FriendlyName}.{typeof(OperationLog).Name}".ToLower(); - if (string.IsNullOrWhiteSpace(errIndexName)) - errIndexName = $"{AppDomain.CurrentDomain.FriendlyName}.{typeof(ErrorLog).Name}".ToLower(); - - var searchResult = await _elasticClient - .SearchAsync(i => - i.Index(opIndexName) - .Query(x => + opIndexName = $"op.{partitionKey}"; + errIndexName = $"err.{partitionKey}"; + } + if (string.IsNullOrWhiteSpace(opIndexName)) + opIndexName = $"{AppDomain.CurrentDomain.FriendlyName}.{typeof(OperationLog).Name}".ToLower(); + if (string.IsNullOrWhiteSpace(errIndexName)) + errIndexName = $"{AppDomain.CurrentDomain.FriendlyName}.{typeof(ErrorLog).Name}".ToLower(); + + var searchResult = await _elasticClient + .SearchAsync(i => + i.Index(opIndexName) + .Query(x => + { + List queryContainer = new(); + if (!string.IsNullOrWhiteSpace(searchString)) { - List queryContainer = new(); - if (!string.IsNullOrWhiteSpace(searchString)) - { - queryContainer.Add( - x.MultiMatch(c => c - .Fields(f => f - .Field(doc => doc.Body) - .Field(doc => doc.Description) - .Field(doc => doc.Detail) - .Field(doc => doc.Headers) - .Field(doc => doc.Method) - .Field(doc => doc.PageUrl) - .Field(doc => doc.Url) - .Field(doc => doc.UserName) - .Field(doc => doc.SubSystem) - ) - .Query(searchString) - )); - } - if (!string.IsNullOrWhiteSpace(username)) - queryContainer.Add(x.Match(f => f.Field(doc => doc.UserName).Query(username))); - - return x.Bool(b => b.Must(queryContainer.ToArray())); - }) - .Aggregations(a => a.Terms("req_id", x => x.Field(f => f.RequestId.Suffix("raw")))) - .From((pageNumber - 1) * pageSize) - .Take(pageSize * 2)//because each operation consists of 1 req + 1 response - .Sort(s => s.Descending(d => d.When))).ConfigureAwait(true); - - var opResult = searchResult.Documents; - List logs = new(); - - foreach (var op in opResult.GroupBy(g => g.RequestId)) + queryContainer.Add( + x.MultiMatch(c => c + .Fields(f => f + .Field(doc => doc.Body) + .Field(doc => doc.Description) + .Field(doc => doc.Detail) + .Field(doc => doc.Headers) + .Field(doc => doc.Method) + .Field(doc => doc.PageUrl) + .Field(doc => doc.Url) + .Field(doc => doc.UserName) + .Field(doc => doc.SubSystem) + ) + .Query(searchString) + )); + } + if (!string.IsNullOrWhiteSpace(username)) + queryContainer.Add(x.Match(f => f.Field(doc => doc.UserName).Query(username))); + + return x.Bool(b => b.Must(queryContainer.ToArray())); + }) + .Aggregations(a => a.Terms("req_id", x => x.Field(f => f.RequestId.Suffix("raw")))) + .From((pageNumber - 1) * pageSize) + .Take(pageSize * 2)//because each operation consists of 1 req + 1 response + .Sort(s => s.Descending(d => d.When))).ConfigureAwait(true); + + var opResult = searchResult.Documents; + List logs = new(); + + foreach (var op in opResult.GroupBy(g => g.RequestId)) + { + var errSearchResult = await _elasticClient.SearchAsync(i => { - var errSearchResult = await _elasticClient.SearchAsync(i => - { - var expr = i.Index(errIndexName) - .Query(q => + var expr = i.Index(errIndexName) + .Query(q => + { + List queryContainer = new() { - List queryContainer = new() - { - q.Match(m => m.Field(doc => doc.RequestId).Query(op.Key.ToString())) - }; - return q.Bool(b => b.Must(queryContainer.ToArray())); - }); - - return expr; - }); - - logs.Add(new LogViewModel(op, errSearchResult.Documents)); - } - var result = logs.Select(l => new - LogSearchViewModel( - l.Op.First().RequestId, - l.Op.First().IP, - l.Op.First().Url, - l.Op.First().Method, - l.Op.First().PageUrl, - l.Op.Select(o => new LogSearchViewModel.OperationLogSearchViewModel( - o.IsResponse ? "response" : "request", - o.When, - o.Body, - o.ContentLength, - o.Headers, - o.Detail, - o.Description - )), - l.Err.Select(e => new LogSearchViewModel.ErrorLogSearchViewModel( - e.When, - e.Description, - e.Severity - )) - )).ToList(); - - return result.Take(pageSize).ToList(); + q.Match(m => m.Field(doc => doc.RequestId).Query(op.Key.ToString())) + }; + return q.Bool(b => b.Must(queryContainer.ToArray())); + }); + + return expr; + }); + + logs.Add(new LogViewModel(op, errSearchResult.Documents)); } + var result = logs.Select(l => new + LogSearchViewModel( + l.Op.First().RequestId, + l.Op.First().IP, + l.Op.First().Url, + l.Op.First().Method, + l.Op.First().PageUrl, + l.Op.Select(o => new LogSearchViewModel.OperationLogSearchViewModel( + o.IsResponse ? "response" : "request", + o.When, + o.Body, + o.ContentLength, + o.Headers, + o.Detail, + o.Description + )), + l.Err.Select(e => new LogSearchViewModel.ErrorLogSearchViewModel( + e.When, + e.Description, + e.Severity + )) + )).ToList(); + + return result.Take(pageSize).ToList(); } } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/Handlers/IElasticSearchRepository.cs b/03-Infrastructure/Jinget.Logger/Handlers/IElasticSearchRepository.cs index f598f7b..7fb2749 100644 --- a/03-Infrastructure/Jinget.Logger/Handlers/IElasticSearchRepository.cs +++ b/03-Infrastructure/Jinget.Logger/Handlers/IElasticSearchRepository.cs @@ -5,38 +5,37 @@ using System.Collections.Generic; using System.Threading.Tasks; -namespace Jinget.Logger.Handlers +namespace Jinget.Logger.Handlers; + +public interface IElasticSearchRepository + where TModelType : LogBaseEntity { - public interface IElasticSearchRepository - where TModelType : LogBaseEntity - { - /// - /// Create index if index not exists - /// - Task CreateIndexAsync(string indexName); + /// + /// Create index if index not exists + /// + Task CreateIndexAsync(string indexName); - /// - /// Create a new document - /// - Task IndexAsync(TModelType param); + /// + /// Create a new document + /// + Task IndexAsync(TModelType param); - /// - /// Create a list of documents - /// - Task BulkIndexAsync(IList @params); + /// + /// Create a list of documents + /// + Task BulkIndexAsync(IList @params); - /// - /// Get latest log - /// - /// - /// - /// - Task GetLatestAsync(Func, IPromise>> orderBy = null, string partitionKey = ""); + /// + /// Get latest log + /// + /// + /// + /// + Task GetLatestAsync(Func, IPromise>> orderBy = null, string partitionKey = ""); - /// - /// Get list of logs - /// - /// If username specified, then logs will be filtered using - Task> SearchAsync(string partitionKey, string searchString, int pageNumber, int pageSize, string username = ""); - } + /// + /// Get list of logs + /// + /// If username specified, then logs will be filtered using + Task> SearchAsync(string partitionKey, string searchString, int pageNumber, int pageSize, string username = ""); } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/ILog.cs b/03-Infrastructure/Jinget.Logger/ILog.cs index 6a81666..3997088 100644 --- a/03-Infrastructure/Jinget.Logger/ILog.cs +++ b/03-Infrastructure/Jinget.Logger/ILog.cs @@ -1,10 +1,9 @@ using Microsoft.AspNetCore.Http; using System.Threading.Tasks; -namespace Jinget.Logger +namespace Jinget.Logger; + +public interface ILog { - public interface ILog - { - Task LogAsync(HttpContext context); - } + Task LogAsync(HttpContext context); } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/ILoggerExtensions.cs b/03-Infrastructure/Jinget.Logger/ILoggerExtensions.cs index 5ba00d8..b8c226b 100644 --- a/03-Infrastructure/Jinget.Logger/ILoggerExtensions.cs +++ b/03-Infrastructure/Jinget.Logger/ILoggerExtensions.cs @@ -4,24 +4,23 @@ using Microsoft.Extensions.Logging; using Newtonsoft.Json; -namespace Jinget.Logger +namespace Jinget.Logger; + +public static class ILoggerExtensions { - public static class ILoggerExtensions + public static void LogCustom(this ILogger logger, string message, + Guid? requestId = null, + [CallerFilePath] string callerFilePath = "", + [CallerLineNumber] long callerLineNumber = 0, + [CallerMemberName] string callerMember = "") { - public static void LogCustom(this ILogger logger, string message, - Guid? requestId = null, - [CallerFilePath] string callerFilePath = "", - [CallerLineNumber] long callerLineNumber = 0, - [CallerMemberName] string callerMember = "") + logger.LogDebug(JsonConvert.SerializeObject(new CustomLog { - logger.LogDebug(JsonConvert.SerializeObject(new CustomLog - { - Description = message, - CallerFilePath = callerFilePath, - CallerLineNumber = callerLineNumber, - CallerMember = callerMember, - RequestId = requestId ?? Guid.Empty - }), null); - } + Description = message, + CallerFilePath = callerFilePath, + CallerLineNumber = callerLineNumber, + CallerMember = callerMember, + RequestId = requestId ?? Guid.Empty + }), null); } } diff --git a/03-Infrastructure/Jinget.Logger/Log.cs b/03-Infrastructure/Jinget.Logger/Log.cs index c06cff4..9bd33f1 100644 --- a/03-Infrastructure/Jinget.Logger/Log.cs +++ b/03-Infrastructure/Jinget.Logger/Log.cs @@ -5,26 +5,25 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -namespace Jinget.Logger +namespace Jinget.Logger; + +public class Log { - public class Log - { - protected readonly ILogger Logger; - protected readonly RequestDelegate Next; + protected readonly ILogger Logger; + protected readonly RequestDelegate Next; - protected List BlackListHeaders; - protected List WhiteListHeaders; + protected List BlackListHeaders; + protected List WhiteListHeaders; - protected Log(RequestDelegate next, ILogger logger, IOptions blackListHeaders, IOptions whiteListHeaders) - { - Next = next; - Logger = logger; + protected Log(RequestDelegate next, ILogger logger, IOptions blackListHeaders, IOptions whiteListHeaders) + { + Next = next; + Logger = logger; - BlackListHeaders = blackListHeaders.Value.Headers?.Where(x => x != null).Select(x => x.ToLower()).ToList(); - BlackListHeaders ??= new List(); + BlackListHeaders = blackListHeaders.Value.Headers?.Where(x => x != null).Select(x => x.ToLower()).ToList(); + BlackListHeaders ??= new List(); - WhiteListHeaders = whiteListHeaders.Value.Headers?.Where(x => x != null).Select(x => x.ToLower()).ToList(); - WhiteListHeaders ??= new List(); - } + WhiteListHeaders = whiteListHeaders.Value.Headers?.Where(x => x != null).Select(x => x.ToLower()).ToList(); + WhiteListHeaders ??= new List(); } } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/LogMessage.cs b/03-Infrastructure/Jinget.Logger/LogMessage.cs index 5a56844..1015736 100644 --- a/03-Infrastructure/Jinget.Logger/LogMessage.cs +++ b/03-Infrastructure/Jinget.Logger/LogMessage.cs @@ -2,28 +2,27 @@ using System.Text; using Microsoft.Extensions.Logging; -namespace Jinget.Logger +namespace Jinget.Logger; + +public struct LogMessage { - public struct LogMessage - { - public DateTime Timestamp { get; set; } - public string Description { get; set; } - public LogLevel Severity { get; set; } - public string Exception { get; set; } + public DateTime Timestamp { get; set; } + public string Description { get; set; } + public LogLevel Severity { get; set; } + public string Exception { get; set; } - public override string ToString() - { - var builder = new StringBuilder(); - builder.Append(Timestamp.ToString("yyyy-MM-dd HH:mm:ss.fff zzz")); - builder.Append(" ["); - builder.Append(Severity); - builder.Append("] "); - builder.AppendLine(Description); - builder.AppendLine(Exception); + public override string ToString() + { + var builder = new StringBuilder(); + builder.Append(Timestamp.ToString("yyyy-MM-dd HH:mm:ss.fff zzz")); + builder.Append(" ["); + builder.Append(Severity); + builder.Append("] "); + builder.AppendLine(Description); + builder.AppendLine(Exception); - builder.Append(Environment.NewLine); + builder.Append(Environment.NewLine); - return builder.ToString(); - } + return builder.ToString(); } } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/Members/RequestLogger.cs b/03-Infrastructure/Jinget.Logger/Members/RequestLogger.cs index 76c12fc..ae529f9 100644 --- a/03-Infrastructure/Jinget.Logger/Members/RequestLogger.cs +++ b/03-Infrastructure/Jinget.Logger/Members/RequestLogger.cs @@ -13,97 +13,96 @@ using Microsoft.Extensions.Primitives; using Newtonsoft.Json; -namespace Jinget.Logger.Members +namespace Jinget.Logger.Members; + +public class RequestLogger : Log, ILog { - public class RequestLogger : Log, ILog + private readonly IExceptionHandler _exception; + + public RequestLogger(RequestDelegate next, ILogger logger, + IExceptionHandler exception, + IOptions blackListHeaders, + IOptions whiteListHeaders) + : base(next, logger, blackListHeaders, whiteListHeaders) => _exception = exception; + + public async Task LogAsync(HttpContext context) { - private readonly IExceptionHandler _exception; + string requestBodyText; + Stream originalRequestBody = null; + + if (context.Request.GetTypedHeaders() != null && + context.Request.GetTypedHeaders().ContentType != null && + context.Request.GetTypedHeaders().ContentType.MediaType.Value.ToLower().StartsWith("multipart/form-data")) + { + requestBodyText = "--REQUEST BODY TRIMMED BY LOGGER-- multipart/form-data"; + } + else + { + var requestBodyStream = new MemoryStream(); + originalRequestBody = context.Request?.Body; + + await context.Request?.Body.CopyToAsync(requestBodyStream); + + requestBodyStream.Seek(0, SeekOrigin.Begin); + + requestBodyText = await new StreamReader(requestBodyStream).ReadToEndAsync(); - public RequestLogger(RequestDelegate next, ILogger logger, - IExceptionHandler exception, - IOptions blackListHeaders, - IOptions whiteListHeaders) - : base(next, logger, blackListHeaders, whiteListHeaders) => _exception = exception; + requestBodyStream.Seek(0, SeekOrigin.Begin); + context.Request.Body = requestBodyStream; + } + + context.Response.Headers.Add("RequestId", Guid.NewGuid().ToString()); + + var contentLength = context.Request.ContentLength ?? + string.Join(",", context.Request.Headers.Select(x => x.Key + ":" + x.Value).ToList()).Length + + requestBodyText.Length; + context.Request.Headers.TryGetValue("Referer", out StringValues pageUrl); + + string headers = ""; + if (BlackListHeaders.Any()) + headers = JsonConvert.SerializeObject(context.Response.Headers + .Where(x => !BlackListHeaders.Contains(x.Key.ToLower())) + .Select(x => x.ToString()), Formatting.Indented); + else if (WhiteListHeaders.Any()) + headers = JsonConvert.SerializeObject(context.Response.Headers + .Where(x => WhiteListHeaders.Contains(x.Key.ToLower())) + .Select(x => x.ToString()), Formatting.Indented); + + var model = new OperationLog + { + ParitionKey = context.Items["jinget.log.partitionkey"] != null ? context.Items["jinget.log.partitionkey"].ToString() : "", + UserName = context.User.Identity.Name, + When = DateTime.Now, + Method = context.Request.Method, + Body = requestBodyText, + Headers = headers, + Url = context.Request.GetDisplayUrl(), + IP = context.Connection.RemoteIpAddress == null ? "Unknown" : context.Connection.RemoteIpAddress.ToString(), + IsResponse = false, + Description = null, + RequestId = new Guid(context.Response.Headers["RequestId"].ToString()), + Detail = context.Request.Headers["Detail"], + SubSystem = AppDomain.CurrentDomain.FriendlyName, + PageUrl = pageUrl.FirstOrDefault(), + ContentLength = contentLength + }; + + try + { + if (context.Request.Method != "OPTIONS") + Logger.LogInformation(JsonConvert.SerializeObject(model)); - public async Task LogAsync(HttpContext context) + await Next(context); + } + catch (Exception ex) { - string requestBodyText; - Stream originalRequestBody = null; - - if (context.Request.GetTypedHeaders() != null && - context.Request.GetTypedHeaders().ContentType != null && - context.Request.GetTypedHeaders().ContentType.MediaType.Value.ToLower().StartsWith("multipart/form-data")) - { - requestBodyText = "--REQUEST BODY TRIMMED BY LOGGER-- multipart/form-data"; - } - else - { - var requestBodyStream = new MemoryStream(); - originalRequestBody = context.Request?.Body; - - await context.Request?.Body.CopyToAsync(requestBodyStream); - - requestBodyStream.Seek(0, SeekOrigin.Begin); - - requestBodyText = await new StreamReader(requestBodyStream).ReadToEndAsync(); - - requestBodyStream.Seek(0, SeekOrigin.Begin); - context.Request.Body = requestBodyStream; - } - - context.Response.Headers.Add("RequestId", Guid.NewGuid().ToString()); - - var contentLength = context.Request.ContentLength ?? - string.Join(",", context.Request.Headers.Select(x => x.Key + ":" + x.Value).ToList()).Length + - requestBodyText.Length; - context.Request.Headers.TryGetValue("Referer", out StringValues pageUrl); - - string headers = ""; - if (BlackListHeaders.Any()) - headers = JsonConvert.SerializeObject(context.Response.Headers - .Where(x => !BlackListHeaders.Contains(x.Key.ToLower())) - .Select(x => x.ToString()), Formatting.Indented); - else if (WhiteListHeaders.Any()) - headers = JsonConvert.SerializeObject(context.Response.Headers - .Where(x => WhiteListHeaders.Contains(x.Key.ToLower())) - .Select(x => x.ToString()), Formatting.Indented); - - var model = new OperationLog - { - ParitionKey = context.Items["jinget.log.partitionkey"] != null ? context.Items["jinget.log.partitionkey"].ToString() : "", - UserName = context.User.Identity.Name, - When = DateTime.Now, - Method = context.Request.Method, - Body = requestBodyText, - Headers = headers, - Url = context.Request.GetDisplayUrl(), - IP = context.Connection.RemoteIpAddress == null ? "Unknown" : context.Connection.RemoteIpAddress.ToString(), - IsResponse = false, - Description = null, - RequestId = new Guid(context.Response.Headers["RequestId"].ToString()), - Detail = context.Request.Headers["Detail"], - SubSystem = AppDomain.CurrentDomain.FriendlyName, - PageUrl = pageUrl.FirstOrDefault(), - ContentLength = contentLength - }; - - try - { - if (context.Request.Method != "OPTIONS") - Logger.LogInformation(JsonConvert.SerializeObject(model)); - - await Next(context); - } - catch (Exception ex) - { - _exception.Handle(ex, model); - - context.Response.StatusCode = 500; - context.Response.ContentType = MediaTypeNames.Application.Json; - await context.Response.WriteAsync(JsonConvert.SerializeObject(new { error = ex.Message })); - } - - if (originalRequestBody != null) context.Request.Body = originalRequestBody; + _exception.Handle(ex, model); + + context.Response.StatusCode = 500; + context.Response.ContentType = MediaTypeNames.Application.Json; + await context.Response.WriteAsync(JsonConvert.SerializeObject(new { error = ex.Message })); } + + if (originalRequestBody != null) context.Request.Body = originalRequestBody; } } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/Members/ResponseLogger.cs b/03-Infrastructure/Jinget.Logger/Members/ResponseLogger.cs index 8efabc3..86d6e00 100644 --- a/03-Infrastructure/Jinget.Logger/Members/ResponseLogger.cs +++ b/03-Infrastructure/Jinget.Logger/Members/ResponseLogger.cs @@ -11,94 +11,93 @@ using Microsoft.Extensions.Primitives; using Newtonsoft.Json; -namespace Jinget.Logger.Members +namespace Jinget.Logger.Members; + +public class ResponseLogger : Log, ILog { - public class ResponseLogger : Log, ILog + public ResponseLogger(RequestDelegate next, + ILogger logger, + IOptions blackListHeaders, + IOptions whiteListHeaders) + : base(next, logger, blackListHeaders, whiteListHeaders) { } + + public async Task LogAsync(HttpContext context) { - public ResponseLogger(RequestDelegate next, - ILogger logger, - IOptions blackListHeaders, - IOptions whiteListHeaders) - : base(next, logger, blackListHeaders, whiteListHeaders) { } + string responseBody; + Stream responseBodyStream = null; + Stream bodyStream = null; - public async Task LogAsync(HttpContext context) + if (context.Request?.GetTypedHeaders() != null && + context.Request.GetTypedHeaders().ContentType != null && + context.Request.GetTypedHeaders().ContentType.MediaType.Value.ToLower().StartsWith("multipart/form-data")) { - string responseBody; - Stream responseBodyStream = null; - Stream bodyStream = null; - - if (context.Request?.GetTypedHeaders() != null && - context.Request.GetTypedHeaders().ContentType != null && - context.Request.GetTypedHeaders().ContentType.MediaType.Value.ToLower().StartsWith("multipart/form-data")) - { - responseBody = "--RESPONSE BODY TRIMMED BY LOGGER-- multipart/form-data"; + responseBody = "--RESPONSE BODY TRIMMED BY LOGGER-- multipart/form-data"; - await Next(context); - } - else - { - bodyStream = context.Response.Body; - responseBodyStream = new MemoryStream(); + await Next(context); + } + else + { + bodyStream = context.Response.Body; + responseBodyStream = new MemoryStream(); - context.Response.Body = responseBodyStream; - await Next(context); + context.Response.Body = responseBodyStream; + await Next(context); - responseBodyStream.Seek(0, SeekOrigin.Begin); - responseBody = await new StreamReader(responseBodyStream).ReadToEndAsync(); - } + responseBodyStream.Seek(0, SeekOrigin.Begin); + responseBody = await new StreamReader(responseBodyStream).ReadToEndAsync(); + } - var contentLength = context.Response.ContentLength ?? - string.Join(",", - context.Response.Headers.Select(x => x.Key + ":" + x.Value) - .ToList()) - .Length + - responseBody.Length; + var contentLength = context.Response.ContentLength ?? + string.Join(",", + context.Response.Headers.Select(x => x.Key + ":" + x.Value) + .ToList()) + .Length + + responseBody.Length; - context.Request.Headers.TryGetValue("Referer", out StringValues pageUrl); + context.Request.Headers.TryGetValue("Referer", out StringValues pageUrl); - string headers = ""; - if (BlackListHeaders.Any()) - headers = JsonConvert.SerializeObject( - context.Response.Headers - .Where(x => !BlackListHeaders.Contains(x.Key.ToLower())) - .Select(x => x.ToString()), Formatting.Indented); - else if (WhiteListHeaders.Any()) - headers = JsonConvert.SerializeObject(context.Response.Headers - .Where(x => WhiteListHeaders.Contains(x.Key.ToLower())) - .Select(x => x.ToString()), Formatting.Indented); + string headers = ""; + if (BlackListHeaders.Any()) + headers = JsonConvert.SerializeObject( + context.Response.Headers + .Where(x => !BlackListHeaders.Contains(x.Key.ToLower())) + .Select(x => x.ToString()), Formatting.Indented); + else if (WhiteListHeaders.Any()) + headers = JsonConvert.SerializeObject(context.Response.Headers + .Where(x => WhiteListHeaders.Contains(x.Key.ToLower())) + .Select(x => x.ToString()), Formatting.Indented); - var model = new OperationLog - { - ParitionKey = context.Items["jinget.log.partitionkey"] != null ? context.Items["jinget.log.partitionkey"].ToString() : "", - UserName = context.User.Identity.Name, - When = DateTime.Now, - Method = context.Request.Method, - Body = responseBody, - Headers = headers, - Url = context.Request.GetDisplayUrl(), - IP = context.Connection.RemoteIpAddress == null - ? "Unknown" - : context.Connection.RemoteIpAddress.ToString(), - IsResponse = true, - Description = JsonConvert.SerializeObject(new { context.Response.StatusCode }), - RequestId = new Guid(context.Response.Headers["RequestId"].ToString()), - Detail = context.Response.Headers["Detail"], - SubSystem = AppDomain.CurrentDomain.FriendlyName, - PageUrl = pageUrl.FirstOrDefault(), - ContentLength = contentLength - }; + var model = new OperationLog + { + ParitionKey = context.Items["jinget.log.partitionkey"] != null ? context.Items["jinget.log.partitionkey"].ToString() : "", + UserName = context.User.Identity.Name, + When = DateTime.Now, + Method = context.Request.Method, + Body = responseBody, + Headers = headers, + Url = context.Request.GetDisplayUrl(), + IP = context.Connection.RemoteIpAddress == null + ? "Unknown" + : context.Connection.RemoteIpAddress.ToString(), + IsResponse = true, + Description = JsonConvert.SerializeObject(new { context.Response.StatusCode }), + RequestId = new Guid(context.Response.Headers["RequestId"].ToString()), + Detail = context.Response.Headers["Detail"], + SubSystem = AppDomain.CurrentDomain.FriendlyName, + PageUrl = pageUrl.FirstOrDefault(), + ContentLength = contentLength + }; - if (context.Request.Method != "OPTIONS") - { - if (context.Response.StatusCode < 400) - Logger.LogInformation(null, JsonConvert.SerializeObject(model)); - } + if (context.Request.Method != "OPTIONS") + { + if (context.Response.StatusCode < 400) + Logger.LogInformation(null, JsonConvert.SerializeObject(model)); + } - if (responseBodyStream != null && context.Response.StatusCode != 204) - { - responseBodyStream.Seek(0, SeekOrigin.Begin); - await responseBodyStream.CopyToAsync(bodyStream); - } + if (responseBodyStream != null && context.Response.StatusCode != 204) + { + responseBodyStream.Seek(0, SeekOrigin.Begin); + await responseBodyStream.CopyToAsync(bodyStream); } } } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/Providers/BatchingLogger.cs b/03-Infrastructure/Jinget.Logger/Providers/BatchingLogger.cs index c919783..a336e9e 100644 --- a/03-Infrastructure/Jinget.Logger/Providers/BatchingLogger.cs +++ b/03-Infrastructure/Jinget.Logger/Providers/BatchingLogger.cs @@ -1,41 +1,40 @@ using System; using Microsoft.Extensions.Logging; -namespace Jinget.Logger.Providers +namespace Jinget.Logger.Providers; + +public class BatchingLogger : ILogger { - public class BatchingLogger : ILogger - { - private readonly BatchingLoggerProvider _provider; + private readonly BatchingLoggerProvider _provider; - public BatchingLogger(BatchingLoggerProvider loggerProvider) => _provider = loggerProvider; + public BatchingLogger(BatchingLoggerProvider loggerProvider) => _provider = loggerProvider; - public IDisposable BeginScope(TState state) => null; + public IDisposable BeginScope(TState state) => null; - public bool IsEnabled(LogLevel logLevel) => logLevel != LogLevel.None; + public bool IsEnabled(LogLevel logLevel) => logLevel != LogLevel.None; - public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, - Func formatter) - { - if (!IsEnabled(logLevel)) - return; + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, + Func formatter) + { + if (!IsEnabled(logLevel)) + return; - Log(DateTime.Now, logLevel, eventId, state, exception, formatter); - } + Log(DateTime.Now, logLevel, eventId, state, exception, formatter); + } #pragma warning disable IDE0060 // Remove unused parameter - public void Log(DateTime timestamp, LogLevel logLevel, EventId eventId, TState state, + public void Log(DateTime timestamp, LogLevel logLevel, EventId eventId, TState state, #pragma warning restore IDE0060 // Remove unused parameter - Exception exception, Func formatter) - { - _provider.AddMessage( - timestamp, - new LogMessage - { - Description = formatter(state, exception), - Exception = exception == null ? "" : exception.ToString(), - Severity = logLevel, - Timestamp = timestamp - }); - } + Exception exception, Func formatter) + { + _provider.AddMessage( + timestamp, + new LogMessage + { + Description = formatter(state, exception), + Exception = exception == null ? "" : exception.ToString(), + Severity = logLevel, + Timestamp = timestamp + }); } } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/Providers/BatchingLoggerOptions.cs b/03-Infrastructure/Jinget.Logger/Providers/BatchingLoggerOptions.cs index b123c12..6640b58 100644 --- a/03-Infrastructure/Jinget.Logger/Providers/BatchingLoggerOptions.cs +++ b/03-Infrastructure/Jinget.Logger/Providers/BatchingLoggerOptions.cs @@ -1,90 +1,89 @@ using Microsoft.Extensions.Logging; using System; -namespace Jinget.Logger.Providers +namespace Jinget.Logger.Providers; + +public class BatchingLoggerOptions { - public class BatchingLoggerOptions - { - private int? _backgroundQueueSize; - private int? _batchSize = 32; - private string[] _blacklistStrings = Array.Empty(); - private TimeSpan _flushPeriod = TimeSpan.FromSeconds(1); - private LogLevel[] allowedLogLevels; + private int? _backgroundQueueSize; + private int? _batchSize = 32; + private string[] _blacklistStrings = Array.Empty(); + private TimeSpan _flushPeriod = TimeSpan.FromSeconds(1); + private LogLevel[] allowedLogLevels; - /// - /// Defines what log levels should processed - /// Defaults to Trace, Debug, Information, Warning, Error, Critical - /// - public LogLevel[] AllowedLogLevels - { - get => allowedLogLevels; - set => allowedLogLevels = value ?? new LogLevel[] { - LogLevel.Trace, - LogLevel.Debug, - LogLevel.Information, - LogLevel.Warning, - LogLevel.Error, - LogLevel.Critical - }; - } + /// + /// Defines what log levels should processed + /// Defaults to Trace, Debug, Information, Warning, Error, Critical + /// + public LogLevel[] AllowedLogLevels + { + get => allowedLogLevels; + set => allowedLogLevels = value ?? new LogLevel[] { + LogLevel.Trace, + LogLevel.Debug, + LogLevel.Information, + LogLevel.Warning, + LogLevel.Error, + LogLevel.Critical + }; + } - /// - /// Gets or sets the period after which logs will be flushed to the store. - /// - public TimeSpan FlushPeriod + /// + /// Gets or sets the period after which logs will be flushed to the store. + /// + public TimeSpan FlushPeriod + { + get => _flushPeriod; + set { - get => _flushPeriod; - set - { - if (value <= TimeSpan.Zero) - throw new ArgumentOutOfRangeException(nameof(value), $"Jinget Says: {nameof(FlushPeriod)} must be positive."); - _flushPeriod = value; - } + if (value <= TimeSpan.Zero) + throw new ArgumentOutOfRangeException(nameof(value), $"Jinget Says: {nameof(FlushPeriod)} must be positive."); + _flushPeriod = value; } + } - /// - /// Gets or sets the blacklist string. reuqest/responses contain the blacklist array items will not logged. - /// Defaults to empty, so every thing will be logged - /// - public string[] BlackListStrings - { - get => _blacklistStrings; - set => _blacklistStrings = value ?? Array.Empty(); - } + /// + /// Gets or sets the blacklist string. reuqest/responses contain the blacklist array items will not logged. + /// Defaults to empty, so every thing will be logged + /// + public string[] BlackListStrings + { + get => _blacklistStrings; + set => _blacklistStrings = value ?? Array.Empty(); + } - /// - /// Gets or sets the maximum size of the background log message queue or null for no limit. - /// After maximum queue size is reached log event sink would start blocking. - /// Defaults to null. - /// - public int? BackgroundQueueSize + /// + /// Gets or sets the maximum size of the background log message queue or null for no limit. + /// After maximum queue size is reached log event sink would start blocking. + /// Defaults to null. + /// + public int? BackgroundQueueSize + { + get => _backgroundQueueSize; + set { - get => _backgroundQueueSize; - set - { - if (value < 0) - throw new ArgumentOutOfRangeException(nameof(value), $"Jinget Says: {nameof(BackgroundQueueSize)} must be non-negative."); - _backgroundQueueSize = value; - } + if (value < 0) + throw new ArgumentOutOfRangeException(nameof(value), $"Jinget Says: {nameof(BackgroundQueueSize)} must be non-negative."); + _backgroundQueueSize = value; } + } - /// - /// Gets or sets a maximum number of events to include in a single batch or null for no limit. - /// - public int? BatchSize + /// + /// Gets or sets a maximum number of events to include in a single batch or null for no limit. + /// + public int? BatchSize + { + get => _batchSize; + set { - get => _batchSize; - set - { - if (value <= 0) - throw new ArgumentOutOfRangeException(nameof(value), $"Jinget Says: {nameof(BatchSize)} must be positive."); - _batchSize = value; - } + if (value <= 0) + throw new ArgumentOutOfRangeException(nameof(value), $"Jinget Says: {nameof(BatchSize)} must be positive."); + _batchSize = value; } - - /// - /// Gets or sets value indicating if logger accepts and queues writes. - /// - public bool IsEnabled { get; set; } } + + /// + /// Gets or sets value indicating if logger accepts and queues writes. + /// + public bool IsEnabled { get; set; } } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/Providers/BatchingLoggerProvider.cs b/03-Infrastructure/Jinget.Logger/Providers/BatchingLoggerProvider.cs index 12cbf7e..a587348 100644 --- a/03-Infrastructure/Jinget.Logger/Providers/BatchingLoggerProvider.cs +++ b/03-Infrastructure/Jinget.Logger/Providers/BatchingLoggerProvider.cs @@ -7,140 +7,139 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -namespace Jinget.Logger.Providers +namespace Jinget.Logger.Providers; + +public abstract class BatchingLoggerProvider : ILoggerProvider { - public abstract class BatchingLoggerProvider : ILoggerProvider + private readonly LogLevel[] _allowedLogLevels; + private readonly int? _batchSize; + private readonly string[] _blacklistStrings; + private readonly List _currentBatch = new(); + private readonly TimeSpan _interval; + private readonly int? _queueSize; + private CancellationTokenSource _cancellationTokenSource; + + private BlockingCollection _messageQueue; + private Task _outputTask; + + protected BatchingLoggerProvider(IOptions options) { - private readonly LogLevel[] _allowedLogLevels; - private readonly int? _batchSize; - private readonly string[] _blacklistStrings; - private readonly List _currentBatch = new(); - private readonly TimeSpan _interval; - private readonly int? _queueSize; - private CancellationTokenSource _cancellationTokenSource; - - private BlockingCollection _messageQueue; - private Task _outputTask; - - protected BatchingLoggerProvider(IOptions options) - { - // NOTE: Only IsEnabled is monitored - - var loggerOptions = options.Value; - if (loggerOptions.BatchSize <= 0) - throw new ArgumentOutOfRangeException(nameof(loggerOptions.BatchSize), $"Jinget Says: {nameof(loggerOptions.BatchSize)} must be a positive number."); - if (loggerOptions.FlushPeriod <= TimeSpan.Zero) - throw new ArgumentOutOfRangeException(nameof(loggerOptions.FlushPeriod), $"Jinget Says: {nameof(loggerOptions.FlushPeriod)} must be longer than zero."); - - _interval = loggerOptions.FlushPeriod; - _batchSize = loggerOptions.BatchSize; - _queueSize = loggerOptions.BackgroundQueueSize; - _blacklistStrings = loggerOptions.BlackListStrings ?? Array.Empty(); - _allowedLogLevels = loggerOptions.AllowedLogLevels ?? new LogLevel[] { - LogLevel.Trace, - LogLevel.Debug, - LogLevel.Information, - LogLevel.Warning, - LogLevel.Error, - LogLevel.Critical - }; - - Start(); - } + // NOTE: Only IsEnabled is monitored + + var loggerOptions = options.Value; + if (loggerOptions.BatchSize <= 0) + throw new ArgumentOutOfRangeException(nameof(loggerOptions.BatchSize), $"Jinget Says: {nameof(loggerOptions.BatchSize)} must be a positive number."); + if (loggerOptions.FlushPeriod <= TimeSpan.Zero) + throw new ArgumentOutOfRangeException(nameof(loggerOptions.FlushPeriod), $"Jinget Says: {nameof(loggerOptions.FlushPeriod)} must be longer than zero."); + + _interval = loggerOptions.FlushPeriod; + _batchSize = loggerOptions.BatchSize; + _queueSize = loggerOptions.BackgroundQueueSize; + _blacklistStrings = loggerOptions.BlackListStrings ?? Array.Empty(); + _allowedLogLevels = loggerOptions.AllowedLogLevels ?? new LogLevel[] { + LogLevel.Trace, + LogLevel.Debug, + LogLevel.Information, + LogLevel.Warning, + LogLevel.Error, + LogLevel.Critical + }; + + Start(); + } - public void Dispose() - { - StopAsync().GetAwaiter().GetResult(); - GC.SuppressFinalize(this); - } + public void Dispose() + { + StopAsync().GetAwaiter().GetResult(); + GC.SuppressFinalize(this); + } - public ILogger CreateLogger(string categoryName) => new BatchingLogger(this); + public ILogger CreateLogger(string categoryName) => new BatchingLogger(this); - protected abstract Task WriteMessagesAsync(IEnumerable messages, CancellationToken token); + protected abstract Task WriteMessagesAsync(IEnumerable messages, CancellationToken token); - private async Task ProcessLogQueueAsync() + private async Task ProcessLogQueueAsync() + { + while (!_cancellationTokenSource.IsCancellationRequested) { - while (!_cancellationTokenSource.IsCancellationRequested) - { - var limit = _batchSize ?? int.MaxValue; + var limit = _batchSize ?? int.MaxValue; - while (limit > 0 && _messageQueue.TryTake(out var message)) - { - _currentBatch.Add(message); - limit--; - } - - if (_currentBatch.Count > 0) - { - try - { - await WriteMessagesAsync(_currentBatch, _cancellationTokenSource.Token); - } - catch - { - // ignored - } - - _currentBatch.Clear(); - } - - await IntervalAsync(_interval, _cancellationTokenSource.Token); + while (limit > 0 && _messageQueue.TryTake(out var message)) + { + _currentBatch.Add(message); + limit--; } - } - protected virtual Task IntervalAsync(TimeSpan interval, CancellationToken cancellationToken) => Task.Delay(interval, cancellationToken); - - internal void AddMessage(DateTimeOffset timestamp, LogMessage message) - { - //if log severity level is not allowed then ignore it - if (!_allowedLogLevels.Contains(message.Severity)) - return; - - //if log contains blacklist string then ignore it - if (_blacklistStrings.Any(message.ToString().Contains)) - return; - - if (!_messageQueue.IsAddingCompleted) + if (_currentBatch.Count > 0) + { try { - _messageQueue.Add(message, _cancellationTokenSource.Token); + await WriteMessagesAsync(_currentBatch, _cancellationTokenSource.Token); } catch { - //cancellation token canceled or CompleteAdding called + // ignored } - } - private void Start() - { - _messageQueue = _queueSize == null - ? new BlockingCollection(new ConcurrentQueue()) - : new BlockingCollection(new ConcurrentQueue(), _queueSize.Value); - - _cancellationTokenSource = new CancellationTokenSource(); - _outputTask = Task.Factory.StartNew( - ProcessLogQueueAsync, - _cancellationTokenSource.Token, - TaskCreationOptions.LongRunning, - TaskScheduler.Default); + _currentBatch.Clear(); + } + + await IntervalAsync(_interval, _cancellationTokenSource.Token); } + } - private async Task StopAsync() - { - _cancellationTokenSource.Cancel(); - _messageQueue.CompleteAdding(); + protected virtual Task IntervalAsync(TimeSpan interval, CancellationToken cancellationToken) => Task.Delay(interval, cancellationToken); + internal void AddMessage(DateTimeOffset timestamp, LogMessage message) + { + //if log severity level is not allowed then ignore it + if (!_allowedLogLevels.Contains(message.Severity)) + return; + + //if log contains blacklist string then ignore it + if (_blacklistStrings.Any(message.ToString().Contains)) + return; + + if (!_messageQueue.IsAddingCompleted) try { - await _outputTask.WaitAsync(_interval); + _messageQueue.Add(message, _cancellationTokenSource.Token); } - catch (TaskCanceledException) - { - } - catch (AggregateException ex) when (ex.InnerExceptions.Count == 1 && - ex.InnerExceptions[0] is TaskCanceledException) + catch { + //cancellation token canceled or CompleteAdding called } + } + + private void Start() + { + _messageQueue = _queueSize == null + ? new BlockingCollection(new ConcurrentQueue()) + : new BlockingCollection(new ConcurrentQueue(), _queueSize.Value); + + _cancellationTokenSource = new CancellationTokenSource(); + _outputTask = Task.Factory.StartNew( + ProcessLogQueueAsync, + _cancellationTokenSource.Token, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); + } + + private async Task StopAsync() + { + _cancellationTokenSource.Cancel(); + _messageQueue.CompleteAdding(); + + try + { + await _outputTask.WaitAsync(_interval); + } + catch (TaskCanceledException) + { + } + catch (AggregateException ex) when (ex.InnerExceptions.Count == 1 && + ex.InnerExceptions[0] is TaskCanceledException) + { } } } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/Providers/ElasticSearchProvider/ElasticSearchLoggerFactoryExtensions.cs b/03-Infrastructure/Jinget.Logger/Providers/ElasticSearchProvider/ElasticSearchLoggerFactoryExtensions.cs index ab93b2a..92afd74 100644 --- a/03-Infrastructure/Jinget.Logger/Providers/ElasticSearchProvider/ElasticSearchLoggerFactoryExtensions.cs +++ b/03-Infrastructure/Jinget.Logger/Providers/ElasticSearchProvider/ElasticSearchLoggerFactoryExtensions.cs @@ -3,55 +3,54 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -namespace Jinget.Logger.Providers.ElasticSearchProvider +namespace Jinget.Logger.Providers.ElasticSearchProvider; + +/// +/// Extensions for adding the to the +/// +public static class ElasticSearchLoggerFactoryExtensions { /// - /// Extensions for adding the to the + /// Adds a elastic search logger to the factory. /// - public static class ElasticSearchLoggerFactoryExtensions + /// The to use. + public static ILoggingBuilder AddElasticSearch(this ILoggingBuilder builder) + where TOperationalEntity : OperationLog, new() + where TErrorEntity : ErrorLog, new() + where TCustomEntity : CustomLog, new() { - /// - /// Adds a elastic search logger to the factory. - /// - /// The to use. - public static ILoggingBuilder AddElasticSearch(this ILoggingBuilder builder) - where TOperationalEntity : OperationLog, new() - where TErrorEntity : ErrorLog, new() - where TCustomEntity : CustomLog, new() - { - builder.Services.AddSingleton>(); - return builder; - } + builder.Services.AddSingleton>(); + return builder; + } - /// - /// Adds a elastic search logger to the factory. - /// - /// The to use. - /// Configure an instance of the to set logging options - public static ILoggingBuilder AddElasticSearch(this ILoggingBuilder builder, Action configure) - where TOperationalEntity : OperationLog, new() - where TErrorEntity : ErrorLog, new() - where TCustomEntity : CustomLog, new() - { - ArgumentNullException.ThrowIfNull(nameof(configure)); + /// + /// Adds a elastic search logger to the factory. + /// + /// The to use. + /// Configure an instance of the to set logging options + public static ILoggingBuilder AddElasticSearch(this ILoggingBuilder builder, Action configure) + where TOperationalEntity : OperationLog, new() + where TErrorEntity : ErrorLog, new() + where TCustomEntity : CustomLog, new() + { + ArgumentNullException.ThrowIfNull(nameof(configure)); - builder.AddElasticSearch(); - builder.Services.Configure(configure); - return builder; - } + builder.AddElasticSearch(); + builder.Services.Configure(configure); + return builder; + } - /// - /// Adds a elastic search logger to the factory. - /// - /// The to use. - /// Configure an instance of the to set logging options - public static ILoggingBuilder AddElasticSearch(this ILoggingBuilder builder, Action configure) - { - ArgumentNullException.ThrowIfNull(nameof(configure)); + /// + /// Adds a elastic search logger to the factory. + /// + /// The to use. + /// Configure an instance of the to set logging options + public static ILoggingBuilder AddElasticSearch(this ILoggingBuilder builder, Action configure) + { + ArgumentNullException.ThrowIfNull(nameof(configure)); - builder.AddElasticSearch(); - builder.Services.Configure(configure); - return builder; - } + builder.AddElasticSearch(); + builder.Services.Configure(configure); + return builder; } } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/Providers/ElasticSearchProvider/ElasticSearchLoggerOptions.cs b/03-Infrastructure/Jinget.Logger/Providers/ElasticSearchProvider/ElasticSearchLoggerOptions.cs index f796d47..c59317a 100644 --- a/03-Infrastructure/Jinget.Logger/Providers/ElasticSearchProvider/ElasticSearchLoggerOptions.cs +++ b/03-Infrastructure/Jinget.Logger/Providers/ElasticSearchProvider/ElasticSearchLoggerOptions.cs @@ -1,9 +1,8 @@ -namespace Jinget.Logger.Providers.ElasticSearchProvider +namespace Jinget.Logger.Providers.ElasticSearchProvider; + +/// +/// Options for elastic search logging. +/// +public class ElasticSearchLoggerOptions : BatchingLoggerOptions { - /// - /// Options for elastic search logging. - /// - public class ElasticSearchLoggerOptions : BatchingLoggerOptions - { - } } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/Providers/ElasticSearchProvider/ElasticSearchLoggerProvider.cs b/03-Infrastructure/Jinget.Logger/Providers/ElasticSearchProvider/ElasticSearchLoggerProvider.cs index 10bff7f..d614a38 100644 --- a/03-Infrastructure/Jinget.Logger/Providers/ElasticSearchProvider/ElasticSearchLoggerProvider.cs +++ b/03-Infrastructure/Jinget.Logger/Providers/ElasticSearchProvider/ElasticSearchLoggerProvider.cs @@ -10,97 +10,96 @@ using Newtonsoft.Json; using Jinget.Core.ExtensionMethods; -namespace Jinget.Logger.Providers.ElasticSearchProvider +namespace Jinget.Logger.Providers.ElasticSearchProvider; + +/// +/// An that writes logs +/// +[ProviderAlias("ElasticSearch")] +public class ElasticSearchLoggerProvider : BatchingLoggerProvider + where TOperationalEntity : OperationLog, new() + where TErrorEntity : ErrorLog, new() + where TCustomEntity : CustomLog, new() { - /// - /// An that writes logs - /// - [ProviderAlias("ElasticSearch")] - public class ElasticSearchLoggerProvider : BatchingLoggerProvider - where TOperationalEntity : OperationLog, new() - where TErrorEntity : ErrorLog, new() - where TCustomEntity : CustomLog, new() - { - private readonly IServiceProvider _serviceProvider; - private IElasticSearchBaseDomainService _operationLogService; - private IElasticSearchBaseDomainService _errorLogService; - private IElasticSearchBaseDomainService _customLogService; + private readonly IServiceProvider _serviceProvider; + private IElasticSearchBaseDomainService _operationLogService; + private IElasticSearchBaseDomainService _errorLogService; + private IElasticSearchBaseDomainService _customLogService; - public ElasticSearchLoggerProvider( - IOptions options, - IServiceProvider serviceProvider) : base(options) => _serviceProvider = serviceProvider; + public ElasticSearchLoggerProvider( + IOptions options, + IServiceProvider serviceProvider) : base(options) => _serviceProvider = serviceProvider; - protected override async Task WriteMessagesAsync(IEnumerable messages, CancellationToken cancellationToken) - { - _errorLogService = _serviceProvider.GetJingetService>(); - _operationLogService = _serviceProvider.GetJingetService>(); - _customLogService = _serviceProvider.GetJingetService>(); + protected override async Task WriteMessagesAsync(IEnumerable messages, CancellationToken cancellationToken) + { + _errorLogService = _serviceProvider.GetJingetService>(); + _operationLogService = _serviceProvider.GetJingetService>(); + _customLogService = _serviceProvider.GetJingetService>(); - foreach (var group in messages.GroupBy(GetGrouping)) + foreach (var group in messages.GroupBy(GetGrouping)) + { + foreach (LogMessage item in group.Where(x => x.Severity == LogLevel.Information)) { - foreach (LogMessage item in group.Where(x => x.Severity == LogLevel.Information)) + try { - try - { - var result = await _operationLogService.CreateAsync(JsonConvert.DeserializeObject(item.Description)); - } - catch (JsonReaderException) //it means that the message is an error reporting message - { - } + var result = await _operationLogService.CreateAsync(JsonConvert.DeserializeObject(item.Description)); } + catch (JsonReaderException) //it means that the message is an error reporting message + { + } + } - //log errors - foreach (var item in group.Where(x => x.Severity > LogLevel.Information)) + //log errors + foreach (var item in group.Where(x => x.Severity > LogLevel.Information)) + { + TErrorEntity model = null; + try { - TErrorEntity model = null; - try - { - model = JsonConvert.DeserializeObject(item.Description); - } - //if the item.Description is a custom message then - //a JsonReaderException will be thrown because item.Description is not deserializable to TErrorEntity - //so in this case the exception will be caught and model will be constructed manually - catch (JsonReaderException) + model = JsonConvert.DeserializeObject(item.Description); + } + //if the item.Description is a custom message then + //a JsonReaderException will be thrown because item.Description is not deserializable to TErrorEntity + //so in this case the exception will be caught and model will be constructed manually + catch (JsonReaderException) + { + model = new TErrorEntity() { - model = new TErrorEntity() - { - Description = item.Description - }; - } - model.When = item.Timestamp; - model.Severity = item.Severity.ToString(); - - var result = await _errorLogService.CreateAsync(model); + Description = item.Description + }; } + model.When = item.Timestamp; + model.Severity = item.Severity.ToString(); + + var result = await _errorLogService.CreateAsync(model); + } - //log custom data - foreach (var item in group.Where(x => x.Severity < LogLevel.Information)) + //log custom data + foreach (var item in group.Where(x => x.Severity < LogLevel.Information)) + { + TCustomEntity model = null; + try { - TCustomEntity model = null; - try - { - model = JsonConvert.DeserializeObject(item.Description); - } - //if the item.Description is a custom message then - //a JsonReaderException will be thrown because item.Description is not deserializable to TErrorEntity - //so in this case the exception will be caught and model will be constructed manually - catch (JsonReaderException) + model = JsonConvert.DeserializeObject(item.Description); + } + //if the item.Description is a custom message then + //a JsonReaderException will be thrown because item.Description is not deserializable to TErrorEntity + //so in this case the exception will be caught and model will be constructed manually + catch (JsonReaderException) + { + model = new TCustomEntity() { - model = new TCustomEntity() - { - Description = item.Description - }; - } - model.SubSystem = string.IsNullOrEmpty(model.SubSystem) - ? AppDomain.CurrentDomain.FriendlyName - : model.SubSystem; - model.When = item.Timestamp; - - var result = await _customLogService.CreateAsync(model); + Description = item.Description + }; } + model.SubSystem = string.IsNullOrEmpty(model.SubSystem) + ? AppDomain.CurrentDomain.FriendlyName + : model.SubSystem; + model.When = item.Timestamp; + + var result = await _customLogService.CreateAsync(model); } } - - private (int Year, int Month, int Day) GetGrouping(LogMessage message) => (message.Timestamp.Year, message.Timestamp.Month, message.Timestamp.Day); } + + private (int Year, int Month, int Day) GetGrouping(LogMessage message) => (message.Timestamp.Year, message.Timestamp.Month, message.Timestamp.Day); } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/Providers/FileProvider/FileLoggerFactoryExtensions.cs b/03-Infrastructure/Jinget.Logger/Providers/FileProvider/FileLoggerFactoryExtensions.cs index 62d73ab..ef479cd 100644 --- a/03-Infrastructure/Jinget.Logger/Providers/FileProvider/FileLoggerFactoryExtensions.cs +++ b/03-Infrastructure/Jinget.Logger/Providers/FileProvider/FileLoggerFactoryExtensions.cs @@ -2,35 +2,34 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -namespace Jinget.Logger.Providers.FileProvider +namespace Jinget.Logger.Providers.FileProvider; + +/// +/// Extensions for adding the to the +/// +public static class FileLoggerFactoryExtensions { /// - /// Extensions for adding the to the + /// Adds a file logger named 'File' to the factory. /// - public static class FileLoggerFactoryExtensions + /// The to use. + public static ILoggingBuilder AddFile(this ILoggingBuilder builder) { - /// - /// Adds a file logger named 'File' to the factory. - /// - /// The to use. - public static ILoggingBuilder AddFile(this ILoggingBuilder builder) - { - builder.Services.AddSingleton(); - return builder; - } + builder.Services.AddSingleton(); + return builder; + } - /// - /// Adds a file logger named 'File' to the factory. - /// - /// The to use. - /// Configure an instance of the to set logging options - public static ILoggingBuilder AddFile(this ILoggingBuilder builder, Action configure) - { - if (configure == null) throw new ArgumentNullException("Jinget Says: " + nameof(configure)); - builder.AddFile(); - builder.Services.Configure(configure); + /// + /// Adds a file logger named 'File' to the factory. + /// + /// The to use. + /// Configure an instance of the to set logging options + public static ILoggingBuilder AddFile(this ILoggingBuilder builder, Action configure) + { + if (configure == null) throw new ArgumentNullException("Jinget Says: " + nameof(configure)); + builder.AddFile(); + builder.Services.Configure(configure); - return builder; - } + return builder; } } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/Providers/FileProvider/FileLoggerOptions.cs b/03-Infrastructure/Jinget.Logger/Providers/FileProvider/FileLoggerOptions.cs index b90ff3b..263f986 100644 --- a/03-Infrastructure/Jinget.Logger/Providers/FileProvider/FileLoggerOptions.cs +++ b/03-Infrastructure/Jinget.Logger/Providers/FileProvider/FileLoggerOptions.cs @@ -1,67 +1,66 @@ using System; -namespace Jinget.Logger.Providers.FileProvider +namespace Jinget.Logger.Providers.FileProvider; + +/// +/// Options for file logging. +/// +public class FileLoggerOptions : BatchingLoggerOptions { + private string _fileName = "logs-"; + private int? _fileSizeLimit = 10; + private int? _retainedFileCountLimit = 2; + /// - /// Options for file logging. + /// Gets or sets a strictly positive value representing the maximum log size in MB or null for no limit. + /// Once the log is full, no more messages will be appended. + /// Defaults to 10MB. /// - public class FileLoggerOptions : BatchingLoggerOptions + public int? FileSizeLimit { - private string _fileName = "logs-"; - private int? _fileSizeLimit = 10; - private int? _retainedFileCountLimit = 2; - - /// - /// Gets or sets a strictly positive value representing the maximum log size in MB or null for no limit. - /// Once the log is full, no more messages will be appended. - /// Defaults to 10MB. - /// - public int? FileSizeLimit + get => _fileSizeLimit; + set { - get => _fileSizeLimit; - set - { - if (value.HasValue && value <= 0) - throw new ArgumentOutOfRangeException(nameof(value), $"Jinget Says: {nameof(FileSizeLimit)} must be positive."); - _fileSizeLimit = value; - } + if (value.HasValue && value <= 0) + throw new ArgumentOutOfRangeException(nameof(value), $"Jinget Says: {nameof(FileSizeLimit)} must be positive."); + _fileSizeLimit = value; } + } - /// - /// Gets or sets a strictly positive value representing the maximum retained file count or null for no limit. - /// Defaults to 2. - /// - public int? RetainedFileCountLimit + /// + /// Gets or sets a strictly positive value representing the maximum retained file count or null for no limit. + /// Defaults to 2. + /// + public int? RetainedFileCountLimit + { + get => _retainedFileCountLimit; + set { - get => _retainedFileCountLimit; - set - { - if (value.HasValue && value <= 0) - throw new ArgumentOutOfRangeException(nameof(value), - $"Jinget Says: {nameof(RetainedFileCountLimit)} must be positive."); - _retainedFileCountLimit = value; - } + if (value.HasValue && value <= 0) + throw new ArgumentOutOfRangeException(nameof(value), + $"Jinget Says: {nameof(RetainedFileCountLimit)} must be positive."); + _retainedFileCountLimit = value; } + } - /// - /// Gets or sets the filename prefix to use for log files. - /// Defaults to logs-. - /// - public string FileName + /// + /// Gets or sets the filename prefix to use for log files. + /// Defaults to logs-. + /// + public string FileName + { + get => _fileName; + set { - get => _fileName; - set - { - if (string.IsNullOrEmpty(value)) throw new ArgumentException("Jinget Says: " + nameof(value)); - _fileName = value; - } + if (string.IsNullOrEmpty(value)) throw new ArgumentException("Jinget Says: " + nameof(value)); + _fileName = value; } - - /// - /// The directory in which log files will be written, relative to the app process. - /// Default to Logs - /// - /// - public string LogDirectory { get; set; } = "Logs"; } + + /// + /// The directory in which log files will be written, relative to the app process. + /// Default to Logs + /// + /// + public string LogDirectory { get; set; } = "Logs"; } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/Providers/FileProvider/FileLoggerProvider.cs b/03-Infrastructure/Jinget.Logger/Providers/FileProvider/FileLoggerProvider.cs index ee18160..d565ec5 100644 --- a/03-Infrastructure/Jinget.Logger/Providers/FileProvider/FileLoggerProvider.cs +++ b/03-Infrastructure/Jinget.Logger/Providers/FileProvider/FileLoggerProvider.cs @@ -6,74 +6,73 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -namespace Jinget.Logger.Providers.FileProvider +namespace Jinget.Logger.Providers.FileProvider; + +/// +/// An that writes logs +/// +[ProviderAlias("File")] +public class FileLoggerProvider : BatchingLoggerProvider { + private readonly string _fileName; + private readonly long? _maxFileSize; + private readonly int? _maxRetainedFiles; + private readonly string _path; + /// - /// An that writes logs + /// Creates an instance of the /// - [ProviderAlias("File")] - public class FileLoggerProvider : BatchingLoggerProvider + /// The options object controlling the logger + public FileLoggerProvider(IOptions options) : base(options) { - private readonly string _fileName; - private readonly long? _maxFileSize; - private readonly int? _maxRetainedFiles; - private readonly string _path; + var loggerOptions = options.Value; + _path = loggerOptions.LogDirectory; + _fileName = loggerOptions.FileName; + _maxFileSize = loggerOptions.FileSizeLimit * 1024 * 1024; + _maxRetainedFiles = loggerOptions.RetainedFileCountLimit; + } - /// - /// Creates an instance of the - /// - /// The options object controlling the logger - public FileLoggerProvider(IOptions options) : base(options) - { - var loggerOptions = options.Value; - _path = loggerOptions.LogDirectory; - _fileName = loggerOptions.FileName; - _maxFileSize = loggerOptions.FileSizeLimit * 1024 * 1024; - _maxRetainedFiles = loggerOptions.RetainedFileCountLimit; - } + /// + protected override async Task WriteMessagesAsync(IEnumerable messages, + CancellationToken cancellationToken) + { + if (!Directory.Exists(_path)) Directory.CreateDirectory(_path); - /// - protected override async Task WriteMessagesAsync(IEnumerable messages, - CancellationToken cancellationToken) + foreach (var group in messages.GroupBy(GetGrouping)) { - if (!Directory.Exists(_path)) Directory.CreateDirectory(_path); - - foreach (var group in messages.GroupBy(GetGrouping)) - { - var fullName = GetFullName(group.Key); - var fileInfo = new FileInfo(fullName); - if (_maxFileSize.HasValue && - _maxFileSize > 0 && - fileInfo.Exists && - fileInfo.Length > _maxFileSize) - return; + var fullName = GetFullName(group.Key); + var fileInfo = new FileInfo(fullName); + if (_maxFileSize.HasValue && + _maxFileSize > 0 && + fileInfo.Exists && + fileInfo.Length > _maxFileSize) + return; - using var streamWriter = File.AppendText(fullName); - foreach (var item in group) - await streamWriter.WriteAsync(item.ToString()); - } - - RollFiles(); + using var streamWriter = File.AppendText(fullName); + foreach (var item in group) + await streamWriter.WriteAsync(item.ToString()); } - private string GetFullName((int Year, int Month, int Day) group) => Path.Combine(_path, $"{_fileName}{@group.Year:0000}{@group.Month:00}{@group.Day:00}.txt"); + RollFiles(); + } + + private string GetFullName((int Year, int Month, int Day) group) => Path.Combine(_path, $"{_fileName}{@group.Year:0000}{@group.Month:00}{@group.Day:00}.txt"); - private (int Year, int Month, int Day) GetGrouping(LogMessage message) => (message.Timestamp.Year, message.Timestamp.Month, message.Timestamp.Day); + private (int Year, int Month, int Day) GetGrouping(LogMessage message) => (message.Timestamp.Year, message.Timestamp.Month, message.Timestamp.Day); - /// - /// Deletes old log files, keeping a number of files defined by - /// - protected void RollFiles() + /// + /// Deletes old log files, keeping a number of files defined by + /// + protected void RollFiles() + { + if (_maxRetainedFiles > 0) { - if (_maxRetainedFiles > 0) - { - var files = new DirectoryInfo(_path) - .GetFiles(_fileName + "*") - .OrderByDescending(f => f.Name) - .Skip(_maxRetainedFiles.Value); + var files = new DirectoryInfo(_path) + .GetFiles(_fileName + "*") + .OrderByDescending(f => f.Name) + .Skip(_maxRetainedFiles.Value); - foreach (var item in files) item.Delete(); - } + foreach (var item in files) item.Delete(); } } } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/ViewModels/LogSearchViewModel.cs b/03-Infrastructure/Jinget.Logger/ViewModels/LogSearchViewModel.cs index 18faa87..42e77b3 100644 --- a/03-Infrastructure/Jinget.Logger/ViewModels/LogSearchViewModel.cs +++ b/03-Infrastructure/Jinget.Logger/ViewModels/LogSearchViewModel.cs @@ -2,29 +2,28 @@ using System.Collections.Generic; using static Jinget.Logger.ViewModels.LogSearchViewModel; -namespace Jinget.Logger.ViewModels +namespace Jinget.Logger.ViewModels; + +public record LogSearchViewModel( + Guid RequestId, + string IP, + string Url, + string Method, + string PageUrl, + IEnumerable Operations, + IEnumerable Errors) { - public record LogSearchViewModel( - Guid RequestId, - string IP, - string Url, - string Method, - string PageUrl, - IEnumerable Operations, - IEnumerable Errors) - { - public record OperationLogSearchViewModel( - string Type, - DateTime When, - string Body, - long ContentLength, - string Headers, - string Detail, - string Description); + public record OperationLogSearchViewModel( + string Type, + DateTime When, + string Body, + long ContentLength, + string Headers, + string Detail, + string Description); - public record ErrorLogSearchViewModel( - DateTime When, - string Description, - string Severity); - } + public record ErrorLogSearchViewModel( + DateTime When, + string Description, + string Severity); } \ No newline at end of file diff --git a/03-Infrastructure/Jinget.Logger/ViewModels/LogViewModel.cs b/03-Infrastructure/Jinget.Logger/ViewModels/LogViewModel.cs index 62d740e..bbee1a1 100644 --- a/03-Infrastructure/Jinget.Logger/ViewModels/LogViewModel.cs +++ b/03-Infrastructure/Jinget.Logger/ViewModels/LogViewModel.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; -namespace Jinget.Logger.ViewModels -{ - internal record LogViewModel(IGrouping Op, IReadOnlyCollection Err); -} \ No newline at end of file +namespace Jinget.Logger.ViewModels; + +internal record LogViewModel(IGrouping Op, IReadOnlyCollection Err); \ No newline at end of file diff --git a/04-Presentation/Jinget.Blazor/Attributes/Core/JingetFormElement.cs b/04-Presentation/Jinget.Blazor/Attributes/Core/JingetFormElement.cs index 9eed27d..a36f462 100644 --- a/04-Presentation/Jinget.Blazor/Attributes/Core/JingetFormElement.cs +++ b/04-Presentation/Jinget.Blazor/Attributes/Core/JingetFormElement.cs @@ -1,41 +1,40 @@ using System.Runtime.CompilerServices; -namespace Jinget.Blazor.Attributes.Core -{ - [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] +namespace Jinget.Blazor.Attributes.Core; + +[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - public abstract class JingetFormElement([CallerMemberName] string? propertyName = null) : Attribute +public abstract class JingetFormElement([CallerMemberName] string? propertyName = null) : Attribute #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - { - public string? PropertyName { get; } = propertyName; +{ + public string? PropertyName { get; } = propertyName; - /// - /// Used as form element id - /// - public string Id { get; set; } + /// + /// Used as form element id + /// + public string Id { get; set; } - /// - /// form elements are being rendered on screen based on their order. - /// If no order is specified, then default order will be assigned to it. default value is int.MaxValue; - /// - public int Order { get; set; } = int.MaxValue; + /// + /// form elements are being rendered on screen based on their order. + /// If no order is specified, then default order will be assigned to it. default value is int.MaxValue; + /// + public int Order { get; set; } = int.MaxValue; - /// - /// Used as form element label text - /// - public string? DisplayName { get; set; } = null; + /// + /// Used as form element label text + /// + public string? DisplayName { get; set; } = null; - /// - /// CSS class. default is 'form-control' - /// - public string LabelCssClass { get; set; } = "col-3"; - public bool HasLabel { get; set; } = false; - public string DivCssClass { get; set; } = "col-3"; - public string CssClass { get; set; } = "form-control"; - public bool IsVisible { get; set; } = true; - public bool IsDisabled { get; set; } = false; - public bool IsReadOnly { get; set; } = false; - public string HelperText { get; set; } + /// + /// CSS class. default is 'form-control' + /// + public string LabelCssClass { get; set; } = "col-3"; + public bool HasLabel { get; set; } = false; + public string DivCssClass { get; set; } = "col-3"; + public string CssClass { get; set; } = "form-control"; + public bool IsVisible { get; set; } = true; + public bool IsDisabled { get; set; } = false; + public bool IsReadOnly { get; set; } = false; + public string HelperText { get; set; } - } } \ No newline at end of file diff --git a/04-Presentation/Jinget.Blazor/Attributes/Input/JingetEmailBox.cs b/04-Presentation/Jinget.Blazor/Attributes/Input/JingetEmailBox.cs index 445befa..1654f2d 100644 --- a/04-Presentation/Jinget.Blazor/Attributes/Input/JingetEmailBox.cs +++ b/04-Presentation/Jinget.Blazor/Attributes/Input/JingetEmailBox.cs @@ -1,6 +1,5 @@ -namespace Jinget.Blazor.Attributes.Input +namespace Jinget.Blazor.Attributes.Input; + +public class JingetEmailBox : JingetFormElement { - public class JingetEmailBox : JingetFormElement - { - } } \ No newline at end of file diff --git a/04-Presentation/Jinget.Blazor/Attributes/Input/JingetNumberBox.cs b/04-Presentation/Jinget.Blazor/Attributes/Input/JingetNumberBox.cs index 20a1f59..1aa343f 100644 --- a/04-Presentation/Jinget.Blazor/Attributes/Input/JingetNumberBox.cs +++ b/04-Presentation/Jinget.Blazor/Attributes/Input/JingetNumberBox.cs @@ -1,6 +1,5 @@ -namespace Jinget.Blazor.Attributes.Input +namespace Jinget.Blazor.Attributes.Input; + +public class JingetNumberBox : JingetFormElement { - public class JingetNumberBox : JingetFormElement - { - } } \ No newline at end of file diff --git a/04-Presentation/Jinget.Blazor/Attributes/Input/JingetPasswordBox.cs b/04-Presentation/Jinget.Blazor/Attributes/Input/JingetPasswordBox.cs index 7b846a9..aceb1bb 100644 --- a/04-Presentation/Jinget.Blazor/Attributes/Input/JingetPasswordBox.cs +++ b/04-Presentation/Jinget.Blazor/Attributes/Input/JingetPasswordBox.cs @@ -1,6 +1,5 @@ -namespace Jinget.Blazor.Attributes.Input +namespace Jinget.Blazor.Attributes.Input; + +public class JingetPasswordBox : JingetFormElement { - public class JingetPasswordBox : JingetFormElement - { - } } \ No newline at end of file diff --git a/04-Presentation/Jinget.Blazor/Attributes/Input/JingetTelephoneBox.cs b/04-Presentation/Jinget.Blazor/Attributes/Input/JingetTelephoneBox.cs index 0e48038..025e4e2 100644 --- a/04-Presentation/Jinget.Blazor/Attributes/Input/JingetTelephoneBox.cs +++ b/04-Presentation/Jinget.Blazor/Attributes/Input/JingetTelephoneBox.cs @@ -1,6 +1,5 @@ -namespace Jinget.Blazor.Attributes.Input +namespace Jinget.Blazor.Attributes.Input; + +public class JingetTelephoneBox : JingetFormElement { - public class JingetTelephoneBox : JingetFormElement - { - } } \ No newline at end of file diff --git a/04-Presentation/Jinget.Blazor/Attributes/Input/JingetTextArea.cs b/04-Presentation/Jinget.Blazor/Attributes/Input/JingetTextArea.cs index 78e490e..ebed6d9 100644 --- a/04-Presentation/Jinget.Blazor/Attributes/Input/JingetTextArea.cs +++ b/04-Presentation/Jinget.Blazor/Attributes/Input/JingetTextArea.cs @@ -1,7 +1,6 @@ -namespace Jinget.Blazor.Attributes.Input +namespace Jinget.Blazor.Attributes.Input; + +public class JingetTextArea : JingetFormElement { - public class JingetTextArea : JingetFormElement - { - public int Rows { get; set; } - } + public int Rows { get; set; } } \ No newline at end of file diff --git a/04-Presentation/Jinget.Blazor/Attributes/Input/JingetTextBox.cs b/04-Presentation/Jinget.Blazor/Attributes/Input/JingetTextBox.cs index 9c5aa81..1009f09 100644 --- a/04-Presentation/Jinget.Blazor/Attributes/Input/JingetTextBox.cs +++ b/04-Presentation/Jinget.Blazor/Attributes/Input/JingetTextBox.cs @@ -1,6 +1,5 @@ -namespace Jinget.Blazor.Attributes.Input +namespace Jinget.Blazor.Attributes.Input; + +public class JingetTextBox : JingetFormElement { - public class JingetTextBox : JingetFormElement - { - } } \ No newline at end of file diff --git a/04-Presentation/Jinget.Blazor/Attributes/JingetComboBox.cs b/04-Presentation/Jinget.Blazor/Attributes/JingetComboBox.cs index 7584a13..da9bc3a 100644 --- a/04-Presentation/Jinget.Blazor/Attributes/JingetComboBox.cs +++ b/04-Presentation/Jinget.Blazor/Attributes/JingetComboBox.cs @@ -1,33 +1,32 @@ -namespace Jinget.Blazor.Attributes +namespace Jinget.Blazor.Attributes; + +public class JingetComboBox : JingetFormElement { - public class JingetComboBox : JingetFormElement - { - public string DefaultText { get; set; } = "---انتخاب کنید---"; + public string DefaultText { get; set; } = "---انتخاب کنید---"; - public bool Searchable { get; set; } - /// - /// set a method which will be called automatically while binding the element - /// - public string? BindingFunction { get; set; } + public bool Searchable { get; set; } + /// + /// set a method which will be called automatically while binding the element + /// + public string? BindingFunction { get; set; } - public async Task> BindAsync(Func>> GetData) - where T : BaseTypeModel => await BindAsync(GetData).ConfigureAwait(false); + public async Task> BindAsync(Func>> GetData) + where T : BaseTypeModel => await BindAsync(GetData).ConfigureAwait(false); - public async Task> BindAsync(Func>> GetData) - where T : BaseTypeModel - { - List result = []; - var data = await GetData.Invoke().ConfigureAwait(false); + public async Task> BindAsync(Func>> GetData) + where T : BaseTypeModel + { + List result = []; + var data = await GetData.Invoke().ConfigureAwait(false); - if (data != null) + if (data != null) + { + foreach (var item in data) { - foreach (var item in data) - { - result.Add(new(item.Code, item.Title, false)); - } + result.Add(new(item.Code, item.Title, false)); } - return result; } + return result; } } \ No newline at end of file diff --git a/04-Presentation/Jinget.Blazor/Attributes/JingetLabel.cs b/04-Presentation/Jinget.Blazor/Attributes/JingetLabel.cs index 4d9a984..2e552e6 100644 --- a/04-Presentation/Jinget.Blazor/Attributes/JingetLabel.cs +++ b/04-Presentation/Jinget.Blazor/Attributes/JingetLabel.cs @@ -1,6 +1,5 @@ -namespace Jinget.Blazor.Attributes +namespace Jinget.Blazor.Attributes; + +public class JingetLabel : JingetFormElement { - public class JingetLabel : JingetFormElement - { - } } \ No newline at end of file diff --git a/04-Presentation/Jinget.Blazor/Attributes/JingetList.cs b/04-Presentation/Jinget.Blazor/Attributes/JingetList.cs index abab1f4..8daeba6 100644 --- a/04-Presentation/Jinget.Blazor/Attributes/JingetList.cs +++ b/04-Presentation/Jinget.Blazor/Attributes/JingetList.cs @@ -1,11 +1,10 @@  -namespace Jinget.Blazor.Attributes +namespace Jinget.Blazor.Attributes; + +public class JingetList : JingetFormElement { - public class JingetList : JingetFormElement - { - /// - /// Property which its content will be rendered as list body content text - /// - public string? BodyMember { get; set; } - } + /// + /// Property which its content will be rendered as list body content text + /// + public string? BodyMember { get; set; } } \ No newline at end of file diff --git a/04-Presentation/Jinget.Blazor/Attributes/JingetTable.cs b/04-Presentation/Jinget.Blazor/Attributes/JingetTable.cs index 71dd5ae..0a372c3 100644 --- a/04-Presentation/Jinget.Blazor/Attributes/JingetTable.cs +++ b/04-Presentation/Jinget.Blazor/Attributes/JingetTable.cs @@ -1,10 +1,9 @@ -namespace Jinget.Blazor.Attributes -{ - [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] - public class JingetTable : JingetFormElement { } +namespace Jinget.Blazor.Attributes; + +[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] +public class JingetTable : JingetFormElement { } - public class JingetTableMember : JingetFormElement - { - public bool Sortable { get; set; } - } +public class JingetTableMember : JingetFormElement +{ + public bool Sortable { get; set; } } \ No newline at end of file diff --git a/04-Presentation/Jinget.Blazor/Attributes/Picker/JingetDatePicker.cs b/04-Presentation/Jinget.Blazor/Attributes/Picker/JingetDatePicker.cs index dfeeb73..d1d17c6 100644 --- a/04-Presentation/Jinget.Blazor/Attributes/Picker/JingetDatePicker.cs +++ b/04-Presentation/Jinget.Blazor/Attributes/Picker/JingetDatePicker.cs @@ -1,7 +1,6 @@ -namespace Jinget.Blazor.Attributes.Picker -{ +namespace Jinget.Blazor.Attributes.Picker; + - public class JingetDatePicker : JingetDatePickerBase - { - } +public class JingetDatePicker : JingetDatePickerBase +{ } \ No newline at end of file diff --git a/04-Presentation/Jinget.Blazor/Attributes/Picker/JingetDatePickerBase.cs b/04-Presentation/Jinget.Blazor/Attributes/Picker/JingetDatePickerBase.cs index ae8988d..06454ee 100644 --- a/04-Presentation/Jinget.Blazor/Attributes/Picker/JingetDatePickerBase.cs +++ b/04-Presentation/Jinget.Blazor/Attributes/Picker/JingetDatePickerBase.cs @@ -1,9 +1,8 @@ -namespace Jinget.Blazor.Attributes.Picker -{ +namespace Jinget.Blazor.Attributes.Picker; + - public abstract class JingetDatePickerBase : JingetFormElement - { - public string Culture { get; set; } - public bool EnglishNumber { get; set; } - } +public abstract class JingetDatePickerBase : JingetFormElement +{ + public string Culture { get; set; } + public bool EnglishNumber { get; set; } } \ No newline at end of file diff --git a/04-Presentation/Jinget.Blazor/Attributes/Picker/JingetDateRangePicker.cs b/04-Presentation/Jinget.Blazor/Attributes/Picker/JingetDateRangePicker.cs index 01e6255..030b850 100644 --- a/04-Presentation/Jinget.Blazor/Attributes/Picker/JingetDateRangePicker.cs +++ b/04-Presentation/Jinget.Blazor/Attributes/Picker/JingetDateRangePicker.cs @@ -1,6 +1,5 @@ -namespace Jinget.Blazor.Attributes.Picker +namespace Jinget.Blazor.Attributes.Picker; + +public class JingetDateRangePicker : JingetDatePickerBase { - public class JingetDateRangePicker : JingetDatePickerBase - { - } } \ No newline at end of file diff --git a/04-Presentation/Jinget.Blazor/Components/Captcha/JingetCaptcha.cs b/04-Presentation/Jinget.Blazor/Components/Captcha/JingetCaptcha.cs index 6f4d5cb..d9337de 100644 --- a/04-Presentation/Jinget.Blazor/Components/Captcha/JingetCaptcha.cs +++ b/04-Presentation/Jinget.Blazor/Components/Captcha/JingetCaptcha.cs @@ -1,337 +1,336 @@ using SkiaSharp; -namespace Jinget.Blazor.Components.Captcha +namespace Jinget.Blazor.Components.Captcha; + +public class JingetCaptcha : ComponentBase { - public class JingetCaptcha : ComponentBase + class Letter { - class Letter - { - public int Angle { get; set; } - public string? Value { get; set; } - public SKColor ForeColor { get; set; } - public string? FontFamily { get; set; } - } - - public enum CharSetCaseSensitivityOptions : byte - { - /// - /// Only upper case characters will be used for rendering - /// - UpperCaseOnly, - - /// - /// Only lower case characters will be used for rendering - /// - LowerCaseOnly, - - /// - /// Both upper and lower case characters will be used for rendering - /// - IgnoreCase - } - - public enum CharSetTypeOptions : byte - { - /// - /// Only digits will be used for rendering(0-9) - /// - DigitOnly, - - /// - /// Only English characters will be used for rendering - /// - EnglishCharsOnly, - - /// - /// Only Farsi characters will be used for rendering. - /// It is important to set the =true for currect rendering. - /// Otherwise characters will be rendered in reverse order - /// - FarsiCharsOnly, - - /// - /// Only English characters and digits will be used for rendering. - /// - EnglishCharsPlusDigit, - - /// - /// Only Farsi characters and digits will be used for rendering. - /// It is important to set the =true for currect rendering. - /// Otherwise characters will be rendered in reverse order - /// - FarsiCharsPlusDigit, - - /// - /// Only Farsi and English characters will be used for rendering. - /// It is important to set the =true for currect rendering. - /// Otherwise characters will be rendered in reverse order. - /// Because of UX issue, this combination is not recomended - /// - EnglishCharsPlusFarsiChars, - - /// - /// All the Farsi and English characters and digits will be used for rendering. - /// It is important to set the =true for currect rendering. - /// Otherwise characters will be rendered in reverse order. - /// Because of UX issue, this combination is not recomended - /// - BlendAll, - - /// - /// characters provided by will be used for rendering. - /// - Custom - } - - List GetEnglishChars() - { - return ContentCaseSensitivity switch - { - CharSetCaseSensitivityOptions.LowerCaseOnly => [.. StringUtility.GetEnglishChars(true).ToCharArray()], - CharSetCaseSensitivityOptions.UpperCaseOnly => [.. StringUtility.GetEnglishChars(false).ToCharArray()], - CharSetCaseSensitivityOptions.IgnoreCase => [.. StringUtility.GetEnglishChars(true).ToCharArray(), .. StringUtility.GetEnglishChars(false).ToCharArray()], - _ => [], - }; - } + public int Angle { get; set; } + public string? Value { get; set; } + public SKColor ForeColor { get; set; } + public string? FontFamily { get; set; } + } - string GetCaptchaWord(int length) - { - List chars = CharSetType switch - { - CharSetTypeOptions.DigitOnly => [.. StringUtility.GetEnglishDigits().ToCharArray()], - CharSetTypeOptions.EnglishCharsOnly => GetEnglishChars(), - CharSetTypeOptions.FarsiCharsOnly => StringUtility.GetFarsiChars(), - CharSetTypeOptions.EnglishCharsPlusDigit => [.. GetEnglishChars(), .. StringUtility.GetEnglishDigits().ToCharArray()], - CharSetTypeOptions.FarsiCharsPlusDigit => [.. StringUtility.GetFarsiChars(), .. StringUtility.GetEnglishDigits().ToCharArray()], - CharSetTypeOptions.EnglishCharsPlusFarsiChars => [.. GetEnglishChars(), .. StringUtility.GetFarsiChars()], - CharSetTypeOptions.BlendAll => [.. GetEnglishChars(), .. StringUtility.GetFarsiChars(), .. StringUtility.GetEnglishDigits().ToCharArray()], - CharSetTypeOptions.Custom => [.. CustomCharSet.ToCharArray()], - _ => [] - }; - - var random = new Random(DateTime.Now.Millisecond); - return new(Enumerable.Repeat(chars, length) - .Select(s => s[random.Next(s.Count)]) - .ToArray()); - } + public enum CharSetCaseSensitivityOptions : byte + { + /// + /// Only upper case characters will be used for rendering + /// + UpperCaseOnly, /// - /// Captcha image box width. - /// Default is 170 + /// Only lower case characters will be used for rendering /// - [Parameter] public int Width { get; set; } = 170; + LowerCaseOnly, /// - /// Captcha image box height. - /// Default is 40 + /// Both upper and lower case characters will be used for rendering /// - [Parameter] public int Height { get; set; } = 40; + IgnoreCase + } - int charCount = 5; + public enum CharSetTypeOptions : byte + { /// - /// Total number of characters to be rendered in image. - /// Default value is 5. The value should be greater than 0 otherwise it will be replaced by 5 + /// Only digits will be used for rendering(0-9) /// - [Parameter] - public int CharCount - { - get => charCount; set - { - if (value <= 0) - value = 5; - charCount = value; - } - } + DigitOnly, /// - /// Set the character set used for rendering the image. - /// Default is + /// Only English characters will be used for rendering /// - [Parameter] public CharSetTypeOptions CharSetType { get; set; } = CharSetTypeOptions.DigitOnly; + EnglishCharsOnly, /// - /// If is set to - /// then characters provided by will be used to render the image + /// Only Farsi characters will be used for rendering. + /// It is important to set the =true for currect rendering. + /// Otherwise characters will be rendered in reverse order /// - [Parameter] public string CustomCharSet { get; set; } = ""; + FarsiCharsOnly, /// - /// Set the character set case sensitivity used for rendering the image. - /// This property is only applied to the English characters. - /// Default value is + /// Only English characters and digits will be used for rendering. /// - [Parameter] public CharSetCaseSensitivityOptions ContentCaseSensitivity { get; set; } = CharSetCaseSensitivityOptions.IgnoreCase; + EnglishCharsPlusDigit, /// - /// Check if the input captcha text validation should be done in case sensitive or case insensitive manner. + /// Only Farsi characters and digits will be used for rendering. + /// It is important to set the =true for currect rendering. + /// Otherwise characters will be rendered in reverse order /// - [Parameter] public bool CaseSesitiveComparison { get; set; } + FarsiCharsPlusDigit, /// - /// If RTL language's character set is being used(such as Farsi, Arabic, etc), - /// this property should be set to true. + /// Only Farsi and English characters will be used for rendering. + /// It is important to set the =true for currect rendering. + /// Otherwise characters will be rendered in reverse order. + /// Because of UX issue, this combination is not recomended /// - [Parameter] public bool IsRtlCharSet { get; set; } + EnglishCharsPlusFarsiChars, /// - /// Sets the Font families used for drawing the text inside the image. - /// Default Values are: Arial, Tahoma and Times New Roman + /// All the Farsi and English characters and digits will be used for rendering. + /// It is important to set the =true for currect rendering. + /// Otherwise characters will be rendered in reverse order. + /// Because of UX issue, this combination is not recomended /// - [Parameter] public string[] FontFamilies { get; set; } = ["Arial", "Tahoma", "Times New Roman"]; + BlendAll, /// - /// Fires a callback whenever the captcha image is changed + /// characters provided by will be used for rendering. /// - [Parameter] public EventCallback CaptchaChanged { get; set; } + Custom + } - string? captchaWord; - Random? randomValue; - List letters = []; - SKColor bgColor; + List GetEnglishChars() + { + return ContentCaseSensitivity switch + { + CharSetCaseSensitivityOptions.LowerCaseOnly => [.. StringUtility.GetEnglishChars(true).ToCharArray()], + CharSetCaseSensitivityOptions.UpperCaseOnly => [.. StringUtility.GetEnglishChars(false).ToCharArray()], + CharSetCaseSensitivityOptions.IgnoreCase => [.. StringUtility.GetEnglishChars(true).ToCharArray(), .. StringUtility.GetEnglishChars(false).ToCharArray()], + _ => [], + }; + } - protected override async Task OnInitializedAsync() + string GetCaptchaWord(int length) + { + List chars = CharSetType switch { - await GetNewCaptchaAsync(); - await base.OnInitializedAsync(); - } + CharSetTypeOptions.DigitOnly => [.. StringUtility.GetEnglishDigits().ToCharArray()], + CharSetTypeOptions.EnglishCharsOnly => GetEnglishChars(), + CharSetTypeOptions.FarsiCharsOnly => StringUtility.GetFarsiChars(), + CharSetTypeOptions.EnglishCharsPlusDigit => [.. GetEnglishChars(), .. StringUtility.GetEnglishDigits().ToCharArray()], + CharSetTypeOptions.FarsiCharsPlusDigit => [.. StringUtility.GetFarsiChars(), .. StringUtility.GetEnglishDigits().ToCharArray()], + CharSetTypeOptions.EnglishCharsPlusFarsiChars => [.. GetEnglishChars(), .. StringUtility.GetFarsiChars()], + CharSetTypeOptions.BlendAll => [.. GetEnglishChars(), .. StringUtility.GetFarsiChars(), .. StringUtility.GetEnglishDigits().ToCharArray()], + CharSetTypeOptions.Custom => [.. CustomCharSet.ToCharArray()], + _ => [] + }; + + var random = new Random(DateTime.Now.Millisecond); + return new(Enumerable.Repeat(chars, length) + .Select(s => s[random.Next(s.Count)]) + .ToArray()); + } - void Initialization() + /// + /// Captcha image box width. + /// Default is 170 + /// + [Parameter] public int Width { get; set; } = 170; + + /// + /// Captcha image box height. + /// Default is 40 + /// + [Parameter] public int Height { get; set; } = 40; + + int charCount = 5; + /// + /// Total number of characters to be rendered in image. + /// Default value is 5. The value should be greater than 0 otherwise it will be replaced by 5 + /// + [Parameter] + public int CharCount + { + get => charCount; set { - if (string.IsNullOrEmpty(captchaWord)) return; + if (value <= 0) + value = 5; + charCount = value; + } + } - randomValue = new Random(); - bgColor = new SKColor((byte)randomValue.Next(70, 100), - (byte)randomValue.Next(60, 80), - (byte)randomValue.Next(50, 90) - ); + /// + /// Set the character set used for rendering the image. + /// Default is + /// + [Parameter] public CharSetTypeOptions CharSetType { get; set; } = CharSetTypeOptions.DigitOnly; + + /// + /// If is set to + /// then characters provided by will be used to render the image + /// + [Parameter] public string CustomCharSet { get; set; } = ""; + + /// + /// Set the character set case sensitivity used for rendering the image. + /// This property is only applied to the English characters. + /// Default value is + /// + [Parameter] public CharSetCaseSensitivityOptions ContentCaseSensitivity { get; set; } = CharSetCaseSensitivityOptions.IgnoreCase; + + /// + /// Check if the input captcha text validation should be done in case sensitive or case insensitive manner. + /// + [Parameter] public bool CaseSesitiveComparison { get; set; } + + /// + /// If RTL language's character set is being used(such as Farsi, Arabic, etc), + /// this property should be set to true. + /// + [Parameter] public bool IsRtlCharSet { get; set; } + + /// + /// Sets the Font families used for drawing the text inside the image. + /// Default Values are: Arial, Tahoma and Times New Roman + /// + [Parameter] public string[] FontFamilies { get; set; } = ["Arial", "Tahoma", "Times New Roman"]; + + /// + /// Fires a callback whenever the captcha image is changed + /// + [Parameter] public EventCallback CaptchaChanged { get; set; } + + string? captchaWord; + Random? randomValue; + List letters = []; + SKColor bgColor; + + protected override async Task OnInitializedAsync() + { + await GetNewCaptchaAsync(); + await base.OnInitializedAsync(); + } - letters = []; + void Initialization() + { + if (string.IsNullOrEmpty(captchaWord)) return; - if (!string.IsNullOrEmpty(captchaWord)) - { - var chars = IsRtlCharSet ? captchaWord.Reverse() : captchaWord; + randomValue = new Random(); + bgColor = new SKColor((byte)randomValue.Next(70, 100), + (byte)randomValue.Next(60, 80), + (byte)randomValue.Next(50, 90) + ); - foreach (char c in chars) + letters = []; + + if (!string.IsNullOrEmpty(captchaWord)) + { + var chars = IsRtlCharSet ? captchaWord.Reverse() : captchaWord; + + foreach (char c in chars) + { + var letter = new Letter { - var letter = new Letter - { - Value = c.ToString(), - Angle = randomValue.Next(-15, 25), - ForeColor = new SKColor((byte)randomValue.Next(100, 256), - (byte)randomValue.Next(110, 256), - (byte)randomValue.Next(90, 256)), - FontFamily = FontFamilies[randomValue.Next(0, FontFamilies.Length)], - }; - - letters.Add(letter); - } + Value = c.ToString(), + Angle = randomValue.Next(-15, 25), + ForeColor = new SKColor((byte)randomValue.Next(100, 256), + (byte)randomValue.Next(110, 256), + (byte)randomValue.Next(90, 256)), + FontFamily = FontFamilies[randomValue.Next(0, FontFamilies.Length)], + }; + + letters.Add(letter); } } + } + + string DrawImage() + { + SKImageInfo imageInfo = new(Width, Height); + using var surface = SKSurface.Create(imageInfo); + var canvas = surface.Canvas; + canvas.Clear(bgColor); - string DrawImage() + using (SKPaint paint = new()) { - SKImageInfo imageInfo = new(Width, Height); - using var surface = SKSurface.Create(imageInfo); - var canvas = surface.Canvas; - canvas.Clear(bgColor); + //starting point(x axis) + float x = 25; - using (SKPaint paint = new()) + foreach (Letter l in letters) { - //starting point(x axis) - float x = 25; - - foreach (Letter l in letters) - { - paint.Color = l.ForeColor; - paint.Typeface = SKTypeface.FromFamilyName(l.FontFamily); + paint.Color = l.ForeColor; + paint.Typeface = SKTypeface.FromFamilyName(l.FontFamily); - paint.TextAlign = IsRtlCharSet ? SKTextAlign.Right : SKTextAlign.Left; - paint.TextSize = randomValue.Next(Height / 2, Height / 2 + Height / 4); - paint.FakeBoldText = true; - paint.IsAntialias = true; + paint.TextAlign = IsRtlCharSet ? SKTextAlign.Right : SKTextAlign.Left; + paint.TextSize = randomValue.Next(Height / 2, Height / 2 + Height / 4); + paint.FakeBoldText = true; + paint.IsAntialias = true; - SKRect rect = new(); - float width = paint.MeasureText(l.Value, ref rect); + SKRect rect = new(); + float width = paint.MeasureText(l.Value, ref rect); - float textWidth = width; - var y = Height - (rect.Height - 5); + float textWidth = width; + var y = Height - (rect.Height - 5); - canvas.Save(); + canvas.Save(); - canvas.RotateDegrees(l.Angle, x, y); - canvas.DrawText(l.Value, x, y, paint); + canvas.RotateDegrees(l.Angle, x, y); + canvas.DrawText(l.Value, x, y, paint); - canvas.Restore(); + canvas.Restore(); - x += textWidth + 10; - } - - canvas.DrawLine(0, randomValue.Next(0, Height), Width, randomValue.Next(0, Height), paint); - canvas.DrawLine(0, randomValue.Next(0, Height), Width, randomValue.Next(0, Height), paint); - paint.Style = SKPaintStyle.Stroke; - canvas.DrawOval(randomValue.Next(-Width, Width), randomValue.Next(-Height, Height), Width, Height, paint); + x += textWidth + 10; } - // save the file - MemoryStream memoryStream = new(); - using (var image = surface.Snapshot()) - using (var data = image.Encode(SKEncodedImageFormat.Png, 75)) - data.SaveTo(memoryStream); - string imageBase64Data2 = Convert.ToBase64String(memoryStream.ToArray()); - return string.Format("data:image/gif;base64,{0}", imageBase64Data2); + canvas.DrawLine(0, randomValue.Next(0, Height), Width, randomValue.Next(0, Height), paint); + canvas.DrawLine(0, randomValue.Next(0, Height), Width, randomValue.Next(0, Height), paint); + paint.Style = SKPaintStyle.Stroke; + canvas.DrawOval(randomValue.Next(-Width, Width), randomValue.Next(-Height, Height), Width, Height, paint); } - void AddImageToRenderTree(RenderTreeBuilder builder, string img) + // save the file + MemoryStream memoryStream = new(); + using (var image = surface.Snapshot()) + using (var data = image.Encode(SKEncodedImageFormat.Png, 75)) + data.SaveTo(memoryStream); + string imageBase64Data2 = Convert.ToBase64String(memoryStream.ToArray()); + return string.Format("data:image/gif;base64,{0}", imageBase64Data2); + } + + void AddImageToRenderTree(RenderTreeBuilder builder, string img) + { + var seq = 0; + builder.OpenElement(++seq, "div"); + builder.AddAttribute(++seq, "class", "divCaptcha"); { - var seq = 0; - builder.OpenElement(++seq, "div"); - builder.AddAttribute(++seq, "class", "divCaptcha"); - { - builder.OpenElement(++seq, "img"); - builder.AddAttribute(++seq, "src", img); - builder.CloseElement(); + builder.OpenElement(++seq, "img"); + builder.AddAttribute(++seq, "src", img); + builder.CloseElement(); - builder.OpenElement(++seq, "button"); - { - builder.AddAttribute(++seq, "class", "btn-refresh"); - builder.AddAttribute(++seq, "style", $"height :{Height}px"); - builder.AddAttribute(++seq, "type", "button"); - builder.AddAttribute(++seq, "onclick", EventCallback.Factory.Create(this, async () => await GetNewCaptchaAsync())); - } - builder.CloseElement(); + builder.OpenElement(++seq, "button"); + { + builder.AddAttribute(++seq, "class", "btn-refresh"); + builder.AddAttribute(++seq, "style", $"height :{Height}px"); + builder.AddAttribute(++seq, "type", "button"); + builder.AddAttribute(++seq, "onclick", EventCallback.Factory.Create(this, async () => await GetNewCaptchaAsync())); } builder.CloseElement(); } + builder.CloseElement(); + } - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - if (randomValue == null) return; - if (string.IsNullOrEmpty(captchaWord)) return; + protected override void BuildRenderTree(RenderTreeBuilder builder) + { + if (randomValue == null) return; + if (string.IsNullOrEmpty(captchaWord)) return; - AddImageToRenderTree(builder, DrawImage()); + AddImageToRenderTree(builder, DrawImage()); - base.BuildRenderTree(builder); - } + base.BuildRenderTree(builder); + } - /// - /// Draw a new captcha image - /// - public async Task GetNewCaptchaAsync() - { - captchaWord = GetCaptchaWord(CharCount); - Initialization(); - await CaptchaChanged.InvokeAsync(captchaWord); - StateHasChanged(); - } + /// + /// Draw a new captcha image + /// + public async Task GetNewCaptchaAsync() + { + captchaWord = GetCaptchaWord(CharCount); + Initialization(); + await CaptchaChanged.InvokeAsync(captchaWord); + StateHasChanged(); + } - /// - /// Checks if the given input text is squal to the image's text - /// - public bool IsValid(string input) - { - return CaseSesitiveComparison - ? string.Equals(captchaWord, input, StringComparison.Ordinal) - : string.Equals(captchaWord, input, StringComparison.OrdinalIgnoreCase); - } + /// + /// Checks if the given input text is squal to the image's text + /// + public bool IsValid(string input) + { + return CaseSesitiveComparison + ? string.Equals(captchaWord, input, StringComparison.Ordinal) + : string.Equals(captchaWord, input, StringComparison.OrdinalIgnoreCase); } } \ No newline at end of file diff --git a/04-Presentation/Jinget.Blazor/Components/DynamicComponent/JingetDynamicForm.razor b/04-Presentation/Jinget.Blazor/Components/DynamicComponent/JingetDynamicForm.razor index 7558016..8d66d02 100644 --- a/04-Presentation/Jinget.Blazor/Components/DynamicComponent/JingetDynamicForm.razor +++ b/04-Presentation/Jinget.Blazor/Components/DynamicComponent/JingetDynamicForm.razor @@ -8,94 +8,94 @@ @foreach (var p in Properties) - { - + { + - } + } @code { - [Parameter] public T? Model { get; set; } - [Parameter] public bool Rtl { get; set; } = true; - [Parameter] public EventCallback> OnModelChanged { get; set; } +[Parameter] public T? Model { get; set; } +[Parameter] public bool Rtl { get; set; } = true; +[Parameter] public EventCallback> OnModelChanged { get; set; } - public HashSet<(PropertyInfo Property, JingetFormElement? Attribute)> Properties { get; set; } = new(); +public HashSet<(PropertyInfo Property, JingetFormElement? Attribute)> Properties { get; set; } = new(); - protected override void OnInitialized() +protected override void OnInitialized() +{ + if (Model != null) { - if (Model != null) - { - IOrderedEnumerable props = Model.GetType().GetProperties() - .Where(x => x.IsDefined(typeof(JingetFormElement))) + IOrderedEnumerable props = Model.GetType().GetProperties() + .Where(x => x.IsDefined(typeof(JingetFormElement))) #pragma warning disable CS8602 // Dereference of a possibly null reference. - .OrderBy(x => x.GetCustomAttribute().Order); + .OrderBy(x => x.GetCustomAttribute().Order); #pragma warning restore CS8602 // Dereference of a possibly null reference. - foreach (var p in props) - { - Properties.Add(new( - p, - p.GetCustomAttribute())); - } + foreach (var p in props) + { + Properties.Add(new( + p, + p.GetCustomAttribute())); } } +} - void OnValueChanged(string prop, object? value) +void OnValueChanged(string prop, object? value) +{ + if (Model != null) { - if (Model != null) + var p = Model.GetType().GetProperty(prop); + var previousValue = p?.GetValue(Model); + object? convertedValue = null; + + try { - var p = Model.GetType().GetProperty(prop); - var previousValue = p?.GetValue(Model); - object? convertedValue = null; + Type t = Nullable.GetUnderlyingType(p.PropertyType) ?? p.PropertyType; + if (value is not IConvertible && t == typeof(string)) + { + value = value==null?null:value?.ToString(); + } - try + if (value is SelectedDateRangeModel dateRangeValue) { - Type t = Nullable.GetUnderlyingType(p.PropertyType) ?? p.PropertyType; - if (value is not IConvertible && t == typeof(string)) + if (t == typeof(DateRange)) { - value = value==null?null:value?.ToString(); + convertedValue = Convert.ChangeType(dateRangeValue.DateRange, t); } - - if (value is SelectedDateRangeModel dateRangeValue) + else + { + convertedValue = Convert.ChangeType(dateRangeValue, t); + } + } + else + { + if (value is IConvertible) { - if (t == typeof(DateRange)) - { - convertedValue = Convert.ChangeType(dateRangeValue.DateRange, t); - } - else - { - convertedValue = Convert.ChangeType(dateRangeValue, t); - } + convertedValue = (value == null) ? null : Convert.ChangeType(value, t); } else { - if (value is IConvertible) - { - convertedValue = (value == null) ? null : Convert.ChangeType(value, t); - } - else - { - convertedValue = (value == null) ? null : Convert.ChangeType(value.ToString(), t); - } + convertedValue = (value == null) ? null : Convert.ChangeType(value.ToString(), t); } - p?.SetValue(Model, convertedValue); - StateHasChanged(); } - catch { } - - Dictionary info = new Dictionary - { - {"Model",Model}, - {"PreviousValue",previousValue}, - {"CurrentValue",value}, - {"ConvertedValue",convertedValue}, - {"PropertyName",prop} - }; - OnModelChanged.InvokeAsync(info); + p?.SetValue(Model, convertedValue); + StateHasChanged(); } + catch { } + + Dictionary info = new Dictionary + { + {"Model",Model}, + {"PreviousValue",previousValue}, + {"CurrentValue",value}, + {"ConvertedValue",convertedValue}, + {"PropertyName",prop} + }; + OnModelChanged.InvokeAsync(info); } +} } \ No newline at end of file diff --git a/04-Presentation/Jinget.Blazor/Components/List/JingetList.razor b/04-Presentation/Jinget.Blazor/Components/List/JingetList.razor index 4a1cbc3..317e1e4 100644 --- a/04-Presentation/Jinget.Blazor/Components/List/JingetList.razor +++ b/04-Presentation/Jinget.Blazor/Components/List/JingetList.razor @@ -4,23 +4,23 @@ {
    @if (ShowTitle) - { -
  • + { +
  • @Title
  • - } + } @foreach (var item in Model) - { -
  • + { +
  • @item.Text
  • - } + }
} @code { - [Parameter] public IList? Model { get; set; } +[Parameter] public IList? Model { get; set; } - [Parameter] public string? Title { get; set; } - [Parameter] public bool ShowTitle { get; set; } = true; - [Parameter] public string HeaderCssClass { get; set; } = "list-group-item-primary"; +[Parameter] public string? Title { get; set; } +[Parameter] public bool ShowTitle { get; set; } = true; +[Parameter] public string HeaderCssClass { get; set; } = "list-group-item-primary"; } \ No newline at end of file diff --git a/04-Presentation/Jinget.Blazor/Components/List/ListItem.cs b/04-Presentation/Jinget.Blazor/Components/List/ListItem.cs index 96a3299..fe76ba8 100644 --- a/04-Presentation/Jinget.Blazor/Components/List/ListItem.cs +++ b/04-Presentation/Jinget.Blazor/Components/List/ListItem.cs @@ -1,7 +1,6 @@ -namespace Jinget.Blazor.Components.List -{ - public record ListItem( - string? Text, - string CssClass = "list-group-item-action") - { } -} +namespace Jinget.Blazor.Components.List; + +public record ListItem( + string? Text, + string CssClass = "list-group-item-action") +{ } diff --git a/04-Presentation/Jinget.Blazor/Components/Picker/CultureService/ArSACultureService.cs b/04-Presentation/Jinget.Blazor/Components/Picker/CultureService/ArSACultureService.cs index 31fdb6a..e554a86 100644 --- a/04-Presentation/Jinget.Blazor/Components/Picker/CultureService/ArSACultureService.cs +++ b/04-Presentation/Jinget.Blazor/Components/Picker/CultureService/ArSACultureService.cs @@ -1,36 +1,35 @@ -namespace Jinget.Blazor.Components.Picker.CultureService +namespace Jinget.Blazor.Components.Picker.CultureService; + +internal class ArSACultureService { - internal class ArSACultureService + internal static CultureInfo GetCulture() { - internal static CultureInfo GetCulture() - { - var culture = new CultureInfo("ar-SA"); - culture.NumberFormat.NumberDecimalSeparator = "/"; - culture.NumberFormat.DigitSubstitution = DigitShapes.NativeNational; - culture.NumberFormat.NumberNegativePattern = 0; - - DateTimeFormatInfo formatInfo = culture.DateTimeFormat; - formatInfo.AbbreviatedDayNames = DateTimeUtility.GetArabicDayAbbrNames(); - formatInfo.DayNames = DateTimeUtility.GetArabicDayNames(); + var culture = new CultureInfo("ar-SA"); + culture.NumberFormat.NumberDecimalSeparator = "/"; + culture.NumberFormat.DigitSubstitution = DigitShapes.NativeNational; + culture.NumberFormat.NumberNegativePattern = 0; - formatInfo.AbbreviatedMonthNames = - formatInfo.MonthNames = - formatInfo.MonthGenitiveNames = formatInfo.AbbreviatedMonthGenitiveNames = DateTimeUtility.GetArabicMonthNames(); - formatInfo.AMDesignator = "ق.ظ"; - formatInfo.PMDesignator = "ب.ظ"; - formatInfo.ShortDatePattern = "yyyy/MM/dd"; - formatInfo.LongDatePattern = "dddd, dd MMMM,yyyy"; - formatInfo.FirstDayOfWeek = DayOfWeek.Saturday; + DateTimeFormatInfo formatInfo = culture.DateTimeFormat; + formatInfo.AbbreviatedDayNames = DateTimeUtility.GetArabicDayAbbrNames(); + formatInfo.DayNames = DateTimeUtility.GetArabicDayNames(); - Calendar cal = new HijriCalendar(); + formatInfo.AbbreviatedMonthNames = + formatInfo.MonthNames = + formatInfo.MonthGenitiveNames = formatInfo.AbbreviatedMonthGenitiveNames = DateTimeUtility.GetArabicMonthNames(); + formatInfo.AMDesignator = "ق.ظ"; + formatInfo.PMDesignator = "ب.ظ"; + formatInfo.ShortDatePattern = "yyyy/MM/dd"; + formatInfo.LongDatePattern = "dddd, dd MMMM,yyyy"; + formatInfo.FirstDayOfWeek = DayOfWeek.Saturday; - FieldInfo fieldInfo = culture.GetType().GetField("calendar", BindingFlags.NonPublic | BindingFlags.Instance); - fieldInfo?.SetValue(culture, cal); - FieldInfo info = formatInfo.GetType().GetField("calendar", BindingFlags.NonPublic | BindingFlags.Instance); - info?.SetValue(formatInfo, cal); + Calendar cal = new HijriCalendar(); - return culture; - } + FieldInfo fieldInfo = culture.GetType().GetField("calendar", BindingFlags.NonPublic | BindingFlags.Instance); + fieldInfo?.SetValue(culture, cal); + FieldInfo info = formatInfo.GetType().GetField("calendar", BindingFlags.NonPublic | BindingFlags.Instance); + info?.SetValue(formatInfo, cal); + return culture; } + } diff --git a/04-Presentation/Jinget.Blazor/Components/Picker/CultureService/CalendarService.cs b/04-Presentation/Jinget.Blazor/Components/Picker/CultureService/CalendarService.cs index 89070d0..4f33c3d 100644 --- a/04-Presentation/Jinget.Blazor/Components/Picker/CultureService/CalendarService.cs +++ b/04-Presentation/Jinget.Blazor/Components/Picker/CultureService/CalendarService.cs @@ -1,16 +1,15 @@ -namespace Jinget.Blazor.Components.Picker.CultureService +namespace Jinget.Blazor.Components.Picker.CultureService; + +public class CalendarService { - public class CalendarService + public static CultureInfo GetCulture(string culture) { - public static CultureInfo GetCulture(string culture) + return culture.ToLowerInvariant() switch { - return culture.ToLowerInvariant() switch - { - "fa-ir" => FaIRCultureService.GetCulture(), - "ar-sa" => ArSACultureService.GetCulture(), - _ => CultureInfo.GetCultureInfo(culture), - }; - } - + "fa-ir" => FaIRCultureService.GetCulture(), + "ar-sa" => ArSACultureService.GetCulture(), + _ => CultureInfo.GetCultureInfo(culture), + }; } + } diff --git a/04-Presentation/Jinget.Blazor/Components/Picker/CultureService/FaIRCultureService.cs b/04-Presentation/Jinget.Blazor/Components/Picker/CultureService/FaIRCultureService.cs index 514e28b..46a1ea9 100644 --- a/04-Presentation/Jinget.Blazor/Components/Picker/CultureService/FaIRCultureService.cs +++ b/04-Presentation/Jinget.Blazor/Components/Picker/CultureService/FaIRCultureService.cs @@ -1,36 +1,35 @@ -namespace Jinget.Blazor.Components.Picker.CultureService +namespace Jinget.Blazor.Components.Picker.CultureService; + +internal class FaIRCultureService { - internal class FaIRCultureService + internal static CultureInfo GetCulture() { - internal static CultureInfo GetCulture() - { - var culture = new CultureInfo("fa-IR"); - culture.NumberFormat.NumberDecimalSeparator = "/"; - culture.NumberFormat.DigitSubstitution = DigitShapes.NativeNational; - culture.NumberFormat.NumberNegativePattern = 0; - - DateTimeFormatInfo formatInfo = culture.DateTimeFormat; - formatInfo.AbbreviatedDayNames = DateTimeUtility.GetJalaliDayAbbrNames(); - formatInfo.DayNames = DateTimeUtility.GetJalaliDayNames(); + var culture = new CultureInfo("fa-IR"); + culture.NumberFormat.NumberDecimalSeparator = "/"; + culture.NumberFormat.DigitSubstitution = DigitShapes.NativeNational; + culture.NumberFormat.NumberNegativePattern = 0; - formatInfo.AbbreviatedMonthNames = - formatInfo.MonthNames = - formatInfo.MonthGenitiveNames = formatInfo.AbbreviatedMonthGenitiveNames = DateTimeUtility.GetJalaliMonthNames(); - formatInfo.AMDesignator = "ق.ظ"; - formatInfo.PMDesignator = "ب.ظ"; - formatInfo.ShortDatePattern = "yyyy/MM/dd"; - formatInfo.LongDatePattern = "dddd, dd MMMM,yyyy"; - formatInfo.FirstDayOfWeek = DayOfWeek.Saturday; + DateTimeFormatInfo formatInfo = culture.DateTimeFormat; + formatInfo.AbbreviatedDayNames = DateTimeUtility.GetJalaliDayAbbrNames(); + formatInfo.DayNames = DateTimeUtility.GetJalaliDayNames(); - Calendar cal = new PersianCalendar(); + formatInfo.AbbreviatedMonthNames = + formatInfo.MonthNames = + formatInfo.MonthGenitiveNames = formatInfo.AbbreviatedMonthGenitiveNames = DateTimeUtility.GetJalaliMonthNames(); + formatInfo.AMDesignator = "ق.ظ"; + formatInfo.PMDesignator = "ب.ظ"; + formatInfo.ShortDatePattern = "yyyy/MM/dd"; + formatInfo.LongDatePattern = "dddd, dd MMMM,yyyy"; + formatInfo.FirstDayOfWeek = DayOfWeek.Saturday; - FieldInfo fieldInfo = culture.GetType().GetField("calendar", BindingFlags.NonPublic | BindingFlags.Instance); - fieldInfo?.SetValue(culture, cal); - FieldInfo info = formatInfo.GetType().GetField("calendar", BindingFlags.NonPublic | BindingFlags.Instance); - info?.SetValue(formatInfo, cal); + Calendar cal = new PersianCalendar(); - return culture; - } + FieldInfo fieldInfo = culture.GetType().GetField("calendar", BindingFlags.NonPublic | BindingFlags.Instance); + fieldInfo?.SetValue(culture, cal); + FieldInfo info = formatInfo.GetType().GetField("calendar", BindingFlags.NonPublic | BindingFlags.Instance); + info?.SetValue(formatInfo, cal); + return culture; } + } diff --git a/04-Presentation/Jinget.Blazor/Components/Picker/JingetDatePicker.razor b/04-Presentation/Jinget.Blazor/Components/Picker/JingetDatePicker.razor index e5f9bd9..ac20940 100644 --- a/04-Presentation/Jinget.Blazor/Components/Picker/JingetDatePicker.razor +++ b/04-Presentation/Jinget.Blazor/Components/Picker/JingetDatePicker.razor @@ -28,50 +28,50 @@ @code { - MudDatePicker? _datePicker; - - DateTime? _previousValue; - DateTime? _currentValue; +MudDatePicker? _datePicker; - [Parameter] - public DateTime? Value +DateTime? _previousValue; +DateTime? _currentValue; + +[Parameter] +public DateTime? Value +{ + get => _currentValue; + set { - get => _currentValue; - set - { - _previousValue = Value; - _currentValue = value; - } + _previousValue = Value; + _currentValue = value; } - [Parameter] public override string Label { get; set; } = "تاریخ"; - [Parameter] public EventCallback DateChanged { get; set; } +} +[Parameter] public override string Label { get; set; } = "تاریخ"; +[Parameter] public EventCallback DateChanged { get; set; } - protected override async Task OnAfterRenderAsync(bool firstRender) - { - if (EnglishNumber) - await JS.InvokeVoidAsync("toEnglishNumber", id); +protected override async Task OnAfterRenderAsync(bool firstRender) +{ + if (EnglishNumber) + await JS.InvokeVoidAsync("toEnglishNumber", id); - if (firstRender) - { - _datePicker.GoToDate(); - } - } - - async Task DateChangedAsync(DateTime? e) + if (firstRender) { - if (e == _previousValue || e == _currentValue) - return; - if (e != null && e.HasValue) - { - await _datePicker.GoToDate(e.Value); - } - await DateChanged.InvokeAsync(e).ConfigureAwait(false); + _datePicker.GoToDate(); } +} - async Task OnOpen() +async Task DateChangedAsync(DateTime? e) +{ + if (e == _previousValue || e == _currentValue) + return; + if (e != null && e.HasValue) { - await JS.InvokeVoidAsync("refreshDatePicker"); - await JS.InvokeVoidAsync("gotoDate", id); + await _datePicker.GoToDate(e.Value); } + await DateChanged.InvokeAsync(e).ConfigureAwait(false); +} + +async Task OnOpen() +{ + await JS.InvokeVoidAsync("refreshDatePicker"); + await JS.InvokeVoidAsync("gotoDate", id); +} } \ No newline at end of file diff --git a/04-Presentation/Jinget.Blazor/Components/Picker/JingetDatePickerBase.cs b/04-Presentation/Jinget.Blazor/Components/Picker/JingetDatePickerBase.cs index 84b6a50..e9d8dd0 100644 --- a/04-Presentation/Jinget.Blazor/Components/Picker/JingetDatePickerBase.cs +++ b/04-Presentation/Jinget.Blazor/Components/Picker/JingetDatePickerBase.cs @@ -1,30 +1,29 @@ -namespace Jinget.Blazor.Components.Picker +namespace Jinget.Blazor.Components.Picker; + +public abstract class JingetDatePickerBase : ComponentBase { - public abstract class JingetDatePickerBase : ComponentBase - { - protected string id = Guid.NewGuid().ToString("N"); + protected string id = Guid.NewGuid().ToString("N"); - public string DateFormat { get; set; } = "yyyy/MM/dd"; + public string DateFormat { get; set; } = "yyyy/MM/dd"; - [Parameter] public string Culture { get; set; } = "fa-IR"; - [Parameter] public bool Disabled { get; set; } - [Parameter] public bool ReadOnly { get; set; } - [Parameter] public bool Editable { get; set; } = true; - [Parameter] public bool Clearable { get; set; } = true; - [Parameter] public DateTime? MinDate { get; set; } - [Parameter] public DateTime? MaxDate { get; set; } - [Parameter] public bool Required { get; set; } = false; - [Parameter] public string RequiredError { get; set; } = "الزامی"; - [Parameter] public bool EnglishNumber { get; set; } - [Parameter] public abstract string Label { get; set; } - [Parameter] public Func DisabledDateFunc { get; set; } - [Parameter] public Func CustomDateStyleFunc { get; set; } = (DateTime dt) => dt.DayOfWeek == DayOfWeek.Friday ? "red-text text-accent-4" : ""; + [Parameter] public string Culture { get; set; } = "fa-IR"; + [Parameter] public bool Disabled { get; set; } + [Parameter] public bool ReadOnly { get; set; } + [Parameter] public bool Editable { get; set; } = true; + [Parameter] public bool Clearable { get; set; } = true; + [Parameter] public DateTime? MinDate { get; set; } + [Parameter] public DateTime? MaxDate { get; set; } + [Parameter] public bool Required { get; set; } = false; + [Parameter] public string RequiredError { get; set; } = "الزامی"; + [Parameter] public bool EnglishNumber { get; set; } + [Parameter] public abstract string Label { get; set; } + [Parameter] public Func DisabledDateFunc { get; set; } + [Parameter] public Func CustomDateStyleFunc { get; set; } = (DateTime dt) => dt.DayOfWeek == DayOfWeek.Friday ? "red-text text-accent-4" : ""; - protected override async Task OnInitializedAsync() - { - if (Culture.ToLower() == "fa-ir" || Culture.ToLower() == "ar-sa") - Editable = false; - await base.OnInitializedAsync(); - } + protected override async Task OnInitializedAsync() + { + if (Culture.ToLower() == "fa-ir" || Culture.ToLower() == "ar-sa") + Editable = false; + await base.OnInitializedAsync(); } } diff --git a/04-Presentation/Jinget.Blazor/Components/Picker/JingetDateRangePicker.razor b/04-Presentation/Jinget.Blazor/Components/Picker/JingetDateRangePicker.razor index 571ae53..3e1618d 100644 --- a/04-Presentation/Jinget.Blazor/Components/Picker/JingetDateRangePicker.razor +++ b/04-Presentation/Jinget.Blazor/Components/Picker/JingetDateRangePicker.razor @@ -25,47 +25,47 @@ DateRangeChanged=@DateRangeChangedAsync PickerOpened=@OnOpen /> @code { - MudDateRangePicker _dateRangePicker; +MudDateRangePicker _dateRangePicker; - DateRange? _previousValue; - DateRange? _currentValue; +DateRange? _previousValue; +DateRange? _currentValue; - [Parameter] - public DateRange? Value +[Parameter] +public DateRange? Value +{ + get => _currentValue; + set { - get => _currentValue; - set - { - _previousValue = Value; - _currentValue = value; - } + _previousValue = Value; + _currentValue = value; } - [Parameter] public override string Label { get; set; } = "بازه تاریخی"; +} +[Parameter] public override string Label { get; set; } = "بازه تاریخی"; - [Parameter] public EventCallback DateRangeChanged { get; set; } +[Parameter] public EventCallback DateRangeChanged { get; set; } - protected override async Task OnAfterRenderAsync(bool firstRender) - { - if (EnglishNumber) - await JS.InvokeVoidAsync("toEnglishNumber", id); - } +protected override async Task OnAfterRenderAsync(bool firstRender) +{ + if (EnglishNumber) + await JS.InvokeVoidAsync("toEnglishNumber", id); +} - async Task DateRangeChangedAsync(DateRange e) - { - if (e == _previousValue || e == _currentValue) - return; - var dateRange = new DateRange(e.Start, e.End); - await DateRangeChanged.InvokeAsync(new SelectedDateRangeModel - { - DateRange = dateRange, - StartDateJalali = e.Start.HasValue ? Jinget.Core.Utilities.DateTimeUtility.ToSolarDate(e.Start.Value) : null, - EndDateJalali = e.End.HasValue ? Jinget.Core.Utilities.DateTimeUtility.ToSolarDate(e.End.Value) : null - } - ); - } +async Task DateRangeChangedAsync(DateRange e) +{ + if (e == _previousValue || e == _currentValue) + return; + var dateRange = new DateRange(e.Start, e.End); + await DateRangeChanged.InvokeAsync(new SelectedDateRangeModel + { + DateRange = dateRange, + StartDateJalali = e.Start.HasValue ? Jinget.Core.Utilities.DateTimeUtility.ToSolarDate(e.Start.Value) : null, + EndDateJalali = e.End.HasValue ? Jinget.Core.Utilities.DateTimeUtility.ToSolarDate(e.End.Value) : null + } + ); +} - async Task OnOpen() - { - await JS.InvokeVoidAsync("gotoDate", id); - } +async Task OnOpen() +{ + await JS.InvokeVoidAsync("gotoDate", id); +} } \ No newline at end of file diff --git a/04-Presentation/Jinget.Blazor/Components/Picker/SelectedDateRangeModel.cs b/04-Presentation/Jinget.Blazor/Components/Picker/SelectedDateRangeModel.cs index f10fff1..bbaa152 100644 --- a/04-Presentation/Jinget.Blazor/Components/Picker/SelectedDateRangeModel.cs +++ b/04-Presentation/Jinget.Blazor/Components/Picker/SelectedDateRangeModel.cs @@ -1,38 +1,37 @@ using MudBlazor; -namespace Jinget.Blazor.Components.Picker +namespace Jinget.Blazor.Components.Picker; + +public class SelectedDateRangeModel { - public class SelectedDateRangeModel - { - public DateRange DateRange { get; set; } - public string? StartDateJalali { get; set; } - public string? EndDateJalali { get; set; } + public DateRange DateRange { get; set; } + public string? StartDateJalali { get; set; } + public string? EndDateJalali { get; set; } - /// - /// set date range by gregorian start and end date - /// - public void Set(DateTime start, DateTime end) - { - if (end < start) - throw new Exception($"{nameof(end)} should be greater than {nameof(start)}"); - DateRange = new DateRange(start, end); - StartDateJalali = DateTimeUtility.ToSolarDate(start); - EndDateJalali = DateTimeUtility.ToSolarDate(end); - } + /// + /// set date range by gregorian start and end date + /// + public void Set(DateTime start, DateTime end) + { + if (end < start) + throw new Exception($"{nameof(end)} should be greater than {nameof(start)}"); + DateRange = new DateRange(start, end); + StartDateJalali = DateTimeUtility.ToSolarDate(start); + EndDateJalali = DateTimeUtility.ToSolarDate(end); + } - /// - /// set date range by solar start and end date - /// - public void Set(string start, string end) - { - var gregorianStart = DateTimeUtility.ToGregorianDate(start); - var gregorianEnd = DateTimeUtility.ToGregorianDate(end); - if (gregorianEnd < gregorianStart) - throw new Exception($"{nameof(end)} should be greater than {nameof(start)}"); + /// + /// set date range by solar start and end date + /// + public void Set(string start, string end) + { + var gregorianStart = DateTimeUtility.ToGregorianDate(start); + var gregorianEnd = DateTimeUtility.ToGregorianDate(end); + if (gregorianEnd < gregorianStart) + throw new Exception($"{nameof(end)} should be greater than {nameof(start)}"); - DateRange = new DateRange(gregorianStart, gregorianEnd); - StartDateJalali = start; - EndDateJalali = end; - } + DateRange = new DateRange(gregorianStart, gregorianEnd); + StartDateJalali = start; + EndDateJalali = end; } } diff --git a/04-Presentation/Jinget.Blazor/Components/Popup/JingetMessageBox.razor b/04-Presentation/Jinget.Blazor/Components/Popup/JingetMessageBox.razor index 5c6d3d7..d8c27c9 100644 --- a/04-Presentation/Jinget.Blazor/Components/Popup/JingetMessageBox.razor +++ b/04-Presentation/Jinget.Blazor/Components/Popup/JingetMessageBox.razor @@ -14,15 +14,15 @@ OnClose="OnCloseCallback"> @if (IsFancy) - { - + { + @((MarkupString)Content) - } - else - { - @Content - } + } + else + { + @Content + } @code { - JingetModal modal { get; set; } = new JingetModal(); - JsonViewer JsonViewer { get; set; } +JingetModal modal { get; set; } = new JingetModal(); +JsonViewer JsonViewer { get; set; } - string? Title { get; set; } - string Content { get; set; } - IList verboseItems { get; set; } - bool IsFancy { get; set; } - Severity Theme { get; set; } +string? Title { get; set; } +string Content { get; set; } +IList verboseItems { get; set; } +bool IsFancy { get; set; } +Severity Theme { get; set; } - [Parameter] public Func>? ShowVerboseFuncAsync { get; set; } +[Parameter] public Func>? ShowVerboseFuncAsync { get; set; } - /// message box title - /// message box body content in string - /// message box detailed description text in body - // /// which users are eligible to view the - /// if is a json string, then defines the key in which its content should be parsed as - /// - /// - public async Task OpenAsync( - string title = "", - string content = "", - string verboseContent = "", - string verboseKey = "error", - Severity theme = Severity.Warning, - bool isFancy = true) +/// message box title +/// message box body content in string +/// message box detailed description text in body +// /// which users are eligible to view the +/// if is a json string, then defines the key in which its content should be parsed as +/// +/// +public async Task OpenAsync( + string title = "", + string content = "", + string verboseContent = "", + string verboseKey = "error", + Severity theme = Severity.Warning, + bool isFancy = true) +{ + this.Title = title; + this.Content = content; + if (verboseItems != null) + verboseItems.Clear(); + if (!string.IsNullOrWhiteSpace(verboseContent)) { - this.Title = title; - this.Content = content; - if (verboseItems != null) - verboseItems.Clear(); - if (!string.IsNullOrWhiteSpace(verboseContent)) - { - verboseItems = new List(); + verboseItems = new List(); - var shouldShowVerbose=ShowVerboseFuncAsync==null?false: (await ShowVerboseFuncAsync.Invoke()); + var shouldShowVerbose=ShowVerboseFuncAsync==null?false: (await ShowVerboseFuncAsync.Invoke()); - if(shouldShowVerbose) + if(shouldShowVerbose) + { + if ( + Jinget.Core.Utilities.Json.JsonUtility.IsValid(verboseContent) && + JObject.Parse(verboseContent).ContainsKey(verboseKey)) + { + verboseItems.Add(new ListItem( + JObject.Parse(verboseContent)[verboseKey].ToString(), + "list-group-item list-group-item-danger" + )); + } + else + if (Jinget.Core.Utilities.Json.JsonUtility.IsValid(verboseContent)) { - if ( - Jinget.Core.Utilities.Json.JsonUtility.IsValid(verboseContent) && - JObject.Parse(verboseContent).ContainsKey(verboseKey)) - { - verboseItems.Add(new ListItem( - JObject.Parse(verboseContent)[verboseKey].ToString(), - "list-group-item list-group-item-danger" - )); - } - else - if (Jinget.Core.Utilities.Json.JsonUtility.IsValid(verboseContent)) - { - await JsonViewer.Render(verboseContent); - } - else - { - verboseItems.Add(new ListItem(verboseContent, "list-group-item list-group-item-danger")); - } + await JsonViewer.Render(verboseContent); + } + else + { + verboseItems.Add(new ListItem(verboseContent, "list-group-item list-group-item-danger")); } } - - Theme = theme; - IsFancy = isFancy; - await modal.OpenAsync(); - await InvokeAsync(StateHasChanged); } - public async Task CloseAsync() - { - await modal.CloseAsync(); - await InvokeAsync(StateHasChanged); - } + Theme = theme; + IsFancy = isFancy; + await modal.OpenAsync(); + await InvokeAsync(StateHasChanged); +} - public async Task ShowErrorAsync( - string title = "", - string content = "", - string verboseContent = "", - bool isFancy = true, - bool rtl=true){ - Rtl = rtl; - await OpenAsync(title,content,verboseContent,theme:Severity.Error, isFancy:isFancy); - } +public async Task CloseAsync() +{ + await modal.CloseAsync(); + await InvokeAsync(StateHasChanged); +} - public async Task ShowWarningAsync( - string title = "", - string content = "", - string verboseContent = "", - bool isFancy = true, - bool rtl=true){ - Rtl = rtl; - await OpenAsync(title,content,verboseContent,theme:Severity.Warning, isFancy:isFancy); - } +public async Task ShowErrorAsync( + string title = "", + string content = "", + string verboseContent = "", + bool isFancy = true, + bool rtl=true){ + Rtl = rtl; + await OpenAsync(title,content,verboseContent,theme:Severity.Error, isFancy:isFancy); + } - public async Task ShowInfoAsync( - string title = "", - string content = "", - string verboseContent = "", - bool isFancy = true, - bool rtl=true){ - Rtl = rtl; - await OpenAsync(title,content,verboseContent,theme:Severity.Info, isFancy:isFancy); - } - async Task OnOpenCallback() => await OnOpen.InvokeAsync(); +public async Task ShowWarningAsync( + string title = "", + string content = "", + string verboseContent = "", + bool isFancy = true, + bool rtl=true){ + Rtl = rtl; + await OpenAsync(title,content,verboseContent,theme:Severity.Warning, isFancy:isFancy); + } + +public async Task ShowInfoAsync( + string title = "", + string content = "", + string verboseContent = "", + bool isFancy = true, + bool rtl=true){ + Rtl = rtl; + await OpenAsync(title,content,verboseContent,theme:Severity.Info, isFancy:isFancy); + } +async Task OnOpenCallback() => await OnOpen.InvokeAsync(); - async Task OnCloseCallback() => await OnClose.InvokeAsync(); +async Task OnCloseCallback() => await OnClose.InvokeAsync(); } \ No newline at end of file diff --git a/04-Presentation/Jinget.Blazor/Components/Popup/JingetModal.razor b/04-Presentation/Jinget.Blazor/Components/Popup/JingetModal.razor index 038ab4f..bcd2a69 100644 --- a/04-Presentation/Jinget.Blazor/Components/Popup/JingetModal.razor +++ b/04-Presentation/Jinget.Blazor/Components/Popup/JingetModal.razor @@ -7,28 +7,28 @@ @code { - IList Model = new List - { - new ListItem("Item 1","list-group-item-info"), - new ListItem("Item 2","list-group-item-secondary"), - new ListItem("Item 3"), - }; +IList Model = new List +{ + new ListItem("Item 1","list-group-item-info"), + new ListItem("Item 2","list-group-item-secondary"), + new ListItem("Item 3"), +}; } \ No newline at end of file diff --git a/Tests/Jinget.Blazor.Test/Components/Pages/Picker/DatePicker.razor b/Tests/Jinget.Blazor.Test/Components/Pages/Picker/DatePicker.razor index 5640c6d..bae500e 100644 --- a/Tests/Jinget.Blazor.Test/Components/Pages/Picker/DatePicker.razor +++ b/Tests/Jinget.Blazor.Test/Components/Pages/Picker/DatePicker.razor @@ -16,11 +16,11 @@ @if (selectedDate_1.HasValue) - { -
+{ +

Selected Date: @selectedDate_1.Value.ToString("yyyy/MM/dd")/@DateTimeUtility.ToSolarDate(selectedDate_1.Value)

- } +}
Set Selected Date Programmatically @@ -32,13 +32,13 @@
@if (selectedDate_2.HasValue) - { -
+{ +

Selected Date: @selectedDate_2.Value.ToString("yyyy/MM/dd") /@DateTimeUtility.ToSolarDate(selectedDate_2.Value)

- } +}
en-US culture with custom label @@ -52,11 +52,11 @@
@if (selectedDate_3.HasValue) - { -
+{ +

Selected Date: @selectedDate_3.Value.ToString("yyyy/MM/dd")/@DateTimeUtility.ToSolarDate(selectedDate_3.Value)

- } +}
Arabic Date Picker(Saudi Arabia) @@ -68,15 +68,15 @@
@if (selectedDate_4.HasValue) - { -
+{ +

Selected Date: @selectedDate_4.Value.ToString("yyyy/MM/dd")/ @DateTimeUtility.ToSolarDate(selectedDate_4.Value) / @selectedDate_4.Value.ToString("yyyy-MM-dd", new CultureInfo("ar-SA"))

- } +}
Chinese Date Picker @@ -89,14 +89,14 @@
@if (selectedDate_5.HasValue) - { -
+{ +

Selected Date: @selectedDate_5.Value.ToString("yyyy/MM/dd") / @DateTimeUtility.ToSolarDate(selectedDate_5.Value)

- } +}
Min/Max Selectabel date @@ -109,14 +109,14 @@
@if (selectedDate_6.HasValue) - { -
+{ +

Selected Date: @selectedDate_6.Value.ToString("yyyy/MM/dd") / @DateTimeUtility.ToSolarDate(selectedDate_6.Value)

- } +}
Disable 15th day of each month @@ -131,37 +131,37 @@
@if (selectedDate_7.HasValue) - { -
+{ +

Selected Date: @selectedDate_7.Value.ToString("yyyy/MM/dd") / @DateTimeUtility.ToSolarDate(selectedDate_7.Value)

- } +}
@code { - DateTime? selectedDate_1; - DateTime? selectedDate_2; - DateTime? selectedDate_3; - DateTime? selectedDate_4; - DateTime? selectedDate_5; - DateTime? selectedDate_6; - DateTime? selectedDate_7; +DateTime? selectedDate_1; +DateTime? selectedDate_2; +DateTime? selectedDate_3; +DateTime? selectedDate_4; +DateTime? selectedDate_5; +DateTime? selectedDate_6; +DateTime? selectedDate_7; - void OnDateChanged_1(DateTime? selectedDate) => selectedDate_1 = selectedDate; - void OnDateChanged_2(DateTime? selectedDate) => selectedDate_2 = selectedDate; - void OnDateChanged_3(DateTime? selectedDate) => selectedDate_3 = selectedDate; - void OnDateChanged_4(DateTime? selectedDate) => selectedDate_4 = selectedDate; - void OnDateChanged_5(DateTime? selectedDate) => selectedDate_5 = selectedDate; - void OnDateChanged_6(DateTime? selectedDate) => selectedDate_6 = selectedDate; - void OnDateChanged_7(DateTime? selectedDate) => selectedDate_7 = selectedDate; +void OnDateChanged_1(DateTime? selectedDate) => selectedDate_1 = selectedDate; +void OnDateChanged_2(DateTime? selectedDate) => selectedDate_2 = selectedDate; +void OnDateChanged_3(DateTime? selectedDate) => selectedDate_3 = selectedDate; +void OnDateChanged_4(DateTime? selectedDate) => selectedDate_4 = selectedDate; +void OnDateChanged_5(DateTime? selectedDate) => selectedDate_5 = selectedDate; +void OnDateChanged_6(DateTime? selectedDate) => selectedDate_6 = selectedDate; +void OnDateChanged_7(DateTime? selectedDate) => selectedDate_7 = selectedDate; - void SetJalaliDate() - { - Random rnd = new Random(); - var selectedDate = $"{rnd.Next(1398, 1402)}/{rnd.Next(1, 12)}/{rnd.Next(1, 9)}"; - selectedDate_2 = Jinget.Core.Utilities.DateTimeUtility.ToGregorianDate(selectedDate); - } +void SetJalaliDate() +{ + Random rnd = new Random(); + var selectedDate = $"{rnd.Next(1398, 1402)}/{rnd.Next(1, 12)}/{rnd.Next(1, 9)}"; + selectedDate_2 = Jinget.Core.Utilities.DateTimeUtility.ToGregorianDate(selectedDate); +} } \ No newline at end of file diff --git a/Tests/Jinget.Blazor.Test/Components/Pages/Picker/DateRangePicker.razor b/Tests/Jinget.Blazor.Test/Components/Pages/Picker/DateRangePicker.razor index 0260de9..8a24f4a 100644 --- a/Tests/Jinget.Blazor.Test/Components/Pages/Picker/DateRangePicker.razor +++ b/Tests/Jinget.Blazor.Test/Components/Pages/Picker/DateRangePicker.razor @@ -16,14 +16,14 @@ @if (selectedDateRange_1 != null) - { -
+{ +

From: @selectedDateRange_1.DateRange?.Start?.ToString("yyyy/MM/dd") To: @selectedDateRange_1.DateRange?.End?.ToString("yyyy/MM/dd") / From: @selectedDateRange_1.StartDateJalali To: @selectedDateRange_1.EndDateJalali

- } +}
@@ -37,14 +37,14 @@
@if (selectedDateRange_2 != null) - { -
+{ +

From: @selectedDateRange_2.DateRange?.Start?.ToString("yyyy/MM/dd") To: @selectedDateRange_2.DateRange?.End?.ToString("yyyy/MM/dd") / From: @selectedDateRange_2.StartDateJalali To: @selectedDateRange_2.EndDateJalali

- } +}
en-US culture with custom label @@ -58,14 +58,14 @@
@if (selectedDateRange_3 != null) - { -
+{ +

From: @selectedDateRange_3.DateRange?.Start?.ToString("yyyy/MM/dd") To: @selectedDateRange_3.DateRange?.End?.ToString("yyyy/MM/dd") / From: @selectedDateRange_3.StartDateJalali To: @selectedDateRange_3.EndDateJalali

- } +}
Arabic Date Picker(Saudi Arabia) @@ -77,14 +77,14 @@
@if (selectedDateRange_4 != null) - { -
+{ +

From: @selectedDateRange_4.DateRange?.Start?.ToString("yyyy/MM/dd") To: @selectedDateRange_4.DateRange?.End?.ToString("yyyy/MM/dd") / From: @selectedDateRange_4.StartDateJalali To: @selectedDateRange_4.EndDateJalali

- } +}
Chinese Date Picker @@ -97,14 +97,14 @@
@if (selectedDateRange_5 != null) - { -
+{ +

From: @selectedDateRange_5.DateRange?.Start?.ToString("yyyy/MM/dd") To: @selectedDateRange_5.DateRange?.End?.ToString("yyyy/MM/dd") / From: @selectedDateRange_5.StartDateJalali To: @selectedDateRange_5.EndDateJalali

- } +}
Min/Max Selectabel date @@ -117,14 +117,14 @@
@if (selectedDateRange_6 != null) - { -
+{ +

From: @selectedDateRange_6.DateRange?.Start?.ToString("yyyy/MM/dd") To: @selectedDateRange_6.DateRange?.End?.ToString("yyyy/MM/dd") / From: @selectedDateRange_6.StartDateJalali To: @selectedDateRange_6.EndDateJalali

- } +}
Disable 15th day of each month @@ -139,47 +139,47 @@
@if (selectedDateRange_7 != null) - { -
+{ +

From: @selectedDateRange_7.DateRange?.Start?.ToString("yyyy/MM/dd") To: @selectedDateRange_7.DateRange?.End?.ToString("yyyy/MM/dd") / From: @selectedDateRange_7.StartDateJalali To: @selectedDateRange_7.EndDateJalali

- } +}
@code { - SelectedDateRangeModel selectedDateRange_1 = new(); - SelectedDateRangeModel selectedDateRange_2 = new(); - SelectedDateRangeModel selectedDateRange_3 = new(); - SelectedDateRangeModel selectedDateRange_4 = new(); - SelectedDateRangeModel selectedDateRange_5 = new(); - SelectedDateRangeModel selectedDateRange_6 = new(); - SelectedDateRangeModel selectedDateRange_7 = new(); +SelectedDateRangeModel selectedDateRange_1 = new(); +SelectedDateRangeModel selectedDateRange_2 = new(); +SelectedDateRangeModel selectedDateRange_3 = new(); +SelectedDateRangeModel selectedDateRange_4 = new(); +SelectedDateRangeModel selectedDateRange_5 = new(); +SelectedDateRangeModel selectedDateRange_6 = new(); +SelectedDateRangeModel selectedDateRange_7 = new(); - void OnDateRangeChanged_1(SelectedDateRangeModel selectedDateRange) => selectedDateRange_1 = selectedDateRange; - void OnDateRangeChanged_2(SelectedDateRangeModel selectedDateRange) => selectedDateRange_2 = selectedDateRange; - void OnDateRangeChanged_3(SelectedDateRangeModel selectedDateRange) => selectedDateRange_3 = selectedDateRange; - void OnDateRangeChanged_4(SelectedDateRangeModel selectedDateRange) => selectedDateRange_4 = selectedDateRange; - void OnDateRangeChanged_5(SelectedDateRangeModel selectedDateRange) => selectedDateRange_5 = selectedDateRange; - void OnDateRangeChanged_6(SelectedDateRangeModel selectedDateRange) => selectedDateRange_6 = selectedDateRange; - void OnDateRangeChanged_7(SelectedDateRangeModel selectedDateRange) => selectedDateRange_7 = selectedDateRange; +void OnDateRangeChanged_1(SelectedDateRangeModel selectedDateRange) => selectedDateRange_1 = selectedDateRange; +void OnDateRangeChanged_2(SelectedDateRangeModel selectedDateRange) => selectedDateRange_2 = selectedDateRange; +void OnDateRangeChanged_3(SelectedDateRangeModel selectedDateRange) => selectedDateRange_3 = selectedDateRange; +void OnDateRangeChanged_4(SelectedDateRangeModel selectedDateRange) => selectedDateRange_4 = selectedDateRange; +void OnDateRangeChanged_5(SelectedDateRangeModel selectedDateRange) => selectedDateRange_5 = selectedDateRange; +void OnDateRangeChanged_6(SelectedDateRangeModel selectedDateRange) => selectedDateRange_6 = selectedDateRange; +void OnDateRangeChanged_7(SelectedDateRangeModel selectedDateRange) => selectedDateRange_7 = selectedDateRange; - void SetJalaliDateRange() - { - Random rnd = new Random(); - var year = rnd.Next(1398, 1402); - var month = rnd.Next(1, 12); - var dayFrom = rnd.Next(1, 29); - var dayTo = rnd.Next(dayFrom, 29); - var selectedDateFrom = $"{year}/{month}/{dayFrom}"; - var selectedDateTo = $"{year}/{month + 1}/{dayTo}"; - selectedDateRange_2 = new SelectedDateRangeModel - { - DateRange = new DateRange( - Jinget.Core.Utilities.DateTimeUtility.ToGregorianDate(selectedDateFrom), - Jinget.Core.Utilities.DateTimeUtility.ToGregorianDate(selectedDateTo)) - }; - } +void SetJalaliDateRange() +{ + Random rnd = new Random(); + var year = rnd.Next(1398, 1402); + var month = rnd.Next(1, 12); + var dayFrom = rnd.Next(1, 29); + var dayTo = rnd.Next(dayFrom, 29); + var selectedDateFrom = $"{year}/{month}/{dayFrom}"; + var selectedDateTo = $"{year}/{month + 1}/{dayTo}"; + selectedDateRange_2 = new SelectedDateRangeModel + { + DateRange = new DateRange( + Jinget.Core.Utilities.DateTimeUtility.ToGregorianDate(selectedDateFrom), + Jinget.Core.Utilities.DateTimeUtility.ToGregorianDate(selectedDateTo)) + }; +} } \ No newline at end of file diff --git a/Tests/Jinget.Blazor.Test/Components/Pages/Popup/MessageBox.razor b/Tests/Jinget.Blazor.Test/Components/Pages/Popup/MessageBox.razor index c7280ce..4c31809 100644 --- a/Tests/Jinget.Blazor.Test/Components/Pages/Popup/MessageBox.razor +++ b/Tests/Jinget.Blazor.Test/Components/Pages/Popup/MessageBox.razor @@ -22,32 +22,32 @@ @code { - JingetMessageBox? messageBox { get; set; } - - bool showVerbose { get; set; } - - void Opened() => messageBox.CloseButtonText = messageBox.Rtl ? "بستن" : "Close"; - - async Task ShowMBox1() - { - messageBox.ShowVerboseFuncAsync = ShowVerboseCondition; - await messageBox?.ShowErrorAsync( - title: "Sample message box", - content: "This is sample message box", - verboseContent: "This is vebose content", - rtl: false); - } - - async Task ShowMBox2() - { - messageBox.ShowVerboseFuncAsync = ShowVerboseCondition; - await messageBox?.ShowErrorAsync( - title: "پیغام تستی", - content: "این یک محتوای تستی است", - verboseContent: "توضیحات بیشتر تستی"); - } - - async Task ShowVerboseCondition() => await Task.FromResult(showVerbose); - - void OnChecked() => showVerbose = !showVerbose; +JingetMessageBox? messageBox { get; set; } + +bool showVerbose { get; set; } + +void Opened() => messageBox.CloseButtonText = messageBox.Rtl ? "بستن" : "Close"; + +async Task ShowMBox1() +{ + messageBox.ShowVerboseFuncAsync = ShowVerboseCondition; + await messageBox?.ShowErrorAsync( + title: "Sample message box", + content: "This is sample message box", + verboseContent: "This is vebose content", + rtl: false); +} + +async Task ShowMBox2() +{ + messageBox.ShowVerboseFuncAsync = ShowVerboseCondition; + await messageBox?.ShowErrorAsync( + title: "پیغام تستی", + content: "این یک محتوای تستی است", + verboseContent: "توضیحات بیشتر تستی"); +} + +async Task ShowVerboseCondition() => await Task.FromResult(showVerbose); + +void OnChecked() => showVerbose = !showVerbose; } \ No newline at end of file diff --git a/Tests/Jinget.Blazor.Test/Components/Pages/Popup/Modal.razor b/Tests/Jinget.Blazor.Test/Components/Pages/Popup/Modal.razor index 40f2cd2..1a4f5b0 100644 --- a/Tests/Jinget.Blazor.Test/Components/Pages/Popup/Modal.razor +++ b/Tests/Jinget.Blazor.Test/Components/Pages/Popup/Modal.razor @@ -55,13 +55,13 @@ @code { - JingetModal? modal1 { get; set; } - JingetModal? modal2 { get; set; } - JingetModal? modal3 { get; set; } - JingetModal? modal31 { get; set; } +JingetModal? modal1 { get; set; } +JingetModal? modal2 { get; set; } +JingetModal? modal3 { get; set; } +JingetModal? modal31 { get; set; } - async Task ShowModal1() => await modal1?.OpenAsync(); - async Task ShowModal2() => await modal2?.OpenAsync(); - async Task ShowModal3() => await modal3?.OpenAsync(); - async Task ShowModal31() => await modal31?.OpenAsync(); +async Task ShowModal1() => await modal1?.OpenAsync(); +async Task ShowModal2() => await modal2?.OpenAsync(); +async Task ShowModal3() => await modal3?.OpenAsync(); +async Task ShowModal31() => await modal31?.OpenAsync(); } \ No newline at end of file diff --git a/Tests/Jinget.Core.DiScanner.Tests/DiScannerTest.cs b/Tests/Jinget.Core.DiScanner.Tests/DiScannerTest.cs index 7ee40b2..1a69b99 100644 --- a/Tests/Jinget.Core.DiScanner.Tests/DiScannerTest.cs +++ b/Tests/Jinget.Core.DiScanner.Tests/DiScannerTest.cs @@ -1,307 +1,306 @@ -namespace Jinget.Core.DiScanner.Tests +namespace Jinget.Core.DiScanner.Tests; + +[TestClass] +public class DiScannerTest { - [TestClass] - public class DiScannerTest + private ServiceCollection? _services; + [TestInitialize] + public void Initialize() + { + _services = []; + } + + #region using assembly + + [TestMethod] + public void Should_register_and_resolve_transient_di_using_calling_assembly() + { + _services.RemoveAll(typeof(ICustomInterface)); + _services.Scan( + s => s.FromCallingAssembly() + .AddClasses() + .AsImplementedInterfaces() + .WithTransientLifetime()); + + var provider = _services.BuildServiceProvider(); + var resolvedService = provider.GetRequiredService(); + + Assert.IsNotNull(resolvedService); + } + + [TestMethod] + public void Should_register_and_resolve_scoped_di_using_calling_assembly() + { + _services.RemoveAll(typeof(ICustomInterface)); + _services.Scan( + s => s.FromCallingAssembly() + .AddClasses() + .AsImplementedInterfaces() + .WithScopedLifetime()); + + var provider = _services.BuildServiceProvider(); + var resolvedService = provider.GetRequiredService(); + + Assert.IsNotNull(resolvedService); + } + + [TestMethod] + public void Should_register_and_resolve_singleton_di_using_calling_assembly() + { + _services.RemoveAll(typeof(ICustomInterface)); + _services.Scan( + s => s.FromCallingAssembly() + .AddClasses() + .AsImplementedInterfaces() + .WithSingletonLifetime()); + + var provider = _services.BuildServiceProvider(); + var resolvedService = provider.GetRequiredService(); + + Assert.IsNotNull(resolvedService); + } + + [TestMethod] + public void Should_register_and_resolve_transient_di_using_executing_assembly() + { + _services.RemoveAll(typeof(ISelector)); + _services.Scan( + s => s.FromExecutingAssembly() + .AddClasses() + .AsImplementedInterfaces() + .WithTransientLifetime()); + + var provider = _services.BuildServiceProvider(); + var resolvedService = provider.GetRequiredService(); + + Assert.IsNotNull(resolvedService); + } + + [TestMethod] + public void Should_register_and_resolve_scoped_di_using_executing_assembly() + { + _services.RemoveAll(typeof(ISelector)); + _services.Scan( + s => s.FromExecutingAssembly() + .AddClasses() + .AsImplementedInterfaces() + .WithScopedLifetime()); + + var provider = _services.BuildServiceProvider(); + var resolvedService = provider.GetRequiredService(); + + Assert.IsNotNull(resolvedService); + } + + [TestMethod] + public void Should_register_and_resolve_singleton_di_using_executing_assembly() + { + _services.RemoveAll(typeof(ISelector)); + _services.Scan( + s => s.FromExecutingAssembly() + .AddClasses() + .AsImplementedInterfaces() + .WithSingletonLifetime()); + + var provider = _services.BuildServiceProvider(); + var resolvedService = provider.GetRequiredService(); + + Assert.IsNotNull(resolvedService); + } + + [TestMethod] + public void Should_register_and_resolve_transient_di_using_from_assemblies() + { + _services.RemoveAll(typeof(ISelector)); + _services.RemoveAll(typeof(ICustomInterface)); + + _services.Scan( + s => s.FromAssemblies(typeof(ICustomInterface).Assembly, typeof(ISelector).Assembly) + .AddClasses() + .AsImplementedInterfaces() + .WithTransientLifetime()); + + var provider = _services.BuildServiceProvider(); + var resolvedService1 = provider.GetRequiredService(); + var resolvedService2 = provider.GetRequiredService(); + + Assert.IsNotNull(resolvedService1); + Assert.IsNotNull(resolvedService2); + } + + [TestMethod] + public void Should_register_and_resolve_scoped_di_using_from_assemblies() + { + _services.RemoveAll(typeof(ISelector)); + _services.RemoveAll(typeof(ICustomInterface)); + + _services.Scan( + s => s.FromAssemblies(typeof(ICustomInterface).Assembly, typeof(ISelector).Assembly).AddClasses() + .AsImplementedInterfaces() + .WithScopedLifetime()); + + var provider = _services.BuildServiceProvider(); + var resolvedService1 = provider.GetRequiredService(); + var resolvedService2 = provider.GetRequiredService(); + + Assert.IsNotNull(resolvedService1); + Assert.IsNotNull(resolvedService2); + } + + [TestMethod] + public void Should_register_and_resolve_singleton_di_using_from_assemblies() + { + _services.RemoveAll(typeof(ISelector)); + _services.RemoveAll(typeof(ICustomInterface)); + + _services.Scan( + s => s.FromAssemblies(typeof(ICustomInterface).Assembly, typeof(ISelector).Assembly) + .AddClasses() + .AsImplementedInterfaces() + .WithSingletonLifetime()); + + var provider = _services.BuildServiceProvider(); + var resolvedService1 = provider.GetRequiredService(); + var resolvedService2 = provider.GetRequiredService(); + + Assert.IsNotNull(resolvedService1); + Assert.IsNotNull(resolvedService2); + } + + [TestMethod] + public void Should_register_and_resolve_transient_di_using_from_assembly() + { + _services.RemoveAll(typeof(ISelector)); + _services.Scan( + s => s.FromAssembliesOf(typeof(TypeSourceSelector)) + .AddClasses() + .AsImplementedInterfaces() + .WithTransientLifetime()); + + var provider = _services.BuildServiceProvider(); + var resolvedService = provider.GetRequiredService(); + + Assert.IsNotNull(resolvedService); + } + + [TestMethod] + public void Should_register_and_resolve_scoped_di_using_from_assembly() + { + _services.RemoveAll(typeof(ISelector)); + _services.Scan( + s => s.FromAssembliesOf(typeof(TypeSourceSelector)) + .AddClasses() + .AsImplementedInterfaces() + .WithScopedLifetime()); + + var provider = _services.BuildServiceProvider(); + var resolvedService = provider.GetRequiredService(); + + Assert.IsNotNull(resolvedService); + } + + [TestMethod] + public void Should_register_and_resolve_singleton_di_using_from_assembly() + { + _services.RemoveAll(typeof(ISelector)); + _services.Scan( + s => s.FromAssembliesOf(typeof(TypeSourceSelector)) + .AddClasses() + .AsImplementedInterfaces() + .WithSingletonLifetime()); + + var provider = _services.BuildServiceProvider(); + var resolvedService = provider.GetRequiredService(); + + Assert.IsNotNull(resolvedService); + } + + #endregion + + #region as self + + [TestMethod] + public void Should_register_and_resolve_di_as_self() + { + _services.RemoveAll(typeof(Sample)); + _services.Scan( + s => s.FromAssembliesOf(typeof(Sample)) + .AddClasses() + .AsSelf() + .WithSingletonLifetime()); + + var provider = _services.BuildServiceProvider(); + var resolvedService = provider.GetRequiredService(); + + Assert.IsNotNull(resolvedService); + } + + [TestMethod] + public void Should_register_and_resolve_di_as_custom() + { + _services.RemoveAll(typeof(ICustomInterface)); + _services.Scan( + s => s.FromAssembliesOf(typeof(Sample)) + .AddClasses(x => x.AssignableTo(typeof(ICustomInterface))) + .As() + .WithSingletonLifetime()); + + var provider = _services.BuildServiceProvider(); + var resolvedService = provider.GetRequiredService(); + + Assert.IsNotNull(resolvedService); + } + + [TestMethod] + public void Should_register_and_resolve_di_as_self_and_impl_interfaces() + { + _services.RemoveAll(typeof(ICustomInterface)); + _services.RemoveAll(typeof(Sample)); + _services.Scan( + s => s.FromAssembliesOf(typeof(Sample)) + .AddClasses() + .AsSelfWithInterfaces() + .WithSingletonLifetime()); + + var provider = _services.BuildServiceProvider(); + var resolvedService1 = provider.GetRequiredService(); + var resolvedService2 = provider.GetRequiredService(); + + Assert.IsNotNull(resolvedService1); + Assert.IsNotNull(resolvedService2); + } + + #endregion + + [TestMethod] + public void Should_register_and_resolve_di__using_addtype() + { + _services.RemoveAll(typeof(Sample)); + _services.Scan( + s => s.AddType() + .AsImplementedInterfaces() + .WithSingletonLifetime()); + + var provider = _services.BuildServiceProvider(); + var resolvedService = provider.GetRequiredService(); + + Assert.IsNotNull(resolvedService); + } + + [TestMethod] + public void Should_register_and_resolve_di__using_addtypes() { - private ServiceCollection? _services; - [TestInitialize] - public void Initialize() - { - _services = []; - } - - #region using assembly - - [TestMethod] - public void Should_register_and_resolve_transient_di_using_calling_assembly() - { - _services.RemoveAll(typeof(ICustomInterface)); - _services.Scan( - s => s.FromCallingAssembly() - .AddClasses() - .AsImplementedInterfaces() - .WithTransientLifetime()); - - var provider = _services.BuildServiceProvider(); - var resolvedService = provider.GetRequiredService(); - - Assert.IsNotNull(resolvedService); - } - - [TestMethod] - public void Should_register_and_resolve_scoped_di_using_calling_assembly() - { - _services.RemoveAll(typeof(ICustomInterface)); - _services.Scan( - s => s.FromCallingAssembly() - .AddClasses() - .AsImplementedInterfaces() - .WithScopedLifetime()); - - var provider = _services.BuildServiceProvider(); - var resolvedService = provider.GetRequiredService(); - - Assert.IsNotNull(resolvedService); - } - - [TestMethod] - public void Should_register_and_resolve_singleton_di_using_calling_assembly() - { - _services.RemoveAll(typeof(ICustomInterface)); - _services.Scan( - s => s.FromCallingAssembly() - .AddClasses() - .AsImplementedInterfaces() - .WithSingletonLifetime()); - - var provider = _services.BuildServiceProvider(); - var resolvedService = provider.GetRequiredService(); - - Assert.IsNotNull(resolvedService); - } - - [TestMethod] - public void Should_register_and_resolve_transient_di_using_executing_assembly() - { - _services.RemoveAll(typeof(ISelector)); - _services.Scan( - s => s.FromExecutingAssembly() - .AddClasses() - .AsImplementedInterfaces() - .WithTransientLifetime()); - - var provider = _services.BuildServiceProvider(); - var resolvedService = provider.GetRequiredService(); - - Assert.IsNotNull(resolvedService); - } - - [TestMethod] - public void Should_register_and_resolve_scoped_di_using_executing_assembly() - { - _services.RemoveAll(typeof(ISelector)); - _services.Scan( - s => s.FromExecutingAssembly() - .AddClasses() - .AsImplementedInterfaces() - .WithScopedLifetime()); - - var provider = _services.BuildServiceProvider(); - var resolvedService = provider.GetRequiredService(); - - Assert.IsNotNull(resolvedService); - } - - [TestMethod] - public void Should_register_and_resolve_singleton_di_using_executing_assembly() - { - _services.RemoveAll(typeof(ISelector)); - _services.Scan( - s => s.FromExecutingAssembly() - .AddClasses() - .AsImplementedInterfaces() - .WithSingletonLifetime()); - - var provider = _services.BuildServiceProvider(); - var resolvedService = provider.GetRequiredService(); - - Assert.IsNotNull(resolvedService); - } - - [TestMethod] - public void Should_register_and_resolve_transient_di_using_from_assemblies() - { - _services.RemoveAll(typeof(ISelector)); - _services.RemoveAll(typeof(ICustomInterface)); - - _services.Scan( - s => s.FromAssemblies(typeof(ICustomInterface).Assembly, typeof(ISelector).Assembly) - .AddClasses() - .AsImplementedInterfaces() - .WithTransientLifetime()); - - var provider = _services.BuildServiceProvider(); - var resolvedService1 = provider.GetRequiredService(); - var resolvedService2 = provider.GetRequiredService(); - - Assert.IsNotNull(resolvedService1); - Assert.IsNotNull(resolvedService2); - } - - [TestMethod] - public void Should_register_and_resolve_scoped_di_using_from_assemblies() - { - _services.RemoveAll(typeof(ISelector)); - _services.RemoveAll(typeof(ICustomInterface)); - - _services.Scan( - s => s.FromAssemblies(typeof(ICustomInterface).Assembly, typeof(ISelector).Assembly).AddClasses() - .AsImplementedInterfaces() - .WithScopedLifetime()); - - var provider = _services.BuildServiceProvider(); - var resolvedService1 = provider.GetRequiredService(); - var resolvedService2 = provider.GetRequiredService(); - - Assert.IsNotNull(resolvedService1); - Assert.IsNotNull(resolvedService2); - } - - [TestMethod] - public void Should_register_and_resolve_singleton_di_using_from_assemblies() - { - _services.RemoveAll(typeof(ISelector)); - _services.RemoveAll(typeof(ICustomInterface)); - - _services.Scan( - s => s.FromAssemblies(typeof(ICustomInterface).Assembly, typeof(ISelector).Assembly) - .AddClasses() - .AsImplementedInterfaces() - .WithSingletonLifetime()); - - var provider = _services.BuildServiceProvider(); - var resolvedService1 = provider.GetRequiredService(); - var resolvedService2 = provider.GetRequiredService(); - - Assert.IsNotNull(resolvedService1); - Assert.IsNotNull(resolvedService2); - } - - [TestMethod] - public void Should_register_and_resolve_transient_di_using_from_assembly() - { - _services.RemoveAll(typeof(ISelector)); - _services.Scan( - s => s.FromAssembliesOf(typeof(TypeSourceSelector)) - .AddClasses() - .AsImplementedInterfaces() - .WithTransientLifetime()); - - var provider = _services.BuildServiceProvider(); - var resolvedService = provider.GetRequiredService(); - - Assert.IsNotNull(resolvedService); - } - - [TestMethod] - public void Should_register_and_resolve_scoped_di_using_from_assembly() - { - _services.RemoveAll(typeof(ISelector)); - _services.Scan( - s => s.FromAssembliesOf(typeof(TypeSourceSelector)) - .AddClasses() - .AsImplementedInterfaces() - .WithScopedLifetime()); - - var provider = _services.BuildServiceProvider(); - var resolvedService = provider.GetRequiredService(); - - Assert.IsNotNull(resolvedService); - } - - [TestMethod] - public void Should_register_and_resolve_singleton_di_using_from_assembly() - { - _services.RemoveAll(typeof(ISelector)); - _services.Scan( - s => s.FromAssembliesOf(typeof(TypeSourceSelector)) - .AddClasses() - .AsImplementedInterfaces() - .WithSingletonLifetime()); - - var provider = _services.BuildServiceProvider(); - var resolvedService = provider.GetRequiredService(); - - Assert.IsNotNull(resolvedService); - } - - #endregion - - #region as self - - [TestMethod] - public void Should_register_and_resolve_di_as_self() - { - _services.RemoveAll(typeof(Sample)); - _services.Scan( - s => s.FromAssembliesOf(typeof(Sample)) - .AddClasses() - .AsSelf() - .WithSingletonLifetime()); - - var provider = _services.BuildServiceProvider(); - var resolvedService = provider.GetRequiredService(); - - Assert.IsNotNull(resolvedService); - } - - [TestMethod] - public void Should_register_and_resolve_di_as_custom() - { - _services.RemoveAll(typeof(ICustomInterface)); - _services.Scan( - s => s.FromAssembliesOf(typeof(Sample)) - .AddClasses(x => x.AssignableTo(typeof(ICustomInterface))) - .As() - .WithSingletonLifetime()); - - var provider = _services.BuildServiceProvider(); - var resolvedService = provider.GetRequiredService(); - - Assert.IsNotNull(resolvedService); - } - - [TestMethod] - public void Should_register_and_resolve_di_as_self_and_impl_interfaces() - { - _services.RemoveAll(typeof(ICustomInterface)); - _services.RemoveAll(typeof(Sample)); - _services.Scan( - s => s.FromAssembliesOf(typeof(Sample)) - .AddClasses() - .AsSelfWithInterfaces() - .WithSingletonLifetime()); - - var provider = _services.BuildServiceProvider(); - var resolvedService1 = provider.GetRequiredService(); - var resolvedService2 = provider.GetRequiredService(); - - Assert.IsNotNull(resolvedService1); - Assert.IsNotNull(resolvedService2); - } - - #endregion - - [TestMethod] - public void Should_register_and_resolve_di__using_addtype() - { - _services.RemoveAll(typeof(Sample)); - _services.Scan( - s => s.AddType() - .AsImplementedInterfaces() - .WithSingletonLifetime()); - - var provider = _services.BuildServiceProvider(); - var resolvedService = provider.GetRequiredService(); - - Assert.IsNotNull(resolvedService); - } - - [TestMethod] - public void Should_register_and_resolve_di__using_addtypes() - { - _services.RemoveAll(typeof(Sample)); - _services.Scan( - s => s.AddTypes(typeof(Sample), typeof(TypeSourceSelector)) - .AsImplementedInterfaces() - .WithSingletonLifetime()); - - var provider = _services.BuildServiceProvider(); - var resolvedService1 = provider.GetRequiredService(); - var resolvedService2 = provider.GetRequiredService(); - - Assert.IsNotNull(resolvedService1); - Assert.IsNotNull(resolvedService2); - } + _services.RemoveAll(typeof(Sample)); + _services.Scan( + s => s.AddTypes(typeof(Sample), typeof(TypeSourceSelector)) + .AsImplementedInterfaces() + .WithSingletonLifetime()); + + var provider = _services.BuildServiceProvider(); + var resolvedService1 = provider.GetRequiredService(); + var resolvedService2 = provider.GetRequiredService(); + + Assert.IsNotNull(resolvedService1); + Assert.IsNotNull(resolvedService2); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.DiScanner.Tests/SampleTypes/Contracts/ICustomInterface.cs b/Tests/Jinget.Core.DiScanner.Tests/SampleTypes/Contracts/ICustomInterface.cs index 9f042b7..062ac97 100644 --- a/Tests/Jinget.Core.DiScanner.Tests/SampleTypes/Contracts/ICustomInterface.cs +++ b/Tests/Jinget.Core.DiScanner.Tests/SampleTypes/Contracts/ICustomInterface.cs @@ -1,6 +1,5 @@ -namespace Jinget.Core.DiScanner.Tests.SampleTypes.Contracts +namespace Jinget.Core.DiScanner.Tests.SampleTypes.Contracts; + +public interface ICustomInterface { - public interface ICustomInterface - { - } } diff --git a/Tests/Jinget.Core.DiScanner.Tests/SampleTypes/Sample.cs b/Tests/Jinget.Core.DiScanner.Tests/SampleTypes/Sample.cs index cc76f81..9de02ea 100644 --- a/Tests/Jinget.Core.DiScanner.Tests/SampleTypes/Sample.cs +++ b/Tests/Jinget.Core.DiScanner.Tests/SampleTypes/Sample.cs @@ -1,8 +1,7 @@ using Jinget.Core.DiScanner.Tests.SampleTypes.Contracts; -namespace Jinget.Core.DiScanner.Tests.SampleTypes +namespace Jinget.Core.DiScanner.Tests.SampleTypes; + +public class Sample : ICustomInterface { - public class Sample : ICustomInterface - { - } } diff --git a/Tests/Jinget.Core.Tests/CodeDom/JingetDynamicCodeTests.cs b/Tests/Jinget.Core.Tests/CodeDom/JingetDynamicCodeTests.cs index 7312e05..0b05f7d 100644 --- a/Tests/Jinget.Core.Tests/CodeDom/JingetDynamicCodeTests.cs +++ b/Tests/Jinget.Core.Tests/CodeDom/JingetDynamicCodeTests.cs @@ -3,15 +3,15 @@ using System.Collections.Generic; using System.Linq; -namespace Jinget.Core.CodeDom.Tests +namespace Jinget.Core.CodeDom.Tests; + +[TestClass()] +public class JingetDynamicCodeTests { - [TestClass()] - public class JingetDynamicCodeTests + [TestMethod()] + public void should_compile_and_execute_dynamic_code_at_runtime_void_parameterless() { - [TestMethod()] - public void should_compile_and_execute_dynamic_code_at_runtime_void_parameterless() - { - string expectedSource = @" + string expectedSource = @" using System; namespace JingetDynamic { internal sealed class DynamicInvoker { @@ -21,20 +21,20 @@ internal sealed class DynamicInvoker { } } "; - string source = @"int x = 2*2"; + string source = @"int x = 2*2"; - var result = JingetDynamicCode.Execute(source, out List errors, out string compiledSourceCode); + var result = JingetDynamicCode.Execute(source, out List errors, out string compiledSourceCode); - Assert.IsNull(result); - Assert.IsFalse(errors.Any()); - Assert.AreEqual(expectedSource.Trim(), compiledSourceCode); - } + Assert.IsNull(result); + Assert.IsFalse(errors.Any()); + Assert.AreEqual(expectedSource.Trim(), compiledSourceCode); + } - [TestMethod] - public void should_compile_and_execute_dynamic_code_at_runtime_int_parameterless() - { - int expectedResult = 4; - string expectedSource = @" + [TestMethod] + public void should_compile_and_execute_dynamic_code_at_runtime_int_parameterless() + { + int expectedResult = 4; + string expectedSource = @" using System; namespace JingetDynamic { internal sealed class DynamicInvoker { @@ -44,20 +44,20 @@ internal sealed class DynamicInvoker { } } "; - string source = @"return 2*2"; + string source = @"return 2*2"; - var result = JingetDynamicCode.Execute(source, out List errors, out string compiledSourceCode, - new JingetDynamicCode.MethodOptions { ReturnType = typeof(int) }); + var result = JingetDynamicCode.Execute(source, out List errors, out string compiledSourceCode, + new JingetDynamicCode.MethodOptions { ReturnType = typeof(int) }); - Assert.IsFalse(errors.Any()); - Assert.AreEqual(expectedResult, result); - Assert.AreEqual(expectedSource.Trim(), compiledSourceCode); - } + Assert.IsFalse(errors.Any()); + Assert.AreEqual(expectedResult, result); + Assert.AreEqual(expectedSource.Trim(), compiledSourceCode); + } - [TestMethod] - public void should_compile_and_execute_dynamic_code_at_runtime_void_parametric() - { - string expectedSource = @" + [TestMethod] + public void should_compile_and_execute_dynamic_code_at_runtime_void_parametric() + { + string expectedSource = @" using System; using System.Linq; namespace JingetDynamic { @@ -68,27 +68,27 @@ internal sealed class DynamicInvoker { } } "; - string source = @"using System.Linq; double c = a*b;"; - - var result = JingetDynamicCode.Execute(source, out List errors, out string compiledSourceCode, - new JingetDynamicCode.MethodOptions - { - Parameters = - [ - new() {Name = "a",Type = typeof(int)}, - new() {Name = "b",Type = typeof(double)} - ] - }); - - Assert.IsFalse(errors.Any()); - Assert.IsNull(result); - Assert.AreEqual(expectedSource.Trim(), compiledSourceCode); - } + string source = @"using System.Linq; double c = a*b;"; + + var result = JingetDynamicCode.Execute(source, out List errors, out string compiledSourceCode, + new JingetDynamicCode.MethodOptions + { + Parameters = + [ + new() {Name = "a",Type = typeof(int)}, + new() {Name = "b",Type = typeof(double)} + ] + }); + + Assert.IsFalse(errors.Any()); + Assert.IsNull(result); + Assert.AreEqual(expectedSource.Trim(), compiledSourceCode); + } - [TestMethod] - public void should_compile_and_return_error() - { - string expectedSource = @" + [TestMethod] + public void should_compile_and_return_error() + { + string expectedSource = @" using System; namespace JingetDynamic { internal sealed class DynamicInvoker { @@ -99,126 +99,125 @@ internal sealed class DynamicInvoker { } "; - string source = @"c = a*b;"; - - var result = JingetDynamicCode.Execute(source, out List errors, out string compiledSourceCode, - new JingetDynamicCode.MethodOptions - { - Parameters = - [ - new() {Name = "a",Type = typeof(int)}, - new() {Name = "b",Type = typeof(double)} - ] - }); - - Assert.IsTrue(errors.Any()); - Assert.IsNull(result); - Assert.AreEqual(expectedSource.Trim(), compiledSourceCode); - } + string source = @"c = a*b;"; + + var result = JingetDynamicCode.Execute(source, out List errors, out string compiledSourceCode, + new JingetDynamicCode.MethodOptions + { + Parameters = + [ + new() {Name = "a",Type = typeof(int)}, + new() {Name = "b",Type = typeof(double)} + ] + }); + + Assert.IsTrue(errors.Any()); + Assert.IsNull(result); + Assert.AreEqual(expectedSource.Trim(), compiledSourceCode); + } - [TestMethod] - public void should_compile_and_execute_multiline_dynamic_code_at_runtime() - { - string expectedResult = "1399/07/21"; + [TestMethod] + public void should_compile_and_execute_multiline_dynamic_code_at_runtime() + { + string expectedResult = "1399/07/21"; - string code = @" + string code = @" using Jinget.Core; return ConvertDate(dt); string ConvertDate(DateTime dt) { return Jinget.Core.Utilities.DateTimeUtility.ToSolarDate(dt); }"; - var result = JingetDynamicCode.Execute( - code, - out List errors, out string compiledSourceCode, - options: new JingetDynamicCode.MethodOptions - { - ReturnType = typeof(string), - Parameters = - [ - new() { - Name="dt", - Value=new DateTime(2020, 10, 12), - Type = typeof(DateTime) - } - ] - }, - references: [typeof(Utilities.DateTimeUtility).Assembly.Location]); - - Assert.IsFalse(errors.Any()); - Assert.IsFalse(string.IsNullOrEmpty(compiledSourceCode)); - Assert.AreEqual(expectedResult, result); - } + var result = JingetDynamicCode.Execute( + code, + out List errors, out string compiledSourceCode, + options: new JingetDynamicCode.MethodOptions + { + ReturnType = typeof(string), + Parameters = + [ + new() { + Name="dt", + Value=new DateTime(2020, 10, 12), + Type = typeof(DateTime) + } + ] + }, + references: [typeof(Utilities.DateTimeUtility).Assembly.Location]); - [TestMethod] - public void should_compile_and_execute_single_dynamic_code_at_runtime() - { - string expectedResult = "1399/07/21"; - - string code = @"using Jinget.Core;return ConvertDate(dt);string ConvertDate(DateTime dt){return Jinget.Core.Utilities.DateTimeUtility.ToSolarDate(dt);}"; - - var result = JingetDynamicCode.Execute( - code, - out List errors, - out string compiledSourceCode, - options: new JingetDynamicCode.MethodOptions - { - ReturnType = typeof(string), - Parameters = - [ - new() { - Name="dt", - Value=new DateTime(2020, 10, 12), - Type = typeof(DateTime) - } - ] - }, - references: [typeof(Utilities.DateTimeUtility).Assembly.Location]); - - Assert.IsFalse(errors.Any()); - Assert.IsFalse(string.IsNullOrEmpty(compiledSourceCode)); - Assert.AreEqual(expectedResult, result); - } + Assert.IsFalse(errors.Any()); + Assert.IsFalse(string.IsNullOrEmpty(compiledSourceCode)); + Assert.AreEqual(expectedResult, result); + } - [TestMethod] - public void should_compile_and_execute_single_dynamic_code_at_runtime_with_pass_parameter_value() - { - int expectedResult = 6; - - string code = @"return GetValue(a, b);int GetValue(int a, int b){return a*b;}"; - - var result = JingetDynamicCode.Execute(code, out List errors, out string compiledSourceCode, - new JingetDynamicCode.MethodOptions() - { - ReturnType = typeof(int), - Parameters = - [ - new() { - Name = "a", - Value = 2, - Type = typeof(int) - }, - new() { - Name = "b", - Value = 3, - Type = typeof(int) - } - ] - }); - - Assert.IsFalse(errors.Any()); - Assert.IsFalse(string.IsNullOrEmpty(compiledSourceCode)); - Assert.AreEqual(expectedResult, result); - } + [TestMethod] + public void should_compile_and_execute_single_dynamic_code_at_runtime() + { + string expectedResult = "1399/07/21"; + + string code = @"using Jinget.Core;return ConvertDate(dt);string ConvertDate(DateTime dt){return Jinget.Core.Utilities.DateTimeUtility.ToSolarDate(dt);}"; + + var result = JingetDynamicCode.Execute( + code, + out List errors, + out string compiledSourceCode, + options: new JingetDynamicCode.MethodOptions + { + ReturnType = typeof(string), + Parameters = + [ + new() { + Name="dt", + Value=new DateTime(2020, 10, 12), + Type = typeof(DateTime) + } + ] + }, + references: [typeof(Utilities.DateTimeUtility).Assembly.Location]); - [TestMethod] - [ExpectedException(typeof(ArgumentException))] - public void should_throw_exception() - { - string source = ""; - for (int i = 0; i < 10001; i++) source += "c = a*b;"; + Assert.IsFalse(errors.Any()); + Assert.IsFalse(string.IsNullOrEmpty(compiledSourceCode)); + Assert.AreEqual(expectedResult, result); + } - JingetDynamicCode.Execute(source, out List _, out string _); - } + [TestMethod] + public void should_compile_and_execute_single_dynamic_code_at_runtime_with_pass_parameter_value() + { + int expectedResult = 6; + + string code = @"return GetValue(a, b);int GetValue(int a, int b){return a*b;}"; + + var result = JingetDynamicCode.Execute(code, out List errors, out string compiledSourceCode, + new JingetDynamicCode.MethodOptions() + { + ReturnType = typeof(int), + Parameters = + [ + new() { + Name = "a", + Value = 2, + Type = typeof(int) + }, + new() { + Name = "b", + Value = 3, + Type = typeof(int) + } + ] + }); + + Assert.IsFalse(errors.Any()); + Assert.IsFalse(string.IsNullOrEmpty(compiledSourceCode)); + Assert.AreEqual(expectedResult, result); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void should_throw_exception() + { + string source = ""; + for (int i = 0; i < 10001; i++) source += "c = a*b;"; + + JingetDynamicCode.Execute(source, out List _, out string _); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/Exceptions/JingetExceptionTests.cs b/Tests/Jinget.Core.Tests/Exceptions/JingetExceptionTests.cs index 51cd3d1..489b65b 100644 --- a/Tests/Jinget.Core.Tests/Exceptions/JingetExceptionTests.cs +++ b/Tests/Jinget.Core.Tests/Exceptions/JingetExceptionTests.cs @@ -1,59 +1,58 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using System; -namespace Jinget.Core.Exceptions.Tests +namespace Jinget.Core.Exceptions.Tests; + +[TestClass()] +public class JingetExceptionTests { - [TestClass()] - public class JingetExceptionTests + [TestMethod()] + public void Shsould_throw_jinget_expection_with_default_params() { - [TestMethod()] - public void Shsould_throw_jinget_expection_with_default_params() - { - string exceptionMessage = "This is test exception"; - int exceptionCode = -1; + string exceptionMessage = "This is test exception"; + int exceptionCode = -1; - try - { - throw new JingetException(exceptionMessage); - } - catch (JingetException ex) - when ( - ex.Message == exceptionMessage && - ex.Code == exceptionCode && - ex.Type == Enumerations.ExceptionType.JingetInternal) - { - Assert.IsTrue(true); - } - catch - { - Assert.Fail(); - } + try + { + throw new JingetException(exceptionMessage); } - - [TestMethod()] - public void Shsould_throw_jinget_expection_with_inner_exception() + catch (JingetException ex) + when ( + ex.Message == exceptionMessage && + ex.Code == exceptionCode && + ex.Type == Enumerations.ExceptionType.JingetInternal) { - Exception innerException = new AccessViolationException(); - string exceptionMessage = "This is test exception"; - int exceptionCode = -1; + Assert.IsTrue(true); + } + catch + { + Assert.Fail(); + } + } - try - { - throw new JingetException(exceptionMessage, innerException, exceptionCode, Enumerations.ExceptionType.Custom); - } - catch (JingetException ex) - when ( - ex.Message == exceptionMessage && - ex.Code == exceptionCode && - ex.Type == Enumerations.ExceptionType.Custom && - ex.InnerException is AccessViolationException) - { - Assert.IsTrue(true); - } - catch - { - Assert.Fail(); - } + [TestMethod()] + public void Shsould_throw_jinget_expection_with_inner_exception() + { + Exception innerException = new AccessViolationException(); + string exceptionMessage = "This is test exception"; + int exceptionCode = -1; + + try + { + throw new JingetException(exceptionMessage, innerException, exceptionCode, Enumerations.ExceptionType.Custom); + } + catch (JingetException ex) + when ( + ex.Message == exceptionMessage && + ex.Code == exceptionCode && + ex.Type == Enumerations.ExceptionType.Custom && + ex.InnerException is AccessViolationException) + { + Assert.IsTrue(true); + } + catch + { + Assert.Fail(); } } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/ExpressionToSql/Internal/OrderByTests.cs b/Tests/Jinget.Core.Tests/ExpressionToSql/Internal/OrderByTests.cs index faa184e..76d67fb 100644 --- a/Tests/Jinget.Core.Tests/ExpressionToSql/Internal/OrderByTests.cs +++ b/Tests/Jinget.Core.Tests/ExpressionToSql/Internal/OrderByTests.cs @@ -2,49 +2,48 @@ using Jinget.Core.Tests._BaseData; using Jinget.Core.Enumerations; -namespace Jinget.Core.ExpressionToSql.Internal.Tests +namespace Jinget.Core.ExpressionToSql.Internal.Tests; + +[TestClass()] +public class OrderByTests { - [TestClass()] - public class OrderByTests + [TestMethod()] + public void should_return_orderby_clause_simple_expression() { - [TestMethod()] - public void should_return_orderby_clause_simple_expression() + string expectedResult = "[Property1] ASC"; + string result = new OrderBy { - string expectedResult = "[Property1] ASC"; - string result = new OrderBy - { - Name = f => ((TestClass)f).Property1, - Direction = OrderByDirection.Ascending - }.ToString(); - Assert.AreEqual(expectedResult, result); - } + Name = f => ((TestClass)f).Property1, + Direction = OrderByDirection.Ascending + }.ToString(); + Assert.AreEqual(expectedResult, result); + } - [TestMethod] - public void should_return_orderby_clause_constant_column() + [TestMethod] + public void should_return_orderby_clause_constant_column() + { + string expectedResult = "[Property1] ASC"; + string result = new OrderBy { - string expectedResult = "[Property1] ASC"; - string result = new OrderBy - { - Name = f => "Property1", - Direction = OrderByDirection.Ascending - }.ToString(); - Assert.AreEqual(expectedResult, result); - } + Name = f => "Property1", + Direction = OrderByDirection.Ascending + }.ToString(); + Assert.AreEqual(expectedResult, result); + } - /// - /// Successful order by clause creation using reflection property discovery - /// In this case string literal first should convert to lambda expression and then it should executed - /// - [TestMethod] - public void should_return_orderby_clause_string_literal_reflection() + /// + /// Successful order by clause creation using reflection property discovery + /// In this case string literal first should convert to lambda expression and then it should executed + /// + [TestMethod] + public void should_return_orderby_clause_string_literal_reflection() + { + string expectedResult = "[Property1] ASC"; + string result = new OrderBy { - string expectedResult = "[Property1] ASC"; - string result = new OrderBy - { - Name = f => typeof(TestClass).GetProperty("Property1").Name, - Direction = OrderByDirection.Ascending - }.ToString(); - Assert.AreEqual(expectedResult, result); - } + Name = f => typeof(TestClass).GetProperty("Property1").Name, + Direction = OrderByDirection.Ascending + }.ToString(); + Assert.AreEqual(expectedResult, result); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/ExpressionToSql/Internal/PagingTests.cs b/Tests/Jinget.Core.Tests/ExpressionToSql/Internal/PagingTests.cs index 65fcb5b..6cc3423 100644 --- a/Tests/Jinget.Core.Tests/ExpressionToSql/Internal/PagingTests.cs +++ b/Tests/Jinget.Core.Tests/ExpressionToSql/Internal/PagingTests.cs @@ -1,32 +1,31 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace Jinget.Core.ExpressionToSql.Internal.Tests +namespace Jinget.Core.ExpressionToSql.Internal.Tests; + +[TestClass()] +public class PagingTests { - [TestClass()] - public class PagingTests + [TestMethod()] + public void should_return_paging_clause() { - [TestMethod()] - public void should_return_paging_clause() - { - string expectedResult = "OFFSET 0 ROWS FETCH NEXT 5 ROWS ONLY"; - string result = new Paging { PageNumber = 1, PageSize = 5 }.ToString(); - Assert.AreEqual(expectedResult, result); - } + string expectedResult = "OFFSET 0 ROWS FETCH NEXT 5 ROWS ONLY"; + string result = new Paging { PageNumber = 1, PageSize = 5 }.ToString(); + Assert.AreEqual(expectedResult, result); + } - [TestMethod()] - public void should_return_paging_clause_default_page_size() - { - string expectedResult = "OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY"; - string result = new Paging { PageNumber = -1, PageSize = -1 }.ToString(); - Assert.AreEqual(expectedResult, result); - } + [TestMethod()] + public void should_return_paging_clause_default_page_size() + { + string expectedResult = "OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY"; + string result = new Paging { PageNumber = -1, PageSize = -1 }.ToString(); + Assert.AreEqual(expectedResult, result); + } - [TestMethod()] - public void should_return_nothing() - { - string expectedResult = ""; - string result = new Paging { PageNumber = 0, PageSize = 0 }.ToString(); - Assert.AreEqual(expectedResult, result); - } + [TestMethod()] + public void should_return_nothing() + { + string expectedResult = ""; + string result = new Paging { PageNumber = 0, PageSize = 0 }.ToString(); + Assert.AreEqual(expectedResult, result); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/ExpressionToSql/Internal/QueryBuilderTests.cs b/Tests/Jinget.Core.Tests/ExpressionToSql/Internal/QueryBuilderTests.cs index 9787e2f..5f0dc82 100644 --- a/Tests/Jinget.Core.Tests/ExpressionToSql/Internal/QueryBuilderTests.cs +++ b/Tests/Jinget.Core.Tests/ExpressionToSql/Internal/QueryBuilderTests.cs @@ -1,54 +1,53 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Text; -namespace Jinget.Core.ExpressionToSql.Internal.Tests +namespace Jinget.Core.ExpressionToSql.Internal.Tests; + +[TestClass()] +public class QueryBuilderTests { - [TestClass()] - public class QueryBuilderTests - { - private QueryBuilder _qb; + private QueryBuilder _qb; - [TestInitialize] - public void Initialize() => _qb = new QueryBuilder(new StringBuilder()); + [TestInitialize] + public void Initialize() => _qb = new QueryBuilder(new StringBuilder()); - [TestMethod()] - public void should_return_top_expression() - { - string expectedResult = "SELECT TOP 10"; - var result = _qb.Take(10).ToString(); - Assert.AreEqual(expectedResult, result.ToString()); - } + [TestMethod()] + public void should_return_top_expression() + { + string expectedResult = "SELECT TOP 10"; + var result = _qb.Take(10).ToString(); + Assert.AreEqual(expectedResult, result.ToString()); + } - [TestMethod()] - public void should_return_columns() - { - string expectedResult = "SELECT c.[Col1], c.[Col2]"; - var result = _qb.AddAttribute("Col1", "c").AddSeparator().AddAttribute("[Col2]", "c"); - Assert.AreEqual(expectedResult, result.ToString()); - } + [TestMethod()] + public void should_return_columns() + { + string expectedResult = "SELECT c.[Col1], c.[Col2]"; + var result = _qb.AddAttribute("Col1", "c").AddSeparator().AddAttribute("[Col2]", "c"); + Assert.AreEqual(expectedResult, result.ToString()); + } - [TestMethod()] - public void should_return_table_name() + [TestMethod()] + public void should_return_table_name() + { + string expectedResult = "SELECT FROM [Sch].[MyTable] AS T"; + var result = _qb.AddTable(new Table { - string expectedResult = "SELECT FROM [Sch].[MyTable] AS T"; - var result = _qb.AddTable(new Table - { - Name = "MyTable", - Schema = "Sch" - }, "T"); - Assert.AreEqual(expectedResult, result.ToString()); - } + Name = "MyTable", + Schema = "Sch" + }, "T"); + Assert.AreEqual(expectedResult, result.ToString()); + } - [TestMethod()] - public void should_return_function_name() + [TestMethod()] + public void should_return_function_name() + { + string expectedResult = "SELECT FROM [Sch].[Function]() AS F"; + var result = _qb.AddTable(new Table { - string expectedResult = "SELECT FROM [Sch].[Function]() AS F"; - var result = _qb.AddTable(new Table - { - Name = "Function()", - Schema = "Sch" - }, "F"); - Assert.AreEqual(expectedResult, result.ToString()); - } + Name = "Function()", + Schema = "Sch" + }, "F"); + Assert.AreEqual(expectedResult, result.ToString()); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/ExpressionToSql/SqlTests.cs b/Tests/Jinget.Core.Tests/ExpressionToSql/SqlTests.cs index 8c347bb..60c6164 100644 --- a/Tests/Jinget.Core.Tests/ExpressionToSql/SqlTests.cs +++ b/Tests/Jinget.Core.Tests/ExpressionToSql/SqlTests.cs @@ -4,550 +4,549 @@ using System.Collections.Generic; using System; -namespace Jinget.Core.ExpressionToSql.Tests +namespace Jinget.Core.ExpressionToSql.Tests; + +[TestClass()] +public class SqlTests { - [TestClass()] - public class SqlTests - { - #region SELECT + #region SELECT - #region Simple Select + #region Simple Select - [TestMethod] - public void Should_return_select_from_table_using_table_name() - { - var expectedResult = "SELECT a.[Id] FROM [dbo].[tblTest] AS a"; + [TestMethod] + public void Should_return_select_from_table_using_table_name() + { + var expectedResult = "SELECT a.[Id] FROM [dbo].[tblTest] AS a"; - var result = Sql.Select(x => new { x.Id }, "tblTest").ToSql(); + var result = Sql.Select(x => new { x.Id }, "tblTest").ToSql(); - Assert.AreEqual(expectedResult, result.query.ToString()); - Assert.IsTrue(result.parameters is null); - } + Assert.AreEqual(expectedResult, result.query.ToString()); + Assert.IsTrue(result.parameters is null); + } - [TestMethod] - public void Should_return_select_from_table_using_table_type() - { - var expectedResult = "SELECT a.[Id] FROM [dbo].[tblTest] AS a"; + [TestMethod] + public void Should_return_select_from_table_using_table_type() + { + var expectedResult = "SELECT a.[Id] FROM [dbo].[tblTest] AS a"; - var result = Sql.Select(x => new { x.Id }, new Table { Name = "tblTest" }).ToSql(); + var result = Sql.Select(x => new { x.Id }, new Table { Name = "tblTest" }).ToSql(); - Assert.AreEqual(expectedResult, result.query.ToString()); - Assert.IsTrue(result.parameters is null); - } + Assert.AreEqual(expectedResult, result.query.ToString()); + Assert.IsTrue(result.parameters is null); + } - #endregion + #endregion - #region Custome Schema + #region Custome Schema - [TestMethod] - public void Should_return_select_single_column_from_table_custom_schema() - { - var expectedResult = "SELECT a.[Id] FROM [sch].[tblTest] AS a"; + [TestMethod] + public void Should_return_select_single_column_from_table_custom_schema() + { + var expectedResult = "SELECT a.[Id] FROM [sch].[tblTest] AS a"; - var result = Sql.Select(x => new { x.Id }, new Table() { Name = "tblTest", Schema = "sch" }).ToSql(); + var result = Sql.Select(x => new { x.Id }, new Table() { Name = "tblTest", Schema = "sch" }).ToSql(); - Assert.AreEqual(expectedResult, result.query.ToString()); - Assert.IsTrue(result.parameters is null); - } + Assert.AreEqual(expectedResult, result.query.ToString()); + Assert.IsTrue(result.parameters is null); + } - #endregion + #endregion - #region TOP - [TestMethod] - public void Should_return_select_top_from_table_using_table_name() - { - var expectedResult = "SELECT TOP 10 a.[Id] FROM [dbo].[tblTest] AS a"; + #region TOP + [TestMethod] + public void Should_return_select_top_from_table_using_table_name() + { + var expectedResult = "SELECT TOP 10 a.[Id] FROM [dbo].[tblTest] AS a"; - var result = Sql.Top(x => new { x.Id }, 10, "tblTest").ToSql(); + var result = Sql.Top(x => new { x.Id }, 10, "tblTest").ToSql(); - Assert.AreEqual(expectedResult, result.query.ToString()); - Assert.IsTrue(result.parameters is null); - } + Assert.AreEqual(expectedResult, result.query.ToString()); + Assert.IsTrue(result.parameters is null); + } - [TestMethod] - public void Should_return_select_top_from_table_using_table_type() - { - var expectedResult = "SELECT TOP 10 a.[Id] FROM [dbo].[tblTest] AS a"; + [TestMethod] + public void Should_return_select_top_from_table_using_table_type() + { + var expectedResult = "SELECT TOP 10 a.[Id] FROM [dbo].[tblTest] AS a"; - var result = Sql.Top(x => new { x.Id }, 10, new Table { Name = "tblTest" }).ToSql(); + var result = Sql.Top(x => new { x.Id }, 10, new Table { Name = "tblTest" }).ToSql(); - Assert.AreEqual(expectedResult, result.query.ToString()); - Assert.IsTrue(result.parameters is null); - } + Assert.AreEqual(expectedResult, result.query.ToString()); + Assert.IsTrue(result.parameters is null); + } - #endregion + #endregion - #region Multiple Column + #region Multiple Column - [TestMethod] - public void Should_return_select_multiple_columns_from_table() - { - var expectedQuery = "SELECT a.[Id], a.[FirstName] FROM [dbo].[tblTest] AS a"; + [TestMethod] + public void Should_return_select_multiple_columns_from_table() + { + var expectedQuery = "SELECT a.[Id], a.[FirstName] FROM [dbo].[tblTest] AS a"; - var result = Sql.Select(x => new { x.Id, x.FirstName }, "tblTest").ToSql(); + var result = Sql.Select(x => new { x.Id, x.FirstName }, "tblTest").ToSql(); - Assert.AreEqual(expectedQuery, result.query.ToString()); - } + Assert.AreEqual(expectedQuery, result.query.ToString()); + } - [TestMethod] - public void Should_return_select_all_columns_from_table() - { - var expectedQuery = "SELECT a.[Id], a.[FirstName], a.[LastName], a.[Age] FROM [dbo].[tblTest] AS a"; + [TestMethod] + public void Should_return_select_all_columns_from_table() + { + var expectedQuery = "SELECT a.[Id], a.[FirstName], a.[LastName], a.[Age] FROM [dbo].[tblTest] AS a"; - var result = Sql.Select(x => x, "tblTest").ToSql(); + var result = Sql.Select(x => x, "tblTest").ToSql(); - Assert.AreEqual(expectedQuery, result.query.ToString()); - } + Assert.AreEqual(expectedQuery, result.query.ToString()); + } - [TestMethod] - public void Should_return_select_one_column_and_one_constant_from_table() - { - var expectedQuery = "SELECT a.[Id], 'Const Value' FROM [dbo].[tblTest] AS a"; + [TestMethod] + public void Should_return_select_one_column_and_one_constant_from_table() + { + var expectedQuery = "SELECT a.[Id], 'Const Value' FROM [dbo].[tblTest] AS a"; - var result = Sql.Select(x => new { x.Id, Name = "'Const Value'" }, "tblTest").ToSql(); + var result = Sql.Select(x => new { x.Id, Name = "'Const Value'" }, "tblTest").ToSql(); - Assert.AreEqual(expectedQuery, result.query.ToString()); - } + Assert.AreEqual(expectedQuery, result.query.ToString()); + } - #endregion + #endregion - #endregion + #endregion - #region WHERE + #region WHERE - #region WHERE = + #region WHERE = - [TestMethod] - public void Should_return_select_single_column_from_table_where_one_string_column_equal() - { - var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE ([FirstName] = @1)"; - Dictionary expectedParameters = new() { { "1", "Vahid" } }; + [TestMethod] + public void Should_return_select_single_column_from_table_where_one_string_column_equal() + { + var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE ([FirstName] = @1)"; + Dictionary expectedParameters = new() { { "1", "Vahid" } }; - var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => x.FirstName == "Vahid").ToSql(); + var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => x.FirstName == "Vahid").ToSql(); - Assert.AreEqual(expectedQuery, result.query.ToString()); + Assert.AreEqual(expectedQuery, result.query.ToString()); - Assert.IsNotNull(expectedParameters); + Assert.IsNotNull(expectedParameters); - if (result.parameters.Count != 1) - Assert.Fail($"Expected 1 parameter, but get {expectedParameters.Count}"); + if (result.parameters.Count != 1) + Assert.Fail($"Expected 1 parameter, but get {expectedParameters.Count}"); - if (!result.parameters.ContainsKey("1")) - Assert.Fail("Expected parameter 1 not found"); + if (!result.parameters.ContainsKey("1")) + Assert.Fail("Expected parameter 1 not found"); - Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); - } + Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); + } - [TestMethod] - public void Should_return_select_single_column_from_table_where_one_string_column_equal_to_itself() - { - var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE ([FirstName] = @FirstName)"; - Dictionary expectedParameters = []; + [TestMethod] + public void Should_return_select_single_column_from_table_where_one_string_column_equal_to_itself() + { + var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE ([FirstName] = @FirstName)"; + Dictionary expectedParameters = []; - var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => x.FirstName == x.FirstName).ToSql(); + var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => x.FirstName == x.FirstName).ToSql(); - Assert.AreEqual(expectedQuery, result.query.ToString()); + Assert.AreEqual(expectedQuery, result.query.ToString()); - Assert.IsNotNull(expectedParameters); + Assert.IsNotNull(expectedParameters); - if (result.parameters.Count != 0) - Assert.Fail($"Expected 0 parameter, but get {expectedParameters.Count}"); - } + if (result.parameters.Count != 0) + Assert.Fail($"Expected 0 parameter, but get {expectedParameters.Count}"); + } - [TestMethod] - public void Should_return_select_single_column_from_table_where_one_string_column_equal_to_other_column() - { - var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE ([FirstName] = @LastName)"; - Dictionary expectedParameters = []; + [TestMethod] + public void Should_return_select_single_column_from_table_where_one_string_column_equal_to_other_column() + { + var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE ([FirstName] = @LastName)"; + Dictionary expectedParameters = []; - var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => x.FirstName == x.LastName).ToSql(); + var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => x.FirstName == x.LastName).ToSql(); - Assert.AreEqual(expectedQuery, result.query.ToString()); + Assert.AreEqual(expectedQuery, result.query.ToString()); - Assert.IsNotNull(expectedParameters); + Assert.IsNotNull(expectedParameters); - if (result.parameters.Count != 0) - Assert.Fail($"Expected 0 parameter, but get {expectedParameters.Count}"); - } + if (result.parameters.Count != 0) + Assert.Fail($"Expected 0 parameter, but get {expectedParameters.Count}"); + } - [TestMethod] - public void Should_return_select_single_column_from_table_where_one_string_column_call_method() - { - var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE ([FirstName] = @1)"; - Dictionary expectedParameters = new() { { "1", "vahid" } }; + [TestMethod] + public void Should_return_select_single_column_from_table_where_one_string_column_call_method() + { + var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE ([FirstName] = @1)"; + Dictionary expectedParameters = new() { { "1", "vahid" } }; - var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => x.FirstName == "Vahid".ToLower()).ToSql(); + var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => x.FirstName == "Vahid".ToLower()).ToSql(); - Assert.AreEqual(expectedQuery, result.query.ToString()); + Assert.AreEqual(expectedQuery, result.query.ToString()); - Assert.IsNotNull(expectedParameters); + Assert.IsNotNull(expectedParameters); - if (result.parameters.Count != 1) - Assert.Fail($"Expected 1 parameter, but get {expectedParameters.Count}"); + if (result.parameters.Count != 1) + Assert.Fail($"Expected 1 parameter, but get {expectedParameters.Count}"); - if (!result.parameters.ContainsKey("1")) - Assert.Fail("Expected parameter 1 not found"); + if (!result.parameters.ContainsKey("1")) + Assert.Fail("Expected parameter 1 not found"); - Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); - } + Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); + } - [TestMethod] - [ExpectedException(typeof(InvalidOperationException))] - public void Should_throw_exception_for_unsupported_method_call() - { - Sql.Select(x => new { x.Id }, "tblTest").Where(x => x.FirstName.Normalize() == "Vahid").ToSql(); - } + [TestMethod] + [ExpectedException(typeof(InvalidOperationException))] + public void Should_throw_exception_for_unsupported_method_call() + { + Sql.Select(x => new { x.Id }, "tblTest").Where(x => x.FirstName.Normalize() == "Vahid").ToSql(); + } - #endregion + #endregion - #region Where LIKE + #region Where LIKE - [TestMethod] - public void Should_return_select_single_column_from_table_where_one_string_column_like() - { - var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE ([FirstName] LIKE @1)"; - Dictionary expectedParameters = new() { { "1", "%vahid%" } }; + [TestMethod] + public void Should_return_select_single_column_from_table_where_one_string_column_like() + { + var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE ([FirstName] LIKE @1)"; + Dictionary expectedParameters = new() { { "1", "%vahid%" } }; - var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => x.FirstName.Contains("vahid")).ToSql(); + var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => x.FirstName.Contains("vahid")).ToSql(); - Assert.AreEqual(expectedQuery, result.query.ToString()); + Assert.AreEqual(expectedQuery, result.query.ToString()); - Assert.IsNotNull(expectedParameters); + Assert.IsNotNull(expectedParameters); - if (result.parameters.Count != 1) - Assert.Fail($"Expected 1 parameter, but get {expectedParameters.Count}"); + if (result.parameters.Count != 1) + Assert.Fail($"Expected 1 parameter, but get {expectedParameters.Count}"); - if (!result.parameters.ContainsKey("1")) - Assert.Fail("Expected parameter 1 not found"); + if (!result.parameters.ContainsKey("1")) + Assert.Fail("Expected parameter 1 not found"); - Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); - } + Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); + } - [TestMethod] - public void Should_return_select_single_column_from_table_where_one_string_column_like_start() - { - var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE ([FirstName] LIKE @1)"; - Dictionary expectedParameters = new() { { "1", "vahid%" } }; + [TestMethod] + public void Should_return_select_single_column_from_table_where_one_string_column_like_start() + { + var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE ([FirstName] LIKE @1)"; + Dictionary expectedParameters = new() { { "1", "vahid%" } }; - var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => x.FirstName.StartsWith("vahid")).ToSql(); + var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => x.FirstName.StartsWith("vahid")).ToSql(); - Assert.AreEqual(expectedQuery, result.query.ToString()); + Assert.AreEqual(expectedQuery, result.query.ToString()); - Assert.IsNotNull(expectedParameters); + Assert.IsNotNull(expectedParameters); - if (result.parameters.Count != 1) - Assert.Fail($"Expected 1 parameter, but get {expectedParameters.Count}"); + if (result.parameters.Count != 1) + Assert.Fail($"Expected 1 parameter, but get {expectedParameters.Count}"); - if (!result.parameters.ContainsKey("1")) - Assert.Fail("Expected parameter 1 not found"); + if (!result.parameters.ContainsKey("1")) + Assert.Fail("Expected parameter 1 not found"); - Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); - } + Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); + } - [TestMethod] - public void Should_return_select_single_column_from_table_where_one_string_column_like_end() - { - var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE ([FirstName] LIKE @1)"; - Dictionary expectedParameters = new() { { "1", "%vahid" } }; + [TestMethod] + public void Should_return_select_single_column_from_table_where_one_string_column_like_end() + { + var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE ([FirstName] LIKE @1)"; + Dictionary expectedParameters = new() { { "1", "%vahid" } }; - var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => x.FirstName.EndsWith("vahid")).ToSql(); + var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => x.FirstName.EndsWith("vahid")).ToSql(); - Assert.AreEqual(expectedQuery, result.query.ToString()); + Assert.AreEqual(expectedQuery, result.query.ToString()); - Assert.IsNotNull(expectedParameters); + Assert.IsNotNull(expectedParameters); - if (result.parameters.Count != 1) - Assert.Fail($"Expected 1 parameter, but get {expectedParameters.Count}"); + if (result.parameters.Count != 1) + Assert.Fail($"Expected 1 parameter, but get {expectedParameters.Count}"); - if (!result.parameters.ContainsKey("1")) - Assert.Fail("Expected parameter 1 not found"); + if (!result.parameters.ContainsKey("1")) + Assert.Fail("Expected parameter 1 not found"); - Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); - } + Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); + } - #endregion + #endregion - #region Where > + #region Where > - [TestMethod] - public void Should_return_select_single_column_from_table_where_one_number_column_greaterthan() - { - var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE ([Age] > @1)"; - Dictionary expectedParameters = new() { { "1", 20 } }; + [TestMethod] + public void Should_return_select_single_column_from_table_where_one_number_column_greaterthan() + { + var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE ([Age] > @1)"; + Dictionary expectedParameters = new() { { "1", 20 } }; - var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => x.Age > 20).ToSql(); + var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => x.Age > 20).ToSql(); - Assert.AreEqual(expectedQuery, result.query.ToString()); + Assert.AreEqual(expectedQuery, result.query.ToString()); - Assert.IsNotNull(expectedParameters); + Assert.IsNotNull(expectedParameters); - if (result.parameters.Count != 1) - Assert.Fail($"Expected 1 parameter, but get {expectedParameters.Count}"); + if (result.parameters.Count != 1) + Assert.Fail($"Expected 1 parameter, but get {expectedParameters.Count}"); - if (!result.parameters.ContainsKey("1")) - Assert.Fail("Expected parameter 1 not found"); + if (!result.parameters.ContainsKey("1")) + Assert.Fail("Expected parameter 1 not found"); - Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); - } + Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); + } - #endregion + #endregion - #region Where IN + #region Where IN - [TestMethod] - public void Should_return_select_single_column_from_table_where_one_number_column_in() - { - var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE ([Age] IN (@1,@2))"; - Dictionary expectedParameters = new() { { "1", 20 }, { "2", 30 } }; + [TestMethod] + public void Should_return_select_single_column_from_table_where_one_number_column_in() + { + var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE ([Age] IN (@1,@2))"; + Dictionary expectedParameters = new() { { "1", 20 }, { "2", 30 } }; - var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => new List() { 20, 30 }.Contains(x.Age)).ToSql(); + var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => new List() { 20, 30 }.Contains(x.Age)).ToSql(); - Assert.AreEqual(expectedQuery, result.query.ToString()); + Assert.AreEqual(expectedQuery, result.query.ToString()); - Assert.IsNotNull(expectedParameters); + Assert.IsNotNull(expectedParameters); - if (result.parameters.Count != 2) - Assert.Fail($"Expected 2 parameter, but get {expectedParameters.Count}"); + if (result.parameters.Count != 2) + Assert.Fail($"Expected 2 parameter, but get {expectedParameters.Count}"); - if (!result.parameters.ContainsKey("1")) - Assert.Fail("Expected parameter 1 not found"); + if (!result.parameters.ContainsKey("1")) + Assert.Fail("Expected parameter 1 not found"); - if (!result.parameters.ContainsKey("2")) - Assert.Fail("Expected parameter 2 not found"); + if (!result.parameters.ContainsKey("2")) + Assert.Fail("Expected parameter 2 not found"); - Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); - Assert.AreEqual(expectedParameters["2"].ToString(), result.parameters["2"].ToString()); - } + Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); + Assert.AreEqual(expectedParameters["2"].ToString(), result.parameters["2"].ToString()); + } - #endregion + #endregion - #region WHERE AND = - [TestMethod] - public void Should_return_select_single_column_from_table_where_two_string_columns_and() - { - var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE (([FirstName] = @1) AND ([LastName] = @2))"; - Dictionary expectedParameters = new() { { "1", "Vahid" }, { "2", "Farahmandian" } }; + #region WHERE AND = + [TestMethod] + public void Should_return_select_single_column_from_table_where_two_string_columns_and() + { + var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE (([FirstName] = @1) AND ([LastName] = @2))"; + Dictionary expectedParameters = new() { { "1", "Vahid" }, { "2", "Farahmandian" } }; - var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => x.FirstName == "Vahid" && x.LastName == "Farahmandian").ToSql(); + var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => x.FirstName == "Vahid" && x.LastName == "Farahmandian").ToSql(); - Assert.AreEqual(expectedQuery, result.query.ToString()); + Assert.AreEqual(expectedQuery, result.query.ToString()); - Assert.IsNotNull(expectedParameters); + Assert.IsNotNull(expectedParameters); - if (result.parameters.Count != 2) - Assert.Fail($"Expected 2 parameter, but get {expectedParameters.Count}"); + if (result.parameters.Count != 2) + Assert.Fail($"Expected 2 parameter, but get {expectedParameters.Count}"); - if (!result.parameters.ContainsKey("1")) - Assert.Fail("Expected parameter 1 not found"); + if (!result.parameters.ContainsKey("1")) + Assert.Fail("Expected parameter 1 not found"); - if (!result.parameters.ContainsKey("2")) - Assert.Fail("Expected parameter 2 not found"); + if (!result.parameters.ContainsKey("2")) + Assert.Fail("Expected parameter 2 not found"); - Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); + Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); - Assert.AreEqual(expectedParameters["2"].ToString(), result.parameters["2"].ToString()); - } + Assert.AreEqual(expectedParameters["2"].ToString(), result.parameters["2"].ToString()); + } - [TestMethod] - public void Should_return_select_single_column_from_table_where_one_string_column_and_one_number_column() - { - var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE (([Age] > @1) AND ([LastName] = @2))"; - Dictionary expectedParameters = new() { { "1", 20 }, { "2", "Farahmandian" } }; + [TestMethod] + public void Should_return_select_single_column_from_table_where_one_string_column_and_one_number_column() + { + var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE (([Age] > @1) AND ([LastName] = @2))"; + Dictionary expectedParameters = new() { { "1", 20 }, { "2", "Farahmandian" } }; - var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => x.Age > 20 && x.LastName == "Farahmandian").ToSql(); + var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => x.Age > 20 && x.LastName == "Farahmandian").ToSql(); - Assert.AreEqual(expectedQuery, result.query.ToString()); + Assert.AreEqual(expectedQuery, result.query.ToString()); - Assert.IsNotNull(expectedParameters); + Assert.IsNotNull(expectedParameters); - if (result.parameters.Count != 2) - Assert.Fail($"Expected 2 parameter, but get {expectedParameters.Count}"); + if (result.parameters.Count != 2) + Assert.Fail($"Expected 2 parameter, but get {expectedParameters.Count}"); - if (!result.parameters.ContainsKey("1")) - Assert.Fail("Expected parameter 1 not found"); + if (!result.parameters.ContainsKey("1")) + Assert.Fail("Expected parameter 1 not found"); - if (!result.parameters.ContainsKey("2")) - Assert.Fail("Expected parameter 2 not found"); + if (!result.parameters.ContainsKey("2")) + Assert.Fail("Expected parameter 2 not found"); - Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); + Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); - Assert.AreEqual(expectedParameters["2"].ToString(), result.parameters["2"].ToString()); - } + Assert.AreEqual(expectedParameters["2"].ToString(), result.parameters["2"].ToString()); + } - #endregion + #endregion - #region WHERE OR + #region WHERE OR - [TestMethod] - public void Should_return_select_single_column_from_table_where_two_string_columns_or() - { - var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE (([FirstName] = @1) OR ([LastName] = @2))"; - Dictionary expectedParameters = new() { { "1", "Vahid" }, { "2", "Farahmandian" } }; + [TestMethod] + public void Should_return_select_single_column_from_table_where_two_string_columns_or() + { + var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE (([FirstName] = @1) OR ([LastName] = @2))"; + Dictionary expectedParameters = new() { { "1", "Vahid" }, { "2", "Farahmandian" } }; - var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => x.FirstName == "Vahid" || x.LastName == "Farahmandian").ToSql(); + var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => x.FirstName == "Vahid" || x.LastName == "Farahmandian").ToSql(); - Assert.AreEqual(expectedQuery, result.query.ToString()); + Assert.AreEqual(expectedQuery, result.query.ToString()); - Assert.IsNotNull(expectedParameters); + Assert.IsNotNull(expectedParameters); - if (result.parameters.Count != 2) - Assert.Fail($"Expected 2 parameter, but get {expectedParameters.Count}"); + if (result.parameters.Count != 2) + Assert.Fail($"Expected 2 parameter, but get {expectedParameters.Count}"); - if (!result.parameters.ContainsKey("1")) - Assert.Fail("Expected parameter 1 not found"); + if (!result.parameters.ContainsKey("1")) + Assert.Fail("Expected parameter 1 not found"); - if (!result.parameters.ContainsKey("2")) - Assert.Fail("Expected parameter 2 not found"); + if (!result.parameters.ContainsKey("2")) + Assert.Fail("Expected parameter 2 not found"); - Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); + Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); - Assert.AreEqual(expectedParameters["2"].ToString(), result.parameters["2"].ToString()); - } + Assert.AreEqual(expectedParameters["2"].ToString(), result.parameters["2"].ToString()); + } - public string SampleProperty { get; set; } - [TestMethod] - public void Should_return_select_single_column_from_table_where_two_string_columns_equal_to_field_and_property_value() - { - string sampleField = "testFieldValue"; - SampleProperty = "testPropertyValue"; - var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE (([FirstName] = @1) OR ([LastName] = @2))"; - Dictionary expectedParameters = new() { { "1", "testFieldValue" }, { "2", "testPropertyValue" } }; + public string SampleProperty { get; set; } + [TestMethod] + public void Should_return_select_single_column_from_table_where_two_string_columns_equal_to_field_and_property_value() + { + string sampleField = "testFieldValue"; + SampleProperty = "testPropertyValue"; + var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE (([FirstName] = @1) OR ([LastName] = @2))"; + Dictionary expectedParameters = new() { { "1", "testFieldValue" }, { "2", "testPropertyValue" } }; - var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => x.FirstName == sampleField || x.LastName == SampleProperty).ToSql(); + var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => x.FirstName == sampleField || x.LastName == SampleProperty).ToSql(); - Assert.AreEqual(expectedQuery, result.query.ToString()); + Assert.AreEqual(expectedQuery, result.query.ToString()); - Assert.IsNotNull(expectedParameters); + Assert.IsNotNull(expectedParameters); - if (result.parameters.Count != 2) - Assert.Fail($"Expected 1 parameter, but get {expectedParameters.Count}"); + if (result.parameters.Count != 2) + Assert.Fail($"Expected 1 parameter, but get {expectedParameters.Count}"); - if (!result.parameters.ContainsKey("1")) - Assert.Fail("Expected parameter 1 not found"); + if (!result.parameters.ContainsKey("1")) + Assert.Fail("Expected parameter 1 not found"); - Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); - } + Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); + } - #endregion + #endregion - #region AND OR + #region AND OR - [TestMethod] - public void Should_return_select_single_column_from_table_where_two_char_columns_and_or() - { - var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE ((([FirstName] = @1) OR ([LastName] = @2)) AND (([LastName] = @3) OR ([FirstName] = @4)))"; - Dictionary expectedParameters = new() { { "1", "Vahid" }, { "2", "Farahmandian" }, { "3", "Vahid" }, { "4", "Farahmandian" } }; + [TestMethod] + public void Should_return_select_single_column_from_table_where_two_char_columns_and_or() + { + var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE ((([FirstName] = @1) OR ([LastName] = @2)) AND (([LastName] = @3) OR ([FirstName] = @4)))"; + Dictionary expectedParameters = new() { { "1", "Vahid" }, { "2", "Farahmandian" }, { "3", "Vahid" }, { "4", "Farahmandian" } }; - var result = Sql.Select(x => new { x.Id }, "tblTest") - .Where(x => (x.FirstName == "Vahid" || x.LastName == "Farahmandian") && (x.LastName == "Vahid" || x.FirstName == "Farahmandian")).ToSql(); + var result = Sql.Select(x => new { x.Id }, "tblTest") + .Where(x => (x.FirstName == "Vahid" || x.LastName == "Farahmandian") && (x.LastName == "Vahid" || x.FirstName == "Farahmandian")).ToSql(); - Assert.AreEqual(expectedQuery, result.query.ToString()); + Assert.AreEqual(expectedQuery, result.query.ToString()); - Assert.IsNotNull(expectedParameters); + Assert.IsNotNull(expectedParameters); - if (result.parameters.Count != 4) - Assert.Fail($"Expected 4 parameter, but get {expectedParameters.Count}"); + if (result.parameters.Count != 4) + Assert.Fail($"Expected 4 parameter, but get {expectedParameters.Count}"); - if (!result.parameters.ContainsKey("1")) - Assert.Fail("Expected parameter 1 not found"); + if (!result.parameters.ContainsKey("1")) + Assert.Fail("Expected parameter 1 not found"); - if (!result.parameters.ContainsKey("2")) - Assert.Fail("Expected parameter 2 not found"); + if (!result.parameters.ContainsKey("2")) + Assert.Fail("Expected parameter 2 not found"); - if (!result.parameters.ContainsKey("3")) - Assert.Fail("Expected parameter 3 not found"); + if (!result.parameters.ContainsKey("3")) + Assert.Fail("Expected parameter 3 not found"); - if (!result.parameters.ContainsKey("4")) - Assert.Fail("Expected parameter 4 not found"); + if (!result.parameters.ContainsKey("4")) + Assert.Fail("Expected parameter 4 not found"); - Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); + Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); - Assert.AreEqual(expectedParameters["2"].ToString(), result.parameters["2"].ToString()); + Assert.AreEqual(expectedParameters["2"].ToString(), result.parameters["2"].ToString()); - Assert.AreEqual(expectedParameters["3"].ToString(), result.parameters["3"].ToString()); + Assert.AreEqual(expectedParameters["3"].ToString(), result.parameters["3"].ToString()); - Assert.AreEqual(expectedParameters["4"].ToString(), result.parameters["4"].ToString()); - } + Assert.AreEqual(expectedParameters["4"].ToString(), result.parameters["4"].ToString()); + } - #endregion + #endregion - #region WHERE CAST + #region WHERE CAST - [TestMethod] - public void Should_return_select_single_column_from_table_where_cast_convert_tostring() - { - var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE (CAST(FirstName AS NVARCHAR(MAX)) = @1)"; - Dictionary expectedParameters = new() { { "1", "vahid" } }; + [TestMethod] + public void Should_return_select_single_column_from_table_where_cast_convert_tostring() + { + var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE (CAST(FirstName AS NVARCHAR(MAX)) = @1)"; + Dictionary expectedParameters = new() { { "1", "vahid" } }; - var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => Convert.ToString(x.FirstName) == "Vahid".ToLower()).ToSql(); + var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => Convert.ToString(x.FirstName) == "Vahid".ToLower()).ToSql(); - Assert.AreEqual(expectedQuery, result.query.ToString()); + Assert.AreEqual(expectedQuery, result.query.ToString()); - Assert.IsNotNull(expectedParameters); + Assert.IsNotNull(expectedParameters); - if (result.parameters.Count != 1) - Assert.Fail($"Expected 1 parameter, but get {expectedParameters.Count}"); + if (result.parameters.Count != 1) + Assert.Fail($"Expected 1 parameter, but get {expectedParameters.Count}"); - if (!result.parameters.ContainsKey("1")) - Assert.Fail("Expected parameter 1 not found"); + if (!result.parameters.ContainsKey("1")) + Assert.Fail("Expected parameter 1 not found"); - Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); - } + Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); + } - [TestMethod] - public void Should_return_select_single_column_from_table_where_cast_tostring() - { - var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE (CAST(Id AS NVARCHAR(MAX)) = @1)"; - Dictionary expectedParameters = new() { { "1", "Vahid" } }; + [TestMethod] + public void Should_return_select_single_column_from_table_where_cast_tostring() + { + var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE (CAST(Id AS NVARCHAR(MAX)) = @1)"; + Dictionary expectedParameters = new() { { "1", "Vahid" } }; - var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => x.Id.ToString() == "Vahid").ToSql(); + var result = Sql.Select(x => new { x.Id }, "tblTest").Where(x => x.Id.ToString() == "Vahid").ToSql(); - Assert.AreEqual(expectedQuery, result.query.ToString()); + Assert.AreEqual(expectedQuery, result.query.ToString()); - Assert.IsNotNull(expectedParameters); + Assert.IsNotNull(expectedParameters); - if (result.parameters.Count != 1) - Assert.Fail($"Expected 1 parameter, but get {expectedParameters.Count}"); + if (result.parameters.Count != 1) + Assert.Fail($"Expected 1 parameter, but get {expectedParameters.Count}"); - if (!result.parameters.ContainsKey("1")) - Assert.Fail("Expected parameter 1 not found"); + if (!result.parameters.ContainsKey("1")) + Assert.Fail("Expected parameter 1 not found"); - Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); - } + Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); + } - #endregion + #endregion - #region WHERE UPPER & LOWER + #region WHERE UPPER & LOWER - [TestMethod] - public void Should_return_select_single_column_from_table_where_upper() - { - var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE ((UPPER(FirstName) = @1) AND (LOWER(LastName) = @2))"; - Dictionary expectedParameters = new() { { "1", "Vahid" }, { "2", "farahmandian" } }; + [TestMethod] + public void Should_return_select_single_column_from_table_where_upper() + { + var expectedQuery = "SELECT a.[Id] FROM [dbo].[tblTest] AS a WHERE ((UPPER(FirstName) = @1) AND (LOWER(LastName) = @2))"; + Dictionary expectedParameters = new() { { "1", "Vahid" }, { "2", "farahmandian" } }; - var result = Sql.Select(x => new { x.Id }, "tblTest") - .Where(x => x.FirstName.ToUpper() == "Vahid" && x.LastName.ToLower() == "farahmandian").ToSql(); + var result = Sql.Select(x => new { x.Id }, "tblTest") + .Where(x => x.FirstName.ToUpper() == "Vahid" && x.LastName.ToLower() == "farahmandian").ToSql(); - Assert.AreEqual(expectedQuery, result.query.ToString()); + Assert.AreEqual(expectedQuery, result.query.ToString()); - Assert.IsNotNull(expectedParameters); + Assert.IsNotNull(expectedParameters); - if (result.parameters.Count != 2) - Assert.Fail($"Expected 1 parameter, but get {expectedParameters.Count}"); + if (result.parameters.Count != 2) + Assert.Fail($"Expected 1 parameter, but get {expectedParameters.Count}"); - if (!result.parameters.ContainsKey("1")) - Assert.Fail("Expected parameter 1 not found"); + if (!result.parameters.ContainsKey("1")) + Assert.Fail("Expected parameter 1 not found"); - if (!result.parameters.ContainsKey("2")) - Assert.Fail("Expected parameter 2 not found"); + if (!result.parameters.ContainsKey("2")) + Assert.Fail("Expected parameter 2 not found"); - Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); - Assert.AreEqual(expectedParameters["2"].ToString(), result.parameters["2"].ToString()); + Assert.AreEqual(expectedParameters["1"].ToString(), result.parameters["1"].ToString()); + Assert.AreEqual(expectedParameters["2"].ToString(), result.parameters["2"].ToString()); - } + } - #endregion + #endregion - #endregion - } + #endregion } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/ExtensionMethods/Collections/IDictionaryExtensionsTests.cs b/Tests/Jinget.Core.Tests/ExtensionMethods/Collections/IDictionaryExtensionsTests.cs index 94318af..0c4a7f7 100644 --- a/Tests/Jinget.Core.Tests/ExtensionMethods/Collections/IDictionaryExtensionsTests.cs +++ b/Tests/Jinget.Core.Tests/ExtensionMethods/Collections/IDictionaryExtensionsTests.cs @@ -3,73 +3,72 @@ using System.Linq; using Jinget.Core.ExtensionMethods.Collections; -namespace Jinget.Core.Tests.ExtensionMethods.Collections +namespace Jinget.Core.Tests.ExtensionMethods.Collections; + +[TestClass()] +public class IDictionaryExtensionsTests { - [TestClass()] - public class IDictionaryExtensionsTests - { - public IDictionary First { get; private set; } - public IDictionary Second { get; private set; } + public IDictionary First { get; private set; } + public IDictionary Second { get; private set; } - [TestInitialize()] - public void Initialize() + [TestInitialize()] + public void Initialize() + { + First = new Dictionary() { - First = new Dictionary() - { - { "name", "vahid" }, - { "lastname", "farahmandian" } - }; + { "name", "vahid" }, + { "lastname", "farahmandian" } + }; - Second = new Dictionary() - { - { "gender", "male" }, - { "name", "alex" }, - { "country", "Iran" } - }; - } + Second = new Dictionary() + { + { "gender", "male" }, + { "name", "alex" }, + { "country", "Iran" } + }; + } - [TestMethod()] - public void Should_merge_two_dictionaries_and_ignore_duplicates() + [TestMethod()] + public void Should_merge_two_dictionaries_and_ignore_duplicates() + { + Dictionary expected = new() { - Dictionary expected = new() - { - { "name", "vahid" }, - { "lastname", "farahmandian" }, - { "gender", "male" }, - { "country", "Iran" } - }; - - var result = First.Merge(Second); + { "name", "vahid" }, + { "lastname", "farahmandian" }, + { "gender", "male" }, + { "country", "Iran" } + }; + + var result = First.Merge(Second); - Assert.IsFalse(result.Keys.Except(expected.Keys).Any()); - Assert.IsFalse(expected.Keys.Except(result.Keys).Any()); + Assert.IsFalse(result.Keys.Except(expected.Keys).Any()); + Assert.IsFalse(expected.Keys.Except(result.Keys).Any()); - Assert.IsTrue(expected.Keys.SequenceEqual(result.Keys)); - Assert.IsTrue(expected.Values.SequenceEqual(result.Values)); + Assert.IsTrue(expected.Keys.SequenceEqual(result.Keys)); + Assert.IsTrue(expected.Values.SequenceEqual(result.Values)); - Assert.IsTrue(result["name"] == "vahid"); - } + Assert.IsTrue(result["name"] == "vahid"); + } - [TestMethod()] - public void Should_merge_two_dictionaries_and_overwrite_the_duplicates() + [TestMethod()] + public void Should_merge_two_dictionaries_and_overwrite_the_duplicates() + { + Dictionary expected = new() { - Dictionary expected = new() - { - { "name", "alex" }, - { "lastname", "farahmandian" }, - { "gender", "male" }, - { "country", "Iran" } - }; + { "name", "alex" }, + { "lastname", "farahmandian" }, + { "gender", "male" }, + { "country", "Iran" } + }; - var result = First.Merge(Second, overwrite: true); + var result = First.Merge(Second, overwrite: true); - Assert.IsFalse(result.Keys.Except(expected.Keys).Any()); - Assert.IsFalse(expected.Keys.Except(result.Keys).Any()); + Assert.IsFalse(result.Keys.Except(expected.Keys).Any()); + Assert.IsFalse(expected.Keys.Except(result.Keys).Any()); - Assert.IsTrue(expected.Keys.SequenceEqual(result.Keys)); - Assert.IsTrue(expected.Values.SequenceEqual(result.Values)); - - Assert.IsTrue(result["name"] == "alex"); - } + Assert.IsTrue(expected.Keys.SequenceEqual(result.Keys)); + Assert.IsTrue(expected.Values.SequenceEqual(result.Values)); + + Assert.IsTrue(result["name"] == "alex"); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/ExtensionMethods/Collections/IQueryableExtensionsTests.cs b/Tests/Jinget.Core.Tests/ExtensionMethods/Collections/IQueryableExtensionsTests.cs index ce63d28..00221fe 100644 --- a/Tests/Jinget.Core.Tests/ExtensionMethods/Collections/IQueryableExtensionsTests.cs +++ b/Tests/Jinget.Core.Tests/ExtensionMethods/Collections/IQueryableExtensionsTests.cs @@ -7,97 +7,96 @@ using Jinget.Core.ExtensionMethods.Collections; using static Jinget.Core.Tests._BaseData.TestClass; -namespace Jinget.Core.ExtensionMethods.Tests +namespace Jinget.Core.ExtensionMethods.Tests; + +[TestClass()] +public class IQueryableExtensionsTests { - [TestClass()] - public class IQueryableExtensionsTests + [TestMethod()] + public void Should_sort_the_list_based_on_given_property() { - [TestMethod()] - public void Should_sort_the_list_based_on_given_property() - { - TestClass class1 = new() { Property1 = 1, Property2 = "C" }; - TestClass class2 = new() { Property1 = 2, Property2 = "A" }; - TestClass class3 = new() { Property1 = 3, Property2 = "B" }; + TestClass class1 = new() { Property1 = 1, Property2 = "C" }; + TestClass class2 = new() { Property1 = 2, Property2 = "A" }; + TestClass class3 = new() { Property1 = 3, Property2 = "B" }; - var input = new List() { class1, class2, class3 }.AsQueryable(); - var expected = new List() { class1, class3, class2 }.AsQueryable(); + var input = new List() { class1, class2, class3 }.AsQueryable(); + var expected = new List() { class1, class3, class2 }.AsQueryable(); - var result = input.OrderByDynamic("Property2", OrderByDirection.Descending); + var result = input.OrderByDynamic("Property2", OrderByDirection.Descending); - Assert.IsTrue(expected.SequenceEqual(result)); - } + Assert.IsTrue(expected.SequenceEqual(result)); + } - [TestMethod()] - public void Should_sort_the_nested_member_based_on_given_property() - { - TestClass parent1 = new() { Property1 = 1, Property2 = "C", InnerSingularProperty = new() { InnerProperty1 = 10, InnerProperty2 = "CC" } }; - TestClass parent2 = new() { Property1 = 2, Property2 = "A", InnerSingularProperty = new() { InnerProperty1 = 20, InnerProperty2 = "AA" } }; - TestClass parent3 = new() { Property1 = 3, Property2 = "B", InnerSingularProperty = new() { InnerProperty1 = 30, InnerProperty2 = "BB" } }; + [TestMethod()] + public void Should_sort_the_nested_member_based_on_given_property() + { + TestClass parent1 = new() { Property1 = 1, Property2 = "C", InnerSingularProperty = new() { InnerProperty1 = 10, InnerProperty2 = "CC" } }; + TestClass parent2 = new() { Property1 = 2, Property2 = "A", InnerSingularProperty = new() { InnerProperty1 = 20, InnerProperty2 = "AA" } }; + TestClass parent3 = new() { Property1 = 3, Property2 = "B", InnerSingularProperty = new() { InnerProperty1 = 30, InnerProperty2 = "BB" } }; - var input = new List() { parent1, parent2, parent3 }.AsQueryable(); - var expected = new List() { parent3, parent2, parent1 }.AsQueryable(); + var input = new List() { parent1, parent2, parent3 }.AsQueryable(); + var expected = new List() { parent3, parent2, parent1 }.AsQueryable(); - var result = input.OrderByDynamic("InnerSingularProperty.InnerProperty1", OrderByDirection.Descending); + var result = input.OrderByDynamic("InnerSingularProperty.InnerProperty1", OrderByDirection.Descending); - Assert.IsTrue(expected.SequenceEqual(result)); - } + Assert.IsTrue(expected.SequenceEqual(result)); + } - [TestMethod()] - public void Should_sort_the_nested_list_based_on_given_property() - { - InnerClass child1 = new() { InnerProperty1 = 10, InnerProperty2 = "AA" }; - InnerClass child2 = new() { InnerProperty1 = 11, InnerProperty2 = "BB" }; - InnerClass child3 = new() { InnerProperty1 = 12, InnerProperty2 = "CC" }; - - TestClass parent1 = new() { Property1 = 1, Property2 = "A", InnerProperty = new List { child3, child2, child1 } }; - TestClass parent2 = new() { Property1 = 2, Property2 = "B", InnerProperty = new List { child2, child1, child3 } }; - TestClass parent3 = new() { Property1 = 3, Property2 = "C", InnerProperty = new List { child1, child2, child3 } }; - - var input = new List() { parent1, parent2, parent3 }.AsQueryable(); - var expectedParents = new List() { parent3, parent2, parent1 }.AsQueryable(); - var expectedChildren = new List() { child1, child2, child3 }.AsQueryable(); - - var result = input.AsQueryable().OrderByDynamic("Property1", OrderByDirection.Descending) - .Select(x => new TestClass - { - Property1 = x.Property1, - Property2 = x.Property2, - InnerProperty = x.InnerProperty.AsQueryable().OrderByDynamic("InnerProperty1", OrderByDirection.Ascending).ToList() - }); - - Assert.IsTrue(expectedParents.Select(x => new { x.Property1, x.Property2 }).SequenceEqual(result.Select(x => new { x.Property1, x.Property2 }))); - foreach (var item in result) - { - Assert.IsTrue(expectedChildren.SequenceEqual(item.InnerProperty)); - } - } + [TestMethod()] + public void Should_sort_the_nested_list_based_on_given_property() + { + InnerClass child1 = new() { InnerProperty1 = 10, InnerProperty2 = "AA" }; + InnerClass child2 = new() { InnerProperty1 = 11, InnerProperty2 = "BB" }; + InnerClass child3 = new() { InnerProperty1 = 12, InnerProperty2 = "CC" }; - [TestMethod()] - public void Should_return_empty_collection_when_collection_is_empty() - { - var input = new List().AsQueryable(); - var expected = new List().AsQueryable(); + TestClass parent1 = new() { Property1 = 1, Property2 = "A", InnerProperty = new List { child3, child2, child1 } }; + TestClass parent2 = new() { Property1 = 2, Property2 = "B", InnerProperty = new List { child2, child1, child3 } }; + TestClass parent3 = new() { Property1 = 3, Property2 = "C", InnerProperty = new List { child1, child2, child3 } }; - var result = input.OrderByDynamic("", OrderByDirection.Descending); + var input = new List() { parent1, parent2, parent3 }.AsQueryable(); + var expectedParents = new List() { parent3, parent2, parent1 }.AsQueryable(); + var expectedChildren = new List() { child1, child2, child3 }.AsQueryable(); - Assert.IsTrue(expected.SequenceEqual(result)); - } + var result = input.AsQueryable().OrderByDynamic("Property1", OrderByDirection.Descending) + .Select(x => new TestClass + { + Property1 = x.Property1, + Property2 = x.Property2, + InnerProperty = x.InnerProperty.AsQueryable().OrderByDynamic("InnerProperty1", OrderByDirection.Ascending).ToList() + }); - [TestMethod()] - [ExpectedException(typeof(ArgumentException))] - public void Should_throw_ArgumentException_when_property_name_is_invalid() + Assert.IsTrue(expectedParents.Select(x => new { x.Property1, x.Property2 }).SequenceEqual(result.Select(x => new { x.Property1, x.Property2 }))); + foreach (var item in result) { - TestClass class1 = new() { Property1 = 1, Property2 = "C" }; - var input = new List() { class1 }.AsQueryable(); - input.OrderByDynamic("PropertyXYZ", OrderByDirection.Descending); + Assert.IsTrue(expectedChildren.SequenceEqual(item.InnerProperty)); } + } - [TestMethod()] - [ExpectedException(typeof(NullReferenceException))] - public void Should_throw_NullReferenceException_when_collection_is_null() - { - IQueryable input = null; - input.OrderByDynamic("", OrderByDirection.Descending); - } + [TestMethod()] + public void Should_return_empty_collection_when_collection_is_empty() + { + var input = new List().AsQueryable(); + var expected = new List().AsQueryable(); + + var result = input.OrderByDynamic("", OrderByDirection.Descending); + + Assert.IsTrue(expected.SequenceEqual(result)); + } + + [TestMethod()] + [ExpectedException(typeof(ArgumentException))] + public void Should_throw_ArgumentException_when_property_name_is_invalid() + { + TestClass class1 = new() { Property1 = 1, Property2 = "C" }; + var input = new List() { class1 }.AsQueryable(); + input.OrderByDynamic("PropertyXYZ", OrderByDirection.Descending); + } + + [TestMethod()] + [ExpectedException(typeof(NullReferenceException))] + public void Should_throw_NullReferenceException_when_collection_is_null() + { + IQueryable input = null; + input.OrderByDynamic("", OrderByDirection.Descending); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/ExtensionMethods/Dapper/DynamicParametersExtensionsTests.cs b/Tests/Jinget.Core.Tests/ExtensionMethods/Dapper/DynamicParametersExtensionsTests.cs index d695a98..35a8c48 100644 --- a/Tests/Jinget.Core.Tests/ExtensionMethods/Dapper/DynamicParametersExtensionsTests.cs +++ b/Tests/Jinget.Core.Tests/ExtensionMethods/Dapper/DynamicParametersExtensionsTests.cs @@ -2,44 +2,43 @@ using System.Collections.Generic; using Dapper; -namespace Jinget.Core.ExtensionMethods.Dapper.Tests +namespace Jinget.Core.ExtensionMethods.Dapper.Tests; + +[TestClass()] +public class DynamicParametersExtensionsTests { - [TestClass()] - public class DynamicParametersExtensionsTests + [TestMethod()] + public void should_get_key_value_pairs_for_dynamicparameter() { - [TestMethod()] - public void should_get_key_value_pairs_for_dynamicparameter() - { - DynamicParameters parameters = new(); - parameters.Add("persianName", "وحید", System.Data.DbType.String); - parameters.Add("englishName", "vahid", System.Data.DbType.AnsiString); - parameters.Add("sampleNumber", 123, System.Data.DbType.Int32); - parameters.Add("sampleBool", true, System.Data.DbType.Boolean); + DynamicParameters parameters = new(); + parameters.Add("persianName", "وحید", System.Data.DbType.String); + parameters.Add("englishName", "vahid", System.Data.DbType.AnsiString); + parameters.Add("sampleNumber", 123, System.Data.DbType.Int32); + parameters.Add("sampleBool", true, System.Data.DbType.Boolean); - var result = parameters.GetKeyValues(); + var result = parameters.GetKeyValues(); - Assert.IsTrue(result.Count == 4); - Assert.IsTrue(result.GetValueOrDefault("persianName") == "وحید"); - Assert.IsTrue(result.GetValueOrDefault("englishName") == "vahid"); - Assert.IsTrue(result.GetValueOrDefault("sampleNumber") == 123); - Assert.IsTrue(result.GetValueOrDefault("sampleBool") == true); - } + Assert.IsTrue(result.Count == 4); + Assert.IsTrue(result.GetValueOrDefault("persianName") == "وحید"); + Assert.IsTrue(result.GetValueOrDefault("englishName") == "vahid"); + Assert.IsTrue(result.GetValueOrDefault("sampleNumber") == 123); + Assert.IsTrue(result.GetValueOrDefault("sampleBool") == true); + } - [TestMethod()] - public void should_convert_values_to_sql_values() - { - DynamicParameters parameters = new(); - parameters.Add("persianName", "وحید", System.Data.DbType.String); - parameters.Add("englishName", "vahid", System.Data.DbType.AnsiString); - parameters.Add("sampleNumber", 123, System.Data.DbType.Int32); - parameters.Add("sampleBool", true, System.Data.DbType.Boolean); - var result = parameters.GetSQLValues(); + [TestMethod()] + public void should_convert_values_to_sql_values() + { + DynamicParameters parameters = new(); + parameters.Add("persianName", "وحید", System.Data.DbType.String); + parameters.Add("englishName", "vahid", System.Data.DbType.AnsiString); + parameters.Add("sampleNumber", 123, System.Data.DbType.Int32); + parameters.Add("sampleBool", true, System.Data.DbType.Boolean); + var result = parameters.GetSQLValues(); - Assert.IsTrue(result.Count == 4); - Assert.IsTrue(result[0] == "N'وحید'"); - Assert.IsTrue(result[1] == "'vahid'"); - Assert.IsTrue(result[2] == 123); - Assert.IsTrue(result[3] == 1); - } + Assert.IsTrue(result.Count == 4); + Assert.IsTrue(result[0] == "N'وحید'"); + Assert.IsTrue(result[1] == "'vahid'"); + Assert.IsTrue(result[2] == 123); + Assert.IsTrue(result[3] == 1); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/ExtensionMethods/Database/SqlClient/IDbCommandExtensionsTests.cs b/Tests/Jinget.Core.Tests/ExtensionMethods/Database/SqlClient/IDbCommandExtensionsTests.cs index c1b7b99..fcc3ce1 100644 --- a/Tests/Jinget.Core.Tests/ExtensionMethods/Database/SqlClient/IDbCommandExtensionsTests.cs +++ b/Tests/Jinget.Core.Tests/ExtensionMethods/Database/SqlClient/IDbCommandExtensionsTests.cs @@ -4,36 +4,35 @@ using System.Data.SqlClient; using System; -namespace Jinget.Core.Tests.ExtensionMethods.Database.SqlClient +namespace Jinget.Core.Tests.ExtensionMethods.Database.SqlClient; + +[TestClass] +public class IDbCommandExtensionsTests { - [TestClass] - public class IDbCommandExtensionsTests + [TestMethod()] + public void should_replace_arabic_YeKe_in_sqlcommand_with_its_farsi_equalivants() { - [TestMethod()] - public void should_replace_arabic_YeKe_in_sqlcommand_with_its_farsi_equalivants() + IDbCommand command = new SqlCommand { - IDbCommand command = new SqlCommand - { - CommandText = "SELECT * FROM dbo.Users Where (Username = N'علي' OR Username = N'روشنك' OR UserName = @p1 OR UserName = @p2) AND UserName <> @p3" - }; + CommandText = "SELECT * FROM dbo.Users Where (Username = N'علي' OR Username = N'روشنك' OR UserName = @p1 OR UserName = @p2) AND UserName <> @p3" + }; - command.Parameters.Add(new SqlParameter("@p1", "N'رهي'")); - command.Parameters.Add(new SqlParameter("@p2", "N'قاصدك'")); - command.Parameters.Add(new SqlParameter("@p3", DBNull.Value)); + command.Parameters.Add(new SqlParameter("@p1", "N'رهي'")); + command.Parameters.Add(new SqlParameter("@p2", "N'قاصدك'")); + command.Parameters.Add(new SqlParameter("@p3", DBNull.Value)); - command.ApplyCorrectYeKe(); + command.ApplyCorrectYeKe(); - Assert.IsFalse(command.CommandText.Contains("علي")); - Assert.IsTrue(command.CommandText.Contains("علی")); + Assert.IsFalse(command.CommandText.Contains("علي")); + Assert.IsTrue(command.CommandText.Contains("علی")); - Assert.IsFalse(command.CommandText.Contains("روشنك")); - Assert.IsTrue(command.CommandText.Contains("روشنک")); + Assert.IsFalse(command.CommandText.Contains("روشنك")); + Assert.IsTrue(command.CommandText.Contains("روشنک")); - Assert.IsFalse(((SqlParameter)command.Parameters["@p1"]).Value.ToString() == "N'رهي'"); - Assert.IsTrue(((SqlParameter)command.Parameters["@p1"]).Value.ToString() == "N'رهی'"); + Assert.IsFalse(((SqlParameter)command.Parameters["@p1"]).Value.ToString() == "N'رهي'"); + Assert.IsTrue(((SqlParameter)command.Parameters["@p1"]).Value.ToString() == "N'رهی'"); - Assert.IsFalse(((SqlParameter)command.Parameters["@p2"]).Value.ToString() == "N'قاصدك'"); - Assert.IsTrue(((SqlParameter)command.Parameters["@p2"]).Value.ToString() == "N'قاصدک'"); - } + Assert.IsFalse(((SqlParameter)command.Parameters["@p2"]).Value.ToString() == "N'قاصدك'"); + Assert.IsTrue(((SqlParameter)command.Parameters["@p2"]).Value.ToString() == "N'قاصدک'"); } } diff --git a/Tests/Jinget.Core.Tests/ExtensionMethods/Database/SqlClient/IDbConnectionExtensionsTests.cs b/Tests/Jinget.Core.Tests/ExtensionMethods/Database/SqlClient/IDbConnectionExtensionsTests.cs index d614207..9265cd1 100644 --- a/Tests/Jinget.Core.Tests/ExtensionMethods/Database/SqlClient/IDbConnectionExtensionsTests.cs +++ b/Tests/Jinget.Core.Tests/ExtensionMethods/Database/SqlClient/IDbConnectionExtensionsTests.cs @@ -3,30 +3,29 @@ using System.Data; using Jinget.Core.ExtensionMethods.Database.SqlClient; -namespace Jinget.Core.Tests.ExtensionMethods.Database.SqlClient +namespace Jinget.Core.Tests.ExtensionMethods.Database.SqlClient; + +[TestClass] +public class IDbConnectionExtensionsTests { - [TestClass] - public class IDbConnectionExtensionsTests + Mock mockDbConnection; + [TestInitialize] + public void Initialize() { - Mock mockDbConnection; - [TestInitialize] - public void Initialize() - { - ConnectionState state = ConnectionState.Closed; + ConnectionState state = ConnectionState.Closed; - mockDbConnection = new Mock(); - mockDbConnection.Setup(x => x.Open()).Callback(() => { state = ConnectionState.Open; }); - mockDbConnection.Setup(x => x.Close()).Callback(() => { state = ConnectionState.Closed; }); - mockDbConnection.Setup(x => x.State).Returns(() => state); + mockDbConnection = new Mock(); + mockDbConnection.Setup(x => x.Open()).Callback(() => { state = ConnectionState.Open; }); + mockDbConnection.Setup(x => x.Close()).Callback(() => { state = ConnectionState.Closed; }); + mockDbConnection.Setup(x => x.State).Returns(() => state); - } - [TestMethod()] - public void Should_return_open_connection_status() - { - var cnn = mockDbConnection.Object; - cnn.SafeOpen(); - cnn.SafeOpen(); - Assert.IsTrue(cnn.State == ConnectionState.Open); - } + } + [TestMethod()] + public void Should_return_open_connection_status() + { + var cnn = mockDbConnection.Object; + cnn.SafeOpen(); + cnn.SafeOpen(); + Assert.IsTrue(cnn.State == ConnectionState.Open); } } diff --git a/Tests/Jinget.Core.Tests/ExtensionMethods/Enums/DbTypeExtensionsTests.cs b/Tests/Jinget.Core.Tests/ExtensionMethods/Enums/DbTypeExtensionsTests.cs index b95284d..3e29be3 100644 --- a/Tests/Jinget.Core.Tests/ExtensionMethods/Enums/DbTypeExtensionsTests.cs +++ b/Tests/Jinget.Core.Tests/ExtensionMethods/Enums/DbTypeExtensionsTests.cs @@ -2,34 +2,33 @@ using System.Data; using Jinget.Core.ExtensionMethods.Enums; -namespace Jinget.Core.Tests.ExtensionMethods.Enums +namespace Jinget.Core.Tests.ExtensionMethods.Enums; + +[TestClass()] +public class GenericTypeExtensionsTests { - [TestClass()] - public class GenericTypeExtensionsTests - { - - [TestMethod()] - public void Should_return_true_for_numeric_dbType() => Assert.IsTrue(DbType.Int32.IsNumericDbType()); + + [TestMethod()] + public void Should_return_true_for_numeric_dbType() => Assert.IsTrue(DbType.Int32.IsNumericDbType()); - [TestMethod()] - public void Should_return_false_for_non_numeric_dbType() => Assert.IsFalse(DbType.Binary.IsNumericDbType()); + [TestMethod()] + public void Should_return_false_for_non_numeric_dbType() => Assert.IsFalse(DbType.Binary.IsNumericDbType()); - [TestMethod()] - public void Should_return_true_for_unicode_dbType_IsUnicodeType() => Assert.IsTrue(DbType.String.IsUnicodeDbType()); + [TestMethod()] + public void Should_return_true_for_unicode_dbType_IsUnicodeType() => Assert.IsTrue(DbType.String.IsUnicodeDbType()); - [TestMethod()] - public void Should_return_false_for_non_unicode_dbType_IsUnicodeType() => Assert.IsFalse(DbType.AnsiString.IsUnicodeDbType()); + [TestMethod()] + public void Should_return_false_for_non_unicode_dbType_IsUnicodeType() => Assert.IsFalse(DbType.AnsiString.IsUnicodeDbType()); - [TestMethod()] - public void Should_return_false_for_non_unicode_dbType_IsNonUnicodeType() => Assert.IsFalse(DbType.String.IsNonUnicodeDbType()); + [TestMethod()] + public void Should_return_false_for_non_unicode_dbType_IsNonUnicodeType() => Assert.IsFalse(DbType.String.IsNonUnicodeDbType()); - [TestMethod()] - public void Should_return_true_for_non_unicode_dbType_IsNonUnicodeType() => Assert.IsTrue(DbType.AnsiString.IsNonUnicodeDbType()); + [TestMethod()] + public void Should_return_true_for_non_unicode_dbType_IsNonUnicodeType() => Assert.IsTrue(DbType.AnsiString.IsNonUnicodeDbType()); - [TestMethod()] - public void Should_return_false_for_non_bool_dbType_IsBooleanType() => Assert.IsTrue(DbType.Boolean.IsBooleanDbType()); + [TestMethod()] + public void Should_return_false_for_non_bool_dbType_IsBooleanType() => Assert.IsTrue(DbType.Boolean.IsBooleanDbType()); - [TestMethod()] - public void Should_return_true_for_bool_dbType_IsBooleanType() => Assert.IsTrue(DbType.Boolean.IsBooleanDbType()); - } + [TestMethod()] + public void Should_return_true_for_bool_dbType_IsBooleanType() => Assert.IsTrue(DbType.Boolean.IsBooleanDbType()); } diff --git a/Tests/Jinget.Core.Tests/ExtensionMethods/Enums/EnumExtensionsTests.cs b/Tests/Jinget.Core.Tests/ExtensionMethods/Enums/EnumExtensionsTests.cs index e3c99c7..8107ef5 100644 --- a/Tests/Jinget.Core.Tests/ExtensionMethods/Enums/EnumExtensionsTests.cs +++ b/Tests/Jinget.Core.Tests/ExtensionMethods/Enums/EnumExtensionsTests.cs @@ -6,153 +6,152 @@ using System.Linq; using static Jinget.Core.Tests._BaseData.SampleEnum; -namespace Jinget.Core.Tests.ExtensionMethods.Enums +namespace Jinget.Core.Tests.ExtensionMethods.Enums; + +[TestClass()] +public class EnumExtensionsTests { - [TestClass()] - public class EnumExtensionsTests + #region DisplayName + + [TestMethod()] + public void should_return_default_display_name() + { + ProgrammingLanguage langauge = default; + string expected = ""; + string result = langauge.GetDisplayName(); + + Assert.AreEqual(expected, result); + } + + [TestMethod()] + public void should_return_display_name_for_member_with_display_attribute() + { + ProgrammingLanguage langauge = ProgrammingLanguage.FSharp; + string expected = "F#"; + string result = langauge.GetDisplayName(); + + Assert.AreEqual(expected, result); + } + + [TestMethod()] + public void should_return_display_name_for_member_without_display_attribute() + { + ProgrammingLanguage langauge = ProgrammingLanguage.Golang; + string expected = "Golang"; + string result = langauge.GetDisplayName(); + + Assert.AreEqual(expected, result); + } + + [TestMethod()] + public void should_return_enum_value_where_display_name_provided() + { + string enumDisplayName = "C#"; + List expected = [ProgrammingLanguage.CSharp, ProgrammingLanguage.VB]; + + List result = EnumExtensions.GetValueFromDisplayName(enumDisplayName); + + Assert.IsTrue(expected.SequenceEqual(result)); + } + + [TestMethod()] + public void should_return_enum_value_where_display_name_not_provided() + { + string enumDisplayName = "Golang"; + List expected = [ProgrammingLanguage.Golang]; + + List result = EnumExtensions.GetValueFromDisplayName(enumDisplayName); + + Assert.IsTrue(expected.SequenceEqual(result)); + } + + [TestMethod()] + [ExpectedException(typeof(System.ComponentModel.InvalidEnumArgumentException))] + public void should_throw_exception_where_display_name_not_found() + { + string enumDescription = "Java"; + EnumExtensions.GetValueFromDisplayName(enumDescription); + } + + [TestMethod()] + [ExpectedException(typeof(InvalidOperationException))] + public void should_throw_exception_where_enum_type_is_invalid_in_display_name() + { + string enumDescription = "Java"; + EnumExtensions.GetValueFromDisplayName(enumDescription); + } + + #endregion + + #region Description + + [TestMethod()] + public void should_return_default_description() + { + ProgrammingLanguage langauge = default; + string expected = ""; + string result = langauge.GetDescription(); + + Assert.AreEqual(expected, result); + } + + [TestMethod()] + public void should_return_description_for_member_with_description_attribute() { - #region DisplayName - - [TestMethod()] - public void should_return_default_display_name() - { - ProgrammingLanguage langauge = default; - string expected = ""; - string result = langauge.GetDisplayName(); - - Assert.AreEqual(expected, result); - } - - [TestMethod()] - public void should_return_display_name_for_member_with_display_attribute() - { - ProgrammingLanguage langauge = ProgrammingLanguage.FSharp; - string expected = "F#"; - string result = langauge.GetDisplayName(); - - Assert.AreEqual(expected, result); - } - - [TestMethod()] - public void should_return_display_name_for_member_without_display_attribute() - { - ProgrammingLanguage langauge = ProgrammingLanguage.Golang; - string expected = "Golang"; - string result = langauge.GetDisplayName(); - - Assert.AreEqual(expected, result); - } - - [TestMethod()] - public void should_return_enum_value_where_display_name_provided() - { - string enumDisplayName = "C#"; - List expected = [ProgrammingLanguage.CSharp, ProgrammingLanguage.VB]; - - List result = EnumExtensions.GetValueFromDisplayName(enumDisplayName); - - Assert.IsTrue(expected.SequenceEqual(result)); - } - - [TestMethod()] - public void should_return_enum_value_where_display_name_not_provided() - { - string enumDisplayName = "Golang"; - List expected = [ProgrammingLanguage.Golang]; - - List result = EnumExtensions.GetValueFromDisplayName(enumDisplayName); - - Assert.IsTrue(expected.SequenceEqual(result)); - } - - [TestMethod()] - [ExpectedException(typeof(System.ComponentModel.InvalidEnumArgumentException))] - public void should_throw_exception_where_display_name_not_found() - { - string enumDescription = "Java"; - EnumExtensions.GetValueFromDisplayName(enumDescription); - } - - [TestMethod()] - [ExpectedException(typeof(InvalidOperationException))] - public void should_throw_exception_where_enum_type_is_invalid_in_display_name() - { - string enumDescription = "Java"; - EnumExtensions.GetValueFromDisplayName(enumDescription); - } - - #endregion - - #region Description - - [TestMethod()] - public void should_return_default_description() - { - ProgrammingLanguage langauge = default; - string expected = ""; - string result = langauge.GetDescription(); - - Assert.AreEqual(expected, result); - } - - [TestMethod()] - public void should_return_description_for_member_with_description_attribute() - { - ProgrammingLanguage langauge = ProgrammingLanguage.FSharp; - string expected = "F#.Net"; - string result = langauge.GetDescription(); - - Assert.AreEqual(expected, result); - } - - [TestMethod()] - public void should_return_description_for_member_without_description_attribute() - { - ProgrammingLanguage langauge = ProgrammingLanguage.CSharp; - string expected = "CSharp"; - var result = langauge.GetDescription(); - - Assert.AreEqual(expected, result); - } - - [TestMethod()] - public void should_return_enum_value_where_description_provided() - { - string enumDescription = "F#.Net"; - ProgrammingLanguage expected = ProgrammingLanguage.FSharp; - - ProgrammingLanguage result = EnumExtensions.GetValueFromDescription(enumDescription); - - Assert.AreEqual(expected, result); - } - - [TestMethod()] - public void should_return_enum_value_where_description_not_provided() - { - string enumDescription = "VB"; - ProgrammingLanguage expected = ProgrammingLanguage.VB; - - ProgrammingLanguage result = EnumExtensions.GetValueFromDescription(enumDescription); - - Assert.AreEqual(expected, result); - } - - [TestMethod()] - [ExpectedException(typeof(System.ComponentModel.InvalidEnumArgumentException))] - public void should_throw_exception_where_description_not_found() - { - string enumDescription = "Java"; - EnumExtensions.GetValueFromDescription(enumDescription); - } - - [TestMethod()] - [ExpectedException(typeof(InvalidOperationException))] - public void should_throw_exception_where_enum_type_is_invalid_in_description() - { - string enumDescription = "Java"; - EnumExtensions.GetValueFromDescription(enumDescription); - } - - #endregion region + ProgrammingLanguage langauge = ProgrammingLanguage.FSharp; + string expected = "F#.Net"; + string result = langauge.GetDescription(); + + Assert.AreEqual(expected, result); } + + [TestMethod()] + public void should_return_description_for_member_without_description_attribute() + { + ProgrammingLanguage langauge = ProgrammingLanguage.CSharp; + string expected = "CSharp"; + var result = langauge.GetDescription(); + + Assert.AreEqual(expected, result); + } + + [TestMethod()] + public void should_return_enum_value_where_description_provided() + { + string enumDescription = "F#.Net"; + ProgrammingLanguage expected = ProgrammingLanguage.FSharp; + + ProgrammingLanguage result = EnumExtensions.GetValueFromDescription(enumDescription); + + Assert.AreEqual(expected, result); + } + + [TestMethod()] + public void should_return_enum_value_where_description_not_provided() + { + string enumDescription = "VB"; + ProgrammingLanguage expected = ProgrammingLanguage.VB; + + ProgrammingLanguage result = EnumExtensions.GetValueFromDescription(enumDescription); + + Assert.AreEqual(expected, result); + } + + [TestMethod()] + [ExpectedException(typeof(System.ComponentModel.InvalidEnumArgumentException))] + public void should_throw_exception_where_description_not_found() + { + string enumDescription = "Java"; + EnumExtensions.GetValueFromDescription(enumDescription); + } + + [TestMethod()] + [ExpectedException(typeof(InvalidOperationException))] + public void should_throw_exception_where_enum_type_is_invalid_in_description() + { + string enumDescription = "Java"; + EnumExtensions.GetValueFromDescription(enumDescription); + } + + #endregion region } diff --git a/Tests/Jinget.Core.Tests/ExtensionMethods/ExpressionToSql/OrderByExtensionsTests.cs b/Tests/Jinget.Core.Tests/ExtensionMethods/ExpressionToSql/OrderByExtensionsTests.cs index eac2a76..fa099e5 100644 --- a/Tests/Jinget.Core.Tests/ExtensionMethods/ExpressionToSql/OrderByExtensionsTests.cs +++ b/Tests/Jinget.Core.Tests/ExtensionMethods/ExpressionToSql/OrderByExtensionsTests.cs @@ -3,99 +3,98 @@ using Jinget.Core.Tests._BaseData; using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace Jinget.Core.ExtensionMethods.ExpressionToSql +namespace Jinget.Core.ExtensionMethods.ExpressionToSql; + +[TestClass()] +public class OrderByExtensionsTests { - [TestClass()] - public class OrderByExtensionsTests + [TestMethod()] + public void should_return_empty_string() + { + List lstOrderBy = null; + + var result = lstOrderBy.GetSorting(); + + Assert.IsTrue(string.IsNullOrWhiteSpace(result)); + } + + [TestMethod()] + public void should_return_stringfied_order_by_clause() + { + List lstOrderBy = + [ + new OrderBy + { + Name = x=>((TestClass)x).Property1, + Direction = Enumerations.OrderByDirection.Descending + }, + new OrderBy + { + Name = x=>((TestClass)x).Property2, + Direction = Enumerations.OrderByDirection.Ascending + } + ]; + + string expectedResult = "ORDER BY [Property1] DESC,[Property2] ASC"; + + var result = lstOrderBy.GetSorting(); + + Assert.AreEqual(expectedResult, result); + } + + [TestMethod()] + public void should_return_stringfied_order_by_clause_complex_type() + { + List lstOrderBy = + [ + new OrderBy + { + Name = x=>((TestClass)x).InnerSingularProperty.InnerProperty1, + Direction = Enumerations.OrderByDirection.Descending + } + ]; + + string expectedResult = "ORDER BY [InnerSingularProperty.InnerProperty1] DESC"; + + var result = lstOrderBy.GetSorting(); + + Assert.AreEqual(expectedResult, result); + } + + [TestMethod()] + public void should_return_stringfied_order_by_clause_stringfied_type_name() + { + List lstOrderBy = + [ + new OrderBy + { + Name = x=>"Property3", + Direction = Enumerations.OrderByDirection.Descending + } + ]; + + string expectedResult = "ORDER BY [Property3] DESC"; + + var result = lstOrderBy.GetSorting(); + + Assert.AreEqual(expectedResult, result); + } + + [TestMethod()] + public void should_return_stringfied_order_by_clause_using_string_name() { - [TestMethod()] - public void should_return_empty_string() - { - List lstOrderBy = null; - - var result = lstOrderBy.GetSorting(); - - Assert.IsTrue(string.IsNullOrWhiteSpace(result)); - } - - [TestMethod()] - public void should_return_stringfied_order_by_clause() - { - List lstOrderBy = - [ - new OrderBy - { - Name = x=>((TestClass)x).Property1, - Direction = Enumerations.OrderByDirection.Descending - }, - new OrderBy - { - Name = x=>((TestClass)x).Property2, - Direction = Enumerations.OrderByDirection.Ascending - } - ]; - - string expectedResult = "ORDER BY [Property1] DESC,[Property2] ASC"; - - var result = lstOrderBy.GetSorting(); - - Assert.AreEqual(expectedResult, result); - } - - [TestMethod()] - public void should_return_stringfied_order_by_clause_complex_type() - { - List lstOrderBy = - [ - new OrderBy - { - Name = x=>((TestClass)x).InnerSingularProperty.InnerProperty1, - Direction = Enumerations.OrderByDirection.Descending - } - ]; - - string expectedResult = "ORDER BY [InnerSingularProperty.InnerProperty1] DESC"; - - var result = lstOrderBy.GetSorting(); - - Assert.AreEqual(expectedResult, result); - } - - [TestMethod()] - public void should_return_stringfied_order_by_clause_stringfied_type_name() - { - List lstOrderBy = - [ - new OrderBy - { - Name = x=>"Property3", - Direction = Enumerations.OrderByDirection.Descending - } - ]; - - string expectedResult = "ORDER BY [Property3] DESC"; - - var result = lstOrderBy.GetSorting(); - - Assert.AreEqual(expectedResult, result); - } - - [TestMethod()] - public void should_return_stringfied_order_by_clause_using_string_name() - { - List lstOrderBy = - [ - new OrderBy("Property3") - { - Direction = Enumerations.OrderByDirection.Descending - } - ]; - - string expectedResult = "ORDER BY [Property3] DESC"; - - var result = lstOrderBy.GetSorting(); - - Assert.AreEqual(expectedResult, result); - } + List lstOrderBy = + [ + new OrderBy("Property3") + { + Direction = Enumerations.OrderByDirection.Descending + } + ]; + + string expectedResult = "ORDER BY [Property3] DESC"; + + var result = lstOrderBy.GetSorting(); + + Assert.AreEqual(expectedResult, result); } } diff --git a/Tests/Jinget.Core.Tests/ExtensionMethods/ExpressionToSql/PagingExtensionsTests.cs b/Tests/Jinget.Core.Tests/ExtensionMethods/ExpressionToSql/PagingExtensionsTests.cs index c832809..bfffd1b 100644 --- a/Tests/Jinget.Core.Tests/ExtensionMethods/ExpressionToSql/PagingExtensionsTests.cs +++ b/Tests/Jinget.Core.Tests/ExtensionMethods/ExpressionToSql/PagingExtensionsTests.cs @@ -4,82 +4,81 @@ using Jinget.Core.Tests._BaseData; using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace Jinget.Core.ExtensionMethods.ExpressionToSql +namespace Jinget.Core.ExtensionMethods.ExpressionToSql; + +[TestClass()] +public class PagingExtensionsTests { - [TestClass()] - public class PagingExtensionsTests + [TestMethod()] + public void should_return_empty_string() { - [TestMethod()] - public void should_return_empty_string() - { - Paging paging = null; - List lstOrderBy = null; + Paging paging = null; + List lstOrderBy = null; - var result = paging.GetPaging(lstOrderBy); + var result = paging.GetPaging(lstOrderBy); - Assert.IsTrue(string.IsNullOrWhiteSpace(result)); - } + Assert.IsTrue(string.IsNullOrWhiteSpace(result)); + } - [TestMethod()] - [ExpectedException(typeof(JingetException), AllowDerivedTypes = false)] - public void should_throw_jinget_exception() + [TestMethod()] + [ExpectedException(typeof(JingetException), AllowDerivedTypes = false)] + public void should_throw_jinget_exception() + { + Paging paging = new() { - Paging paging = new() - { - PageNumber = 1, - PageSize = 10 - }; - List lstOrderBy = null; + PageNumber = 1, + PageSize = 10 + }; + List lstOrderBy = null; - paging.GetPaging(lstOrderBy); - } + paging.GetPaging(lstOrderBy); + } - [TestMethod()] - public void should_return_stringfied_order_by_clause() - { - Paging paging = null; - List lstOrderBy = - [ - new OrderBy - { - Name = x=>((TestClass)x).Property1, - Direction = Enumerations.OrderByDirection.Descending - } - ]; - string expectedResult = "ORDER BY [Property1] DESC "; + [TestMethod()] + public void should_return_stringfied_order_by_clause() + { + Paging paging = null; + List lstOrderBy = + [ + new OrderBy + { + Name = x=>((TestClass)x).Property1, + Direction = Enumerations.OrderByDirection.Descending + } + ]; + string expectedResult = "ORDER BY [Property1] DESC "; - var result = paging.GetPaging(lstOrderBy); + var result = paging.GetPaging(lstOrderBy); - Assert.AreEqual(expectedResult, result); - } + Assert.AreEqual(expectedResult, result); + } - [TestMethod()] - public void should_return_stringfied_paging_clause() + [TestMethod()] + public void should_return_stringfied_paging_clause() + { + Paging paging = new() { - Paging paging = new() + PageNumber = 1, + PageSize = 10 + }; + List lstOrderBy = + [ + new OrderBy + { + Name = x=>((TestClass)x).Property1, + Direction = Enumerations.OrderByDirection.Descending + }, + new OrderBy { - PageNumber = 1, - PageSize = 10 - }; - List lstOrderBy = - [ - new OrderBy - { - Name = x=>((TestClass)x).Property1, - Direction = Enumerations.OrderByDirection.Descending - }, - new OrderBy - { - Name = x=>((TestClass)x).Property2, - Direction = Enumerations.OrderByDirection.Ascending - } - ]; + Name = x=>((TestClass)x).Property2, + Direction = Enumerations.OrderByDirection.Ascending + } + ]; - string expectedResult = "ORDER BY [Property1] DESC,[Property2] ASC OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY"; + string expectedResult = "ORDER BY [Property1] DESC,[Property2] ASC OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY"; - var result = paging.GetPaging(lstOrderBy); + var result = paging.GetPaging(lstOrderBy); - Assert.AreEqual(expectedResult, result); - } + Assert.AreEqual(expectedResult, result); } } diff --git a/Tests/Jinget.Core.Tests/ExtensionMethods/Expressions/BooleanExpressionExtensionsTests.cs b/Tests/Jinget.Core.Tests/ExtensionMethods/Expressions/BooleanExpressionExtensionsTests.cs index f97916e..17e1539 100644 --- a/Tests/Jinget.Core.Tests/ExtensionMethods/Expressions/BooleanExpressionExtensionsTests.cs +++ b/Tests/Jinget.Core.Tests/ExtensionMethods/Expressions/BooleanExpressionExtensionsTests.cs @@ -3,42 +3,41 @@ using System; using System.Linq.Expressions; -namespace Jinget.Core.ExtensionMethods.Expressions.Tests +namespace Jinget.Core.ExtensionMethods.Expressions.Tests; + +[TestClass()] +public class BooleanExpressionExtensionsTests { - [TestClass()] - public class BooleanExpressionExtensionsTests + [TestMethod()] + public void should_negate_the_given_exoression() { - [TestMethod()] - public void should_negate_the_given_exoression() - { - Expression> expression = x => x.Property1 > 0; - Expression> expectedExpression = x => !(x.Property1 > 0); + Expression> expression = x => x.Property1 > 0; + Expression> expectedExpression = x => !(x.Property1 > 0); - var result = expression.Not(); + var result = expression.Not(); - Assert.AreEqual(expectedExpression.Body.ToString(), result.Body.ToString()); - } + Assert.AreEqual(expectedExpression.Body.ToString(), result.Body.ToString()); + } - [TestMethod()] - public void should_combine_conditions_by_and() - { - Expression> expression = x => x.Property1 > 0; - Expression> expectedExpression = x => x.Property1 > 0 && x.Property2 != string.Empty; + [TestMethod()] + public void should_combine_conditions_by_and() + { + Expression> expression = x => x.Property1 > 0; + Expression> expectedExpression = x => x.Property1 > 0 && x.Property2 != string.Empty; - var result = expression.AndAlso(x => x.Property2 != string.Empty, "x"); + var result = expression.AndAlso(x => x.Property2 != string.Empty, "x"); - Assert.AreEqual(expectedExpression.Body.ToString(), result.Body.ToString()); - } + Assert.AreEqual(expectedExpression.Body.ToString(), result.Body.ToString()); + } - [TestMethod()] - public void should_combine_conditions_by_or() - { - Expression> expression = x => x.Property1 > 0; - Expression> expectedExpression = x => x.Property1 > 0 || x.Property2 != string.Empty; + [TestMethod()] + public void should_combine_conditions_by_or() + { + Expression> expression = x => x.Property1 > 0; + Expression> expectedExpression = x => x.Property1 > 0 || x.Property2 != string.Empty; - var result = expression.OrElse(x => x.Property2 != string.Empty, "x"); + var result = expression.OrElse(x => x.Property2 != string.Empty, "x"); - Assert.AreEqual(expectedExpression.Body.ToString(), result.Body.ToString()); - } + Assert.AreEqual(expectedExpression.Body.ToString(), result.Body.ToString()); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/ExtensionMethods/Expressions/ExpressionExtensionsTests.cs b/Tests/Jinget.Core.Tests/ExtensionMethods/Expressions/ExpressionExtensionsTests.cs index 75f4ac3..d0f4f26 100644 --- a/Tests/Jinget.Core.Tests/ExtensionMethods/Expressions/ExpressionExtensionsTests.cs +++ b/Tests/Jinget.Core.Tests/ExtensionMethods/Expressions/ExpressionExtensionsTests.cs @@ -4,44 +4,43 @@ using System.Linq; using System.Linq.Expressions; -namespace Jinget.Core.ExtensionMethods.Expressions.Tests +namespace Jinget.Core.ExtensionMethods.Expressions.Tests; + +[TestClass()] +public class ExpressionExtensionsTests { - [TestClass()] - public class ExpressionExtensionsTests + [TestMethod()] + public void transform_anonymouse_new_expression_to_nonanonymouse_expression() { - [TestMethod()] - public void transform_anonymouse_new_expression_to_nonanonymouse_expression() - { - Expression> expression = x => new { Property1 = 1 }; + Expression> expression = x => new { Property1 = 1 }; - Expression> expectedExpression = x => new TestClass { Property1 = 1 }; + Expression> expectedExpression = x => new TestClass { Property1 = 1 }; - var result = expression.Transform(); + var result = expression.Transform(); - Assert.IsTrue(result.ToString() == "x => new TestClass() {Property1 = 1}"); - } + Assert.IsTrue(result.ToString() == "x => new TestClass() {Property1 = 1}"); + } - [TestMethod()] - public void transform_anonymouse_collection_expression_to_nonanonymouse_expression() + [TestMethod()] + public void transform_anonymouse_collection_expression_to_nonanonymouse_expression() + { + Expression> expression = x => new { - Expression> expression = x => new + x.Id, + Sub = new { - x.Id, - Sub = new + x.Sub.Id, + ColSubs = x.Sub.ColSubs.Select(u => new { - x.Sub.Id, - ColSubs = x.Sub.ColSubs.Select(u => new - { - u.Id - }).ToList() - } - }; + u.Id + }).ToList() + } + }; - var expectedExpression = "x => new ParentType() {Id = x.Id, Sub = new SubType() {Id = x.Sub.Id, ColSubs = x.Sub.ColSubs.Select(u => new ColSubType() {Id = u.Id}).ToList()}}"; + var expectedExpression = "x => new ParentType() {Id = x.Id, Sub = new SubType() {Id = x.Sub.Id, ColSubs = x.Sub.ColSubs.Select(u => new ColSubType() {Id = u.Id}).ToList()}}"; - var result = expression.Transform(); + var result = expression.Transform(); - Assert.IsTrue(result.ToString() == expectedExpression); - } + Assert.IsTrue(result.ToString() == expectedExpression); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/ExtensionMethods/Expressions/LambdaExpressionExtensionsTests.cs b/Tests/Jinget.Core.Tests/ExtensionMethods/Expressions/LambdaExpressionExtensionsTests.cs index 2527822..2d48afd 100644 --- a/Tests/Jinget.Core.Tests/ExtensionMethods/Expressions/LambdaExpressionExtensionsTests.cs +++ b/Tests/Jinget.Core.Tests/ExtensionMethods/Expressions/LambdaExpressionExtensionsTests.cs @@ -5,65 +5,64 @@ using Jinget.Core.Exceptions; using Jinget.Core.Tests._BaseData; -namespace Jinget.Core.ExtensionMethods.Expressions.Tests +namespace Jinget.Core.ExtensionMethods.Expressions.Tests; + +[TestClass()] +public class LambdaExpressionExtensionsTests { - [TestClass()] - public class LambdaExpressionExtensionsTests + [TestMethod()] + public void stringfy_constant_exppression() { - [TestMethod()] - public void stringfy_constant_exppression() - { - Expression> expr = x => 1; - var result = expr.Stringfy(); - Assert.AreEqual("1", result); - } + Expression> expr = x => 1; + var result = expr.Stringfy(); + Assert.AreEqual("1", result); + } - [TestMethod()] - public void stringfy_member_exppression() - { - Expression> expr = x => x.Property1; - var result = expr.Stringfy(); - Assert.AreEqual("Property1", result); - } + [TestMethod()] + public void stringfy_member_exppression() + { + Expression> expr = x => x.Property1; + var result = expr.Stringfy(); + Assert.AreEqual("Property1", result); + } - [TestMethod()] - public void stringfy_methodcall_select_exppression() - { - Expression> expr = x => x.InnerProperty.Select(y => y.InnerProperty1); - var result = expr.Stringfy(); - Assert.AreEqual("InnerProperty.InnerProperty1", result); - } + [TestMethod()] + public void stringfy_methodcall_select_exppression() + { + Expression> expr = x => x.InnerProperty.Select(y => y.InnerProperty1); + var result = expr.Stringfy(); + Assert.AreEqual("InnerProperty.InnerProperty1", result); + } - [TestMethod()] - public void stringfy_methodcall_tostring_exppression() - { - Expression> expr = x => x.Property2.ToString(); - var result = expr.Stringfy(); - Assert.AreEqual("Property2", result); - } + [TestMethod()] + public void stringfy_methodcall_tostring_exppression() + { + Expression> expr = x => x.Property2.ToString(); + var result = expr.Stringfy(); + Assert.AreEqual("Property2", result); + } - [TestMethod()] - public void stringfy_methodcall_tolower_exppression() - { - Expression> expr = x => x.Property2.ToLower(); - var result = expr.Stringfy(); - Assert.AreEqual("Property2", result); - } + [TestMethod()] + public void stringfy_methodcall_tolower_exppression() + { + Expression> expr = x => x.Property2.ToLower(); + var result = expr.Stringfy(); + Assert.AreEqual("Property2", result); + } - [TestMethod()] - [ExpectedException(typeof(JingetException))] - public void stringfy_methodcall_where_exppression() - { - Expression> expr = x => x.InnerProperty.Where(y => x.Property1 > 0); - var result = expr.Stringfy(); - } + [TestMethod()] + [ExpectedException(typeof(JingetException))] + public void stringfy_methodcall_where_exppression() + { + Expression> expr = x => x.InnerProperty.Where(y => x.Property1 > 0); + var result = expr.Stringfy(); + } - [TestMethod()] - [ExpectedException(typeof(JingetException))] - public void stringfy_methodcall_orderby_exppression() - { - Expression> expr = x => x.InnerProperty.OrderBy(y => x.Property1); - var result = expr.Stringfy(); - } + [TestMethod()] + [ExpectedException(typeof(JingetException))] + public void stringfy_methodcall_orderby_exppression() + { + Expression> expr = x => x.InnerProperty.OrderBy(y => x.Property1); + var result = expr.Stringfy(); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/ExtensionMethods/Generics/GenericTypeExtensionsTests.cs b/Tests/Jinget.Core.Tests/ExtensionMethods/Generics/GenericTypeExtensionsTests.cs index faeb6ac..ffe6eac 100644 --- a/Tests/Jinget.Core.Tests/ExtensionMethods/Generics/GenericTypeExtensionsTests.cs +++ b/Tests/Jinget.Core.Tests/ExtensionMethods/Generics/GenericTypeExtensionsTests.cs @@ -2,30 +2,29 @@ using Jinget.Core.ExtensionMethods.Generics; using Jinget.Core.Tests._BaseData; -namespace Jinget.Core.Tests.ExtensionMethods.Generics +namespace Jinget.Core.Tests.ExtensionMethods.Generics; + +[TestClass()] +public class GenericTypeExtensionsTests { - [TestClass()] - public class GenericTypeExtensionsTests - { - [TestMethod()] - public void should_return_false_for_irrelative_types() => Assert.IsFalse(typeof(System.Tuple).IsSubclassOfRawGeneric(typeof(System.Exception))); + [TestMethod()] + public void should_return_false_for_irrelative_types() => Assert.IsFalse(typeof(System.Tuple).IsSubclassOfRawGeneric(typeof(System.Exception))); - [TestMethod()] - public void should_return_true_for_nongeneric_child_nongeneric_parent() => Assert.IsTrue(typeof(NonGenericChildNonGenericParent).IsSubclassOfRawGeneric(typeof(NonGenericParent))); + [TestMethod()] + public void should_return_true_for_nongeneric_child_nongeneric_parent() => Assert.IsTrue(typeof(NonGenericChildNonGenericParent).IsSubclassOfRawGeneric(typeof(NonGenericParent))); - [TestMethod()] - public void should_return_true_for_nongeneric_child_generic_parent() => Assert.IsTrue(typeof(NonGenericChildGenericParent).IsSubclassOfRawGeneric(typeof(GenericParent<>))); + [TestMethod()] + public void should_return_true_for_nongeneric_child_generic_parent() => Assert.IsTrue(typeof(NonGenericChildGenericParent).IsSubclassOfRawGeneric(typeof(GenericParent<>))); - [TestMethod()] - public void should_return_true_for_generic_child_nongeneric_parent() => Assert.IsTrue(typeof(GenericChildNonGenericParent<>).IsSubclassOfRawGeneric(typeof(NonGenericParent))); + [TestMethod()] + public void should_return_true_for_generic_child_nongeneric_parent() => Assert.IsTrue(typeof(GenericChildNonGenericParent<>).IsSubclassOfRawGeneric(typeof(NonGenericParent))); - [TestMethod()] - public void should_return_true_for_generic_child_generic_parent() => Assert.IsTrue(typeof(GenericChildGenericParent<>).IsSubclassOfRawGeneric(typeof(GenericParent<>))); + [TestMethod()] + public void should_return_true_for_generic_child_generic_parent() => Assert.IsTrue(typeof(GenericChildGenericParent<>).IsSubclassOfRawGeneric(typeof(GenericParent<>))); - [TestMethod()] - public void should_return_true_for_generic_child_multigeneric_parent() => Assert.IsTrue(typeof(GenericChildMultiGenericParent<,,>).IsSubclassOfRawGeneric(typeof(MultiGenericParent<,,>))); + [TestMethod()] + public void should_return_true_for_generic_child_multigeneric_parent() => Assert.IsTrue(typeof(GenericChildMultiGenericParent<,,>).IsSubclassOfRawGeneric(typeof(MultiGenericParent<,,>))); - [TestMethod()] - public void should_return_true_for_nongeneric_child_multigeneric_parent() => Assert.IsTrue(typeof(NonGenericChildMultiGenericParent).IsSubclassOfRawGeneric(typeof(MultiGenericParent<,,>))); - } + [TestMethod()] + public void should_return_true_for_nongeneric_child_multigeneric_parent() => Assert.IsTrue(typeof(NonGenericChildMultiGenericParent).IsSubclassOfRawGeneric(typeof(MultiGenericParent<,,>))); } diff --git a/Tests/Jinget.Core.Tests/ExtensionMethods/IServiceProviderExtensionsTests.cs b/Tests/Jinget.Core.Tests/ExtensionMethods/IServiceProviderExtensionsTests.cs index 0c8433e..18efd1a 100644 --- a/Tests/Jinget.Core.Tests/ExtensionMethods/IServiceProviderExtensionsTests.cs +++ b/Tests/Jinget.Core.Tests/ExtensionMethods/IServiceProviderExtensionsTests.cs @@ -3,33 +3,32 @@ using Microsoft.Extensions.DependencyInjection; using Jinget.Core.Tests._BaseData; -namespace Jinget.Core.ExtensionMethods.Tests +namespace Jinget.Core.ExtensionMethods.Tests; + +[TestClass()] +public class IServiceProviderExtensionsTests { - [TestClass()] - public class IServiceProviderExtensionsTests + IServiceProvider services; + [TestInitialize] + public void Initialize() { - IServiceProvider services; - [TestInitialize] - public void Initialize() - { - var serviceCollection = new ServiceCollection(); - serviceCollection.AddTransient(typeof(ISampleInterface), typeof(SampleInterfaceClass)); - services = serviceCollection.BuildServiceProvider(); - } + var serviceCollection = new ServiceCollection(); + serviceCollection.AddTransient(typeof(ISampleInterface), typeof(SampleInterfaceClass)); + services = serviceCollection.BuildServiceProvider(); + } - [TestMethod()] - public void should_return_registered_service() - { - var result = services.GetJingetService(); + [TestMethod()] + public void should_return_registered_service() + { + var result = services.GetJingetService(); - Assert.IsInstanceOfType(result, typeof(SampleInterfaceClass)); - } + Assert.IsInstanceOfType(result, typeof(SampleInterfaceClass)); + } - [TestMethod()] - [ExpectedException(typeof(InvalidOperationException))] - public void should_throw_exception_for_nonregistered_service() - { - services.GetJingetService(); - } + [TestMethod()] + [ExpectedException(typeof(InvalidOperationException))] + public void should_throw_exception_for_nonregistered_service() + { + services.GetJingetService(); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/ExtensionMethods/ObjectExtensionsTests.cs b/Tests/Jinget.Core.Tests/ExtensionMethods/ObjectExtensionsTests.cs index 414b060..dec0c8c 100644 --- a/Tests/Jinget.Core.Tests/ExtensionMethods/ObjectExtensionsTests.cs +++ b/Tests/Jinget.Core.Tests/ExtensionMethods/ObjectExtensionsTests.cs @@ -3,100 +3,99 @@ using Jinget.Core.Tests._BaseData; using static Jinget.Core.ExtensionMethods.ObjectExtensions; -namespace Jinget.Core.ExtensionMethods.Tests +namespace Jinget.Core.ExtensionMethods.Tests; + +[TestClass()] +public class ObjectExtensionsTests { - [TestClass()] - public class ObjectExtensionsTests + [TestMethod()] + public void should_check_if_given_type_is_a_numeric_type_or_not() { - [TestMethod()] - public void should_check_if_given_type_is_a_numeric_type_or_not() - { - int x = 0; - var result = x.IsNumericType(); - Assert.IsTrue(result); + int x = 0; + var result = x.IsNumericType(); + Assert.IsTrue(result); - string name = "vahid"; - result = name.IsNumericType(); - Assert.IsFalse(result); + string name = "vahid"; + result = name.IsNumericType(); + Assert.IsFalse(result); - TestClass obj = new(); - result = obj.IsNumericType(); - Assert.IsFalse(result); - } + TestClass obj = new(); + result = obj.IsNumericType(); + Assert.IsFalse(result); + } - [TestMethod()] - public void should_convert_given_type_to_dictionary() + [TestMethod()] + public void should_convert_given_type_to_dictionary() + { + TestClass obj = new() { - TestClass obj = new() - { - Property1 = 123, - Property2 = "vahid", - InnerSingularProperty = new TestClass.InnerClass - { - InnerProperty1 = 456 - }, - InnerListProperty = - [ - new() { - InnerProperty1=789 - } - ] - }; - var result = obj.ToDictionary(new Options + Property1 = 123, + Property2 = "vahid", + InnerSingularProperty = new TestClass.InnerClass { - IgnoreNull = false - }); + InnerProperty1 = 456 + }, + InnerListProperty = + [ + new() { + InnerProperty1=789 + } + ] + }; + var result = obj.ToDictionary(new Options + { + IgnoreNull = false + }); - Assert.IsTrue(result.Keys.Any(x => x == "InnerSingularProperty")); - } + Assert.IsTrue(result.Keys.Any(x => x == "InnerSingularProperty")); + } - [TestMethod()] - public void should_get_the_value_of_the_given_property() + [TestMethod()] + public void should_get_the_value_of_the_given_property() + { + TestClass obj = new() { - TestClass obj = new() - { - Property1 = 123, - Property2 = "vahid" - }; - string expectedResult = "vahid"; - var result = obj.GetValue(nameof(TestClass.Property2)); + Property1 = 123, + Property2 = "vahid" + }; + string expectedResult = "vahid"; + var result = obj.GetValue(nameof(TestClass.Property2)); - Assert.AreEqual(expectedResult, result); - } + Assert.AreEqual(expectedResult, result); + } - [TestMethod()] - public void should_convert_object_to_given_type() + [TestMethod()] + public void should_convert_object_to_given_type() + { + Type1 obj = new() { - Type1 obj = new() - { - Id = 123, - Name = "vahid" - }; + Id = 123, + Name = "vahid" + }; - var result = obj.ToType(suppressError: true); + var result = obj.ToType(suppressError: true); - Assert.AreEqual(obj.Id, result.Id); - Assert.AreEqual(obj.Name, result.Name); - Assert.IsTrue(result.SurName == null); - } + Assert.AreEqual(obj.Id, result.Id); + Assert.AreEqual(obj.Name, result.Name); + Assert.IsTrue(result.SurName == null); + } - [TestMethod()] - public void should_return_true_for_two_objects_with_same_structure_and_value() + [TestMethod()] + public void should_return_true_for_two_objects_with_same_structure_and_value() + { + Type1 objSource = new() { - Type1 objSource = new() - { - Id = 123, - Name = "vahid" - }; - Type2 objTarget = new() - { - Id = 123, - Name = "vahid" - }; - var result = objSource.HasSameValuesAs(objTarget); + Id = 123, + Name = "vahid" + }; + Type2 objTarget = new() + { + Id = 123, + Name = "vahid" + }; + var result = objSource.HasSameValuesAs(objTarget); - Assert.IsTrue(result); - } + Assert.IsTrue(result); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/ExtensionMethods/Reflection/AssemblyExtensionsTests.cs b/Tests/Jinget.Core.Tests/ExtensionMethods/Reflection/AssemblyExtensionsTests.cs index 49c75a2..eff4a20 100644 --- a/Tests/Jinget.Core.Tests/ExtensionMethods/Reflection/AssemblyExtensionsTests.cs +++ b/Tests/Jinget.Core.Tests/ExtensionMethods/Reflection/AssemblyExtensionsTests.cs @@ -2,37 +2,36 @@ using System.Linq; using Jinget.Core.Tests._BaseData; -namespace Jinget.Core.ExtensionMethods.Reflection.Tests +namespace Jinget.Core.ExtensionMethods.Reflection.Tests; + +[TestClass()] +public class AssemblyExtensionsTests { - [TestClass()] - public class AssemblyExtensionsTests + [TestMethod()] + public void should_get_all_types_in_an_assembly() { - [TestMethod()] - public void should_get_all_types_in_an_assembly() - { - var result = AssemblyExtensions.GetTypes(this.GetType().Assembly, typeof(NonGenericParent), normalizingPattern: @"Parent`1$"); - Assert.IsNotNull(result); - Assert.IsTrue(result.Any()); - Assert.IsTrue(result.All(x => x.Summary != string.Empty)); - } + var result = AssemblyExtensions.GetTypes(this.GetType().Assembly, typeof(NonGenericParent), normalizingPattern: @"Parent`1$"); + Assert.IsNotNull(result); + Assert.IsTrue(result.Any()); + Assert.IsTrue(result.All(x => x.Summary != string.Empty)); + } - [TestMethod()] - public void should_get_all_authorized_methods_in_a_type() - { - var result = AssemblyExtensions.GetMethods(this.GetType().Assembly, typeof(NonGenericParent), typeof(Attributes.SummaryAttribute)); - Assert.IsNotNull(result); - Assert.IsTrue(result.Any()); - Assert.IsTrue(result.Any(x => x.MethodName!= "SampleMethod3")); - } + [TestMethod()] + public void should_get_all_authorized_methods_in_a_type() + { + var result = AssemblyExtensions.GetMethods(this.GetType().Assembly, typeof(NonGenericParent), typeof(Attributes.SummaryAttribute)); + Assert.IsNotNull(result); + Assert.IsTrue(result.Any()); + Assert.IsTrue(result.Any(x => x.MethodName!= "SampleMethod3")); + } - [TestMethod()] - public void should_get_all_methods_in_a_type() - { - var result = AssemblyExtensions.GetMethods(this.GetType().Assembly, typeof(NonGenericParent), typeof(Attributes.SummaryAttribute), onlyAuthorizedMethods: false); - Assert.IsNotNull(result); - Assert.IsTrue(result.Any()); - Assert.IsTrue(result.Any(x => x.Summary != null)); - } + [TestMethod()] + public void should_get_all_methods_in_a_type() + { + var result = AssemblyExtensions.GetMethods(this.GetType().Assembly, typeof(NonGenericParent), typeof(Attributes.SummaryAttribute), onlyAuthorizedMethods: false); + Assert.IsNotNull(result); + Assert.IsTrue(result.Any()); + Assert.IsTrue(result.Any(x => x.Summary != null)); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/ExtensionMethods/Reflection/ConstructorExtensionsTests.cs b/Tests/Jinget.Core.Tests/ExtensionMethods/Reflection/ConstructorExtensionsTests.cs index 8904410..f6d1b37 100644 --- a/Tests/Jinget.Core.Tests/ExtensionMethods/Reflection/ConstructorExtensionsTests.cs +++ b/Tests/Jinget.Core.Tests/ExtensionMethods/Reflection/ConstructorExtensionsTests.cs @@ -1,39 +1,38 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Jinget.Core.Tests._BaseData; -namespace Jinget.Core.ExtensionMethods.Reflection.Tests +namespace Jinget.Core.ExtensionMethods.Reflection.Tests; + +[TestClass()] +public class ConstructorExtensionsTests { - [TestClass()] - public class ConstructorExtensionsTests + [TestMethod()] + public void Should_return_public_default_constructor() { - [TestMethod()] - public void Should_return_public_default_constructor() - { - var ctor = typeof(TestClass).GetDefaultConstructor(); + var ctor = typeof(TestClass).GetDefaultConstructor(); - Assert.IsNotNull(ctor); - Assert.IsTrue(ctor.IsConstructor); - Assert.IsTrue(ctor.IsPublic); - } + Assert.IsNotNull(ctor); + Assert.IsTrue(ctor.IsConstructor); + Assert.IsTrue(ctor.IsPublic); + } - [TestMethod()] - public void Should_return_private_default_constructor() - { - var ctor = typeof(SubType).GetDefaultConstructor(); + [TestMethod()] + public void Should_return_private_default_constructor() + { + var ctor = typeof(SubType).GetDefaultConstructor(); - Assert.IsNotNull(ctor); - Assert.IsTrue(ctor.IsConstructor); - Assert.IsFalse(ctor.IsPublic); - } + Assert.IsNotNull(ctor); + Assert.IsTrue(ctor.IsConstructor); + Assert.IsFalse(ctor.IsPublic); + } - [TestMethod()] - public void Should_invoke_default_constructor() - { - var obj = typeof(SubType).InvokeDefaultConstructor(); - var expectedType = typeof(SubType); + [TestMethod()] + public void Should_invoke_default_constructor() + { + var obj = typeof(SubType).InvokeDefaultConstructor(); + var expectedType = typeof(SubType); - Assert.IsNotNull(obj); - Assert.AreEqual(expectedType, obj.GetType()); - } + Assert.IsNotNull(obj); + Assert.AreEqual(expectedType, obj.GetType()); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/ExtensionMethods/Reflection/MethodInfoExtensionsTests.cs b/Tests/Jinget.Core.Tests/ExtensionMethods/Reflection/MethodInfoExtensionsTests.cs index af6e6ce..9f1005b 100644 --- a/Tests/Jinget.Core.Tests/ExtensionMethods/Reflection/MethodInfoExtensionsTests.cs +++ b/Tests/Jinget.Core.Tests/ExtensionMethods/Reflection/MethodInfoExtensionsTests.cs @@ -4,24 +4,23 @@ using System.Threading.Tasks; using Jinget.Core.Tests._BaseData; -namespace Jinget.Core.ExtensionMethods.Reflection.Tests +namespace Jinget.Core.ExtensionMethods.Reflection.Tests; + +[TestClass()] +public class MethodInfoExtensionsTests { - [TestClass()] - public class MethodInfoExtensionsTests + async Task> GetAsync(string name) => await Task.FromResult>([ + new() {Id = 1, Name=name}, + new() {Id = 2, Name="Ali"} + ]); + [TestMethod()] + public void Should_call_async_method_and_return_result() { - async Task> GetAsync(string name) => await Task.FromResult>([ - new() {Id = 1, Name=name}, - new() {Id = 2, Name="Ali"} - ]); - [TestMethod()] - public void Should_call_async_method_and_return_result() - { - var method = this.GetType().GetMethod("GetAsync", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); - var result = (List)method.InvokeAsync(this, "vahid"); + var method = this.GetType().GetMethod("GetAsync", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); + var result = (List)method.InvokeAsync(this, "vahid"); - Assert.IsTrue(result.First().Id == 1); - Assert.IsTrue(result.First().Name == "vahid"); - Assert.IsTrue(result.Last().Id == 2); - } + Assert.IsTrue(result.First().Id == 1); + Assert.IsTrue(result.First().Name == "vahid"); + Assert.IsTrue(result.Last().Id == 2); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/ExtensionMethods/Reflection/PropertiesExtensionsTests.cs b/Tests/Jinget.Core.Tests/ExtensionMethods/Reflection/PropertiesExtensionsTests.cs index bccb6cd..f49b9cb 100644 --- a/Tests/Jinget.Core.Tests/ExtensionMethods/Reflection/PropertiesExtensionsTests.cs +++ b/Tests/Jinget.Core.Tests/ExtensionMethods/Reflection/PropertiesExtensionsTests.cs @@ -4,36 +4,35 @@ using System.Collections.Generic; using System.Reflection; -namespace Jinget.Core.ExtensionMethods.Reflection.Tests +namespace Jinget.Core.ExtensionMethods.Reflection.Tests; + +[TestClass()] +public class PropertiesExtensionsTests { - [TestClass()] - public class PropertiesExtensionsTests + [TestMethod()] + public void Should_return_true_for_nullable_type() { - [TestMethod()] - public void Should_return_true_for_nullable_type() - { - var input = typeof(int?); - var result = input.IsNullable(); - Assert.IsTrue(result); + var input = typeof(int?); + var result = input.IsNullable(); + Assert.IsTrue(result); - input = typeof(bool?); - result = input.IsNullable(); - Assert.IsTrue(result); - } + input = typeof(bool?); + result = input.IsNullable(); + Assert.IsTrue(result); + } - [TestMethod()] - public void Should_return_all_writable_primitive_properties() + [TestMethod()] + public void Should_return_all_writable_primitive_properties() + { + Dictionary expectedResult = new() { - Dictionary expectedResult = new() - { - {"Property1", typeof(TestClass).GetProperty("Property1") }, - {"Property2", typeof(TestClass).GetProperty("Property2") } - }; - var result = typeof(TestClass).GetWritableProperties(); + {"Property1", typeof(TestClass).GetProperty("Property1") }, + {"Property2", typeof(TestClass).GetProperty("Property2") } + }; + var result = typeof(TestClass).GetWritableProperties(); - Assert.IsNotNull(result); - Assert.IsTrue(result.Any()); - Assert.AreEqual(expectedResult.First(), result.First()); - } + Assert.IsNotNull(result); + Assert.IsTrue(result.Any()); + Assert.AreEqual(expectedResult.First(), result.First()); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/ExtensionMethods/Reflection/TypeExtensionsTests.cs b/Tests/Jinget.Core.Tests/ExtensionMethods/Reflection/TypeExtensionsTests.cs index e6c8b63..199eada 100644 --- a/Tests/Jinget.Core.Tests/ExtensionMethods/Reflection/TypeExtensionsTests.cs +++ b/Tests/Jinget.Core.Tests/ExtensionMethods/Reflection/TypeExtensionsTests.cs @@ -2,68 +2,67 @@ using Jinget.Core.Tests._BaseData; using System.Linq; -namespace Jinget.Core.ExtensionMethods.Reflection.Tests +namespace Jinget.Core.ExtensionMethods.Reflection.Tests; + +[TestClass()] +public class TypeExtensionsTests { - [TestClass()] - public class TypeExtensionsTests + [TestMethod()] + public void Should_return_true_for_anonymous_type() { - [TestMethod()] - public void Should_return_true_for_anonymous_type() - { - var input = new { Name = "Vahid", Age = 32 }; - var result = input.GetType().IsAnonymousType(); - Assert.IsTrue(result); - } + var input = new { Name = "Vahid", Age = 32 }; + var result = input.GetType().IsAnonymousType(); + Assert.IsTrue(result); + } - [TestMethod()] - public void Should_return_false_for_anonymous_type() - { - var input = new TestClass(); - var result = input.GetType().IsAnonymousType(); - Assert.IsFalse(result); - } + [TestMethod()] + public void Should_return_false_for_anonymous_type() + { + var input = new TestClass(); + var result = input.GetType().IsAnonymousType(); + Assert.IsFalse(result); + } - [TestMethod()] - public void should_call_method_dynamically() - { - string expectedResult = "string is: vahid, integer is: 123, generic type is: SubType"; + [TestMethod()] + public void should_call_method_dynamically() + { + string expectedResult = "string is: vahid, integer is: 123, generic type is: SubType"; - var result = typeof(TestClass).Call( - caller: new TestClass(), - name: nameof(TestClass.GetInfo), - parameters: ["vahid", 123], - generics: typeof(SubType)); + var result = typeof(TestClass).Call( + caller: new TestClass(), + name: nameof(TestClass.GetInfo), + parameters: ["vahid", 123], + generics: typeof(SubType)); - Assert.AreEqual(expectedResult, result); - } + Assert.AreEqual(expectedResult, result); + } - [TestMethod()] - public void shuold_return_all_reference_type_properties_except_string_types() - { - var result = typeof(TestClass).GetReferenceTypeProperties(); + [TestMethod()] + public void shuold_return_all_reference_type_properties_except_string_types() + { + var result = typeof(TestClass).GetReferenceTypeProperties(); - Assert.IsTrue(result.Any(x => x.Name == "InnerSingularProperty")); - } + Assert.IsTrue(result.Any(x => x.Name == "InnerSingularProperty")); + } - [TestMethod()] - public void shuold_return_all_reference_type_properties_including_string_types() - { - var result = typeof(TestClass).GetReferenceTypeProperties(includeStringTypes: true); + [TestMethod()] + public void shuold_return_all_reference_type_properties_including_string_types() + { + var result = typeof(TestClass).GetReferenceTypeProperties(includeStringTypes: true); - Assert.IsTrue(result.Any(x => x.Name == "Property2")); - } + Assert.IsTrue(result.Any(x => x.Name == "Property2")); + } - [TestMethod()] - public void should_return_the_default_value_for_given_type() - { - var result = typeof(string).GetDefaultValue(); - Assert.IsNull(result); + [TestMethod()] + public void should_return_the_default_value_for_given_type() + { + var result = typeof(string).GetDefaultValue(); + Assert.IsNull(result); - result = typeof(int).GetDefaultValue(); - Assert.AreEqual(0, result); + result = typeof(int).GetDefaultValue(); + Assert.AreEqual(0, result); - result = typeof(TestClass).GetDefaultValue(); - Assert.IsNull(result); - } + result = typeof(TestClass).GetDefaultValue(); + Assert.IsNull(result); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/ExtensionMethods/StringExtensionsTests.cs b/Tests/Jinget.Core.Tests/ExtensionMethods/StringExtensionsTests.cs index da09623..f30cd08 100644 --- a/Tests/Jinget.Core.Tests/ExtensionMethods/StringExtensionsTests.cs +++ b/Tests/Jinget.Core.Tests/ExtensionMethods/StringExtensionsTests.cs @@ -2,37 +2,36 @@ using Jinget.Core.ExtensionMethods.Database.SqlClient; using Jinget.Core.ExtensionMethods; -namespace Jinget.Core.Tests.ExtensionMethods.Database.SqlClient +namespace Jinget.Core.Tests.ExtensionMethods.Database.SqlClient; + +[TestClass] +public class StringExtensionsTests { - [TestClass] - public class StringExtensionsTests + [TestMethod()] + public void should_replace_arabic_YeKe_in_string_with_its_farsi_equalivants() { - [TestMethod()] - public void should_replace_arabic_YeKe_in_string_with_its_farsi_equalivants() - { - string input = "Sample text with علي and روشنك"; - string expected = "Sample text with علی and روشنک"; + string input = "Sample text with علي and روشنك"; + string expected = "Sample text with علی and روشنک"; - input = input.ApplyCorrectYeKe(); + input = input.ApplyCorrectYeKe(); - Assert.AreEqual(expected, input); - } + Assert.AreEqual(expected, input); + } - [TestMethod()] - public void should_return_empty_string() - { - Assert.IsTrue("".ApplyCorrectYeKe() == string.Empty); - Assert.IsTrue(" ".ApplyCorrectYeKe() == string.Empty); - Assert.IsTrue(string.Empty.ApplyCorrectYeKe() == string.Empty); - } + [TestMethod()] + public void should_return_empty_string() + { + Assert.IsTrue("".ApplyCorrectYeKe() == string.Empty); + Assert.IsTrue(" ".ApplyCorrectYeKe() == string.Empty); + Assert.IsTrue(string.Empty.ApplyCorrectYeKe() == string.Empty); + } - [TestMethod()] - public void should_return_CamelCase_string() - { - string input = "Vahid Farahmandian"; - string expectedResult = "vahid Farahmandian"; - string result = input.ToCamelCase(); - Assert.AreEqual(expectedResult, result); - } + [TestMethod()] + public void should_return_CamelCase_string() + { + string input = "Vahid Farahmandian"; + string expectedResult = "vahid Farahmandian"; + string result = input.ToCamelCase(); + Assert.AreEqual(expectedResult, result); } } diff --git a/Tests/Jinget.Core.Tests/Operators/GenericEqualityOperatorTests.cs b/Tests/Jinget.Core.Tests/Operators/GenericEqualityOperatorTests.cs index 5293b2f..caf66b6 100644 --- a/Tests/Jinget.Core.Tests/Operators/GenericEqualityOperatorTests.cs +++ b/Tests/Jinget.Core.Tests/Operators/GenericEqualityOperatorTests.cs @@ -1,20 +1,19 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Jinget.Core.Tests._BaseData; -namespace Jinget.Core.Operators.Tests +namespace Jinget.Core.Operators.Tests; + +[TestClass()] +public class GenericEqualityOperatorTests { - [TestClass()] - public class GenericEqualityOperatorTests + class Test where T : struct + { + public bool AreEqual() => GenericEqualityOperator.AreEqual(new SampleGeneric().Id, default); + } + [TestMethod()] + public void should_return_true_for_same_generic_values() { - class Test where T : struct - { - public bool AreEqual() => GenericEqualityOperator.AreEqual(new SampleGeneric().Id, default); - } - [TestMethod()] - public void should_return_true_for_same_generic_values() - { - bool result = new Test().AreEqual(); - Assert.IsTrue(result); - } + bool result = new Test().AreEqual(); + Assert.IsTrue(result); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/Security/AES/AESManagerTests.cs b/Tests/Jinget.Core.Tests/Security/AES/AESManagerTests.cs index 2cc0039..1036d62 100644 --- a/Tests/Jinget.Core.Tests/Security/AES/AESManagerTests.cs +++ b/Tests/Jinget.Core.Tests/Security/AES/AESManagerTests.cs @@ -1,31 +1,30 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace Jinget.Core.Security.AES.Tests +namespace Jinget.Core.Security.AES.Tests; + +[TestClass()] +public class AESManagerTests { - [TestClass()] - public class AESManagerTests + [TestMethod()] + public void should_encrypt_the_string_using_given_key_and_iv() { - [TestMethod()] - public void should_encrypt_the_string_using_given_key_and_iv() - { - string input = "vahid"; - string key = "12345678901234567890123456789012"; - string iv = "1234567890123456"; - string expectedResult = "sQyEKQhH++6olei3SXbWag=="; - var result = AESManager.Encrypt(input, key, iv); + string input = "vahid"; + string key = "12345678901234567890123456789012"; + string iv = "1234567890123456"; + string expectedResult = "sQyEKQhH++6olei3SXbWag=="; + var result = AESManager.Encrypt(input, key, iv); - Assert.AreEqual(expectedResult, result); - } + Assert.AreEqual(expectedResult, result); + } - [TestMethod()] - public void should_decrypt_the_string_using_given_key_and_iv() - { - string encryptedInput = "sQyEKQhH++6olei3SXbWag=="; - string key = "12345678901234567890123456789012"; - string iv = "1234567890123456"; - string expectedResult = "vahid"; - var result = AESManager.Decrypt(encryptedInput, key, iv); - Assert.AreEqual(expectedResult, result); - } + [TestMethod()] + public void should_decrypt_the_string_using_given_key_and_iv() + { + string encryptedInput = "sQyEKQhH++6olei3SXbWag=="; + string key = "12345678901234567890123456789012"; + string iv = "1234567890123456"; + string expectedResult = "vahid"; + var result = AESManager.Decrypt(encryptedInput, key, iv); + Assert.AreEqual(expectedResult, result); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/Security/Hashing/HashManagerTests.cs b/Tests/Jinget.Core.Tests/Security/Hashing/HashManagerTests.cs index 2471f5b..7e512f8 100644 --- a/Tests/Jinget.Core.Tests/Security/Hashing/HashManagerTests.cs +++ b/Tests/Jinget.Core.Tests/Security/Hashing/HashManagerTests.cs @@ -1,40 +1,39 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Jinget.Core.Security.Hashing.Model; -namespace Jinget.Core.Security.Hashing.Tests +namespace Jinget.Core.Security.Hashing.Tests; + +[TestClass()] +public class HashManagerTests { - [TestClass()] - public class HashManagerTests + [TestMethod()] + public void should_compare_given_input_with_its_hashed_value_and_return_true() + { + string input = "vahid"; + HashModel hashedResult = new HashManager().Hash(input); + + var result = new HashManager().AreEqual(hashedResult, input); + + Assert.IsTrue(result); + } + + [TestMethod()] + public void should_hash_input_with_random_generated_salt() { - [TestMethod()] - public void should_compare_given_input_with_its_hashed_value_and_return_true() - { - string input = "vahid"; - HashModel hashedResult = new HashManager().Hash(input); - - var result = new HashManager().AreEqual(hashedResult, input); - - Assert.IsTrue(result); - } - - [TestMethod()] - public void should_hash_input_with_random_generated_salt() - { - string input = "vahid"; - HashModel result = new HashManager().Hash(input); - - Assert.IsFalse(string.IsNullOrWhiteSpace(result.Salt)); - Assert.IsFalse(string.IsNullOrWhiteSpace(result.HashedValue)); - } - - [TestMethod()] - public void should_hash_input_with_specific_salt() - { - string input = "vahid"; - string inputsalt = "qsc7Y/0LN/8lKGu409KBRw=="; - string result = new HashManager().Hash(input, inputsalt); - - Assert.IsFalse(string.IsNullOrWhiteSpace(result)); - } + string input = "vahid"; + HashModel result = new HashManager().Hash(input); + + Assert.IsFalse(string.IsNullOrWhiteSpace(result.Salt)); + Assert.IsFalse(string.IsNullOrWhiteSpace(result.HashedValue)); + } + + [TestMethod()] + public void should_hash_input_with_specific_salt() + { + string input = "vahid"; + string inputsalt = "qsc7Y/0LN/8lKGu409KBRw=="; + string result = new HashManager().Hash(input, inputsalt); + + Assert.IsFalse(string.IsNullOrWhiteSpace(result)); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/Security/SqlInjection/SqlInjectionTests.cs b/Tests/Jinget.Core.Tests/Security/SqlInjection/SqlInjectionTests.cs index 2d1afd6..51cee87 100644 --- a/Tests/Jinget.Core.Tests/Security/SqlInjection/SqlInjectionTests.cs +++ b/Tests/Jinget.Core.Tests/Security/SqlInjection/SqlInjectionTests.cs @@ -1,18 +1,17 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace Jinget.Core.Security.SqlInjection.Tests +namespace Jinget.Core.Security.SqlInjection.Tests; + +[TestClass()] +public class SqlInjectionTests { - [TestClass()] - public class SqlInjectionTests + [TestMethod()] + public void should_immunize_string() { - [TestMethod()] - public void should_immunize_string() - { - string input = ""; - string expectedResult = "var x=0"; - string result = SqlInjection.SecureString(input); + string input = ""; + string expectedResult = "var x=0"; + string result = SqlInjection.SecureString(input); - Assert.AreEqual(expectedResult, result); - } + Assert.AreEqual(expectedResult, result); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/Utilities/BooleanUtilityTests.cs b/Tests/Jinget.Core.Tests/Utilities/BooleanUtilityTests.cs index e513f5f..3798c7b 100644 --- a/Tests/Jinget.Core.Tests/Utilities/BooleanUtilityTests.cs +++ b/Tests/Jinget.Core.Tests/Utilities/BooleanUtilityTests.cs @@ -2,29 +2,28 @@ using System; using System.Linq.Expressions; -namespace Jinget.Core.Utilities.Tests +namespace Jinget.Core.Utilities.Tests; + +[TestClass()] +public class BooleanUtilityTests { - [TestClass()] - public class BooleanUtilityTests + [TestMethod()] + public void should_return_expression_contains_true_condition() { - [TestMethod()] - public void should_return_expression_contains_true_condition() - { - Expression> expectedResult = x => 1 == 1; + Expression> expectedResult = x => 1 == 1; - Expression> result = BooleanUtility.TrueCondition(); + Expression> result = BooleanUtility.TrueCondition(); - Assert.AreEqual(expectedResult.Compile()(new Core.Tests._BaseData.TestClass()), result.Compile()(new Core.Tests._BaseData.TestClass())); - } + Assert.AreEqual(expectedResult.Compile()(new Core.Tests._BaseData.TestClass()), result.Compile()(new Core.Tests._BaseData.TestClass())); + } - [TestMethod()] - public void should_return_expression_contains_false_condition() - { - Expression> expectedResult = x => 1 == 0; + [TestMethod()] + public void should_return_expression_contains_false_condition() + { + Expression> expectedResult = x => 1 == 0; - Expression> result = BooleanUtility.FalseCondition(); + Expression> result = BooleanUtility.FalseCondition(); - Assert.AreEqual(expectedResult.Compile()(new Core.Tests._BaseData.TestClass()), result.Compile()(new Core.Tests._BaseData.TestClass())); - } + Assert.AreEqual(expectedResult.Compile()(new Core.Tests._BaseData.TestClass()), result.Compile()(new Core.Tests._BaseData.TestClass())); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/Utilities/Compression/ZipUtilityTests.cs b/Tests/Jinget.Core.Tests/Utilities/Compression/ZipUtilityTests.cs index d2842c9..4c60558 100644 --- a/Tests/Jinget.Core.Tests/Utilities/Compression/ZipUtilityTests.cs +++ b/Tests/Jinget.Core.Tests/Utilities/Compression/ZipUtilityTests.cs @@ -4,79 +4,78 @@ using System.IO; using System; -namespace Jinget.Core.Utilities.Compression.Tests +namespace Jinget.Core.Utilities.Compression.Tests; + +[TestClass()] +public class ZipUtilityTests { - [TestClass()] - public class ZipUtilityTests - { - ZipUtility zip; - [TestInitialize] - public void Initialize() => zip = new ZipUtility(); + ZipUtility zip; + [TestInitialize] + public void Initialize() => zip = new ZipUtility(); - [TestMethod()] - public async Task should_compress_and_chunkAsync() - { - FileInfo file = new("sample.txt"); - int maxDOP = 5; - int eachFileMaxSize = 4; + [TestMethod()] + public async Task should_compress_and_chunkAsync() + { + FileInfo file = new("sample.txt"); + int maxDOP = 5; + int eachFileMaxSize = 4; - List files = [file]; - await zip.CompressAsync([.. files], files[0].DirectoryName, maxDOP, eachFileMaxSize); + List files = [file]; + await zip.CompressAsync([.. files], files[0].DirectoryName, maxDOP, eachFileMaxSize); - Assert.IsTrue(file.Directory.GetFiles("sample.txt.z??").Length != 0); - } + Assert.IsTrue(file.Directory.GetFiles("sample.txt.z??").Length != 0); + } - [TestMethod()] - public async Task should_compress_using_password_and_chunkAsync() - { - FileInfo file = new("sample.txt"); - string password = "123"; - List files = [file]; - await zip.CompressAsync([.. files], files[0].DirectoryName, password: password); + [TestMethod()] + public async Task should_compress_using_password_and_chunkAsync() + { + FileInfo file = new("sample.txt"); + string password = "123"; + List files = [file]; + await zip.CompressAsync([.. files], files[0].DirectoryName, password: password); - Assert.IsTrue(file.Directory.GetFiles("sample.txt.z??").Length != 0); - } + Assert.IsTrue(file.Directory.GetFiles("sample.txt.z??").Length != 0); + } - [TestMethod()] - public async Task should_decompressed_fileAsync() + [TestMethod()] + public async Task should_decompressed_fileAsync() + { + string fileName = Guid.NewGuid() + ".txt"; + using (var tw = new StreamWriter(fileName, true)) { - string fileName = Guid.NewGuid() + ".txt"; - using (var tw = new StreamWriter(fileName, true)) - { - await tw.WriteLineAsync("sample text"); - } - string password = "123"; - var tobeCompressed = new FileInfo[] { new(fileName) }; - await zip.CompressAsync(tobeCompressed, tobeCompressed[0].DirectoryName, password: password); - File.Delete(fileName); + await tw.WriteLineAsync("sample text"); + } + string password = "123"; + var tobeCompressed = new FileInfo[] { new(fileName) }; + await zip.CompressAsync(tobeCompressed, tobeCompressed[0].DirectoryName, password: password); + File.Delete(fileName); - FileInfo file = new($"{fileName}.zip"); - int maxDOP = 5; + FileInfo file = new($"{fileName}.zip"); + int maxDOP = 5; - List files = [file]; - await zip.DecompressAsync([.. files], files[0].DirectoryName, maxDOP); + List files = [file]; + await zip.DecompressAsync([.. files], files[0].DirectoryName, maxDOP); - Assert.IsTrue(file.Directory.GetFiles(fileName).Length != 0); - } + Assert.IsTrue(file.Directory.GetFiles(fileName).Length != 0); + } - [TestMethod()] - public async Task should_decompressed_using_passwordAsync() + [TestMethod()] + public async Task should_decompressed_using_passwordAsync() + { + string fileName = Guid.NewGuid() + ".txt"; + using (var tw = new StreamWriter(fileName, true)) { - string fileName = Guid.NewGuid() + ".txt"; - using (var tw = new StreamWriter(fileName, true)) - { - await tw.WriteLineAsync("sample text"); - } - string password = "123"; - var tobeCompressed = new FileInfo[] { new(fileName) }; - await zip.CompressAsync(tobeCompressed, tobeCompressed[0].DirectoryName, password: password); - File.Delete(fileName); + await tw.WriteLineAsync("sample text"); + } + string password = "123"; + var tobeCompressed = new FileInfo[] { new(fileName) }; + await zip.CompressAsync(tobeCompressed, tobeCompressed[0].DirectoryName, password: password); + File.Delete(fileName); - FileInfo file = new($"{fileName}.zip"); - List files = [file]; - await zip.DecompressAsync([.. files], files[0].DirectoryName, password: password); + FileInfo file = new($"{fileName}.zip"); + List files = [file]; + await zip.DecompressAsync([.. files], files[0].DirectoryName, password: password); - Assert.IsTrue(file.Directory.GetFiles(fileName).Length != 0); - } + Assert.IsTrue(file.Directory.GetFiles(fileName).Length != 0); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/Utilities/DateTimeUtilityTests.cs b/Tests/Jinget.Core.Tests/Utilities/DateTimeUtilityTests.cs index bf76de6..906d69d 100644 --- a/Tests/Jinget.Core.Tests/Utilities/DateTimeUtilityTests.cs +++ b/Tests/Jinget.Core.Tests/Utilities/DateTimeUtilityTests.cs @@ -1,132 +1,131 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using System; -namespace Jinget.Core.Utilities.Tests +namespace Jinget.Core.Utilities.Tests; + +[TestClass()] +public class DateTimeUtilityTests { - [TestClass()] - public class DateTimeUtilityTests + [TestMethod()] + public void should_return_solar_date() + { + string expectedResult = "1399/07/21"; + + DateTime input = new(2020, 10, 12); + + var result = DateTimeUtility.ToSolarDate(input); + + Assert.AreEqual(expectedResult, result); + } + + [TestMethod()] + [ExpectedException(typeof(ArgumentOutOfRangeException))] + public void should_throw_exception_for_out_of_supported_range_date() + { + DateTime input = DateTime.MinValue; + DateTimeUtility.ToSolarDate(input); + } + + [TestMethod()] + public void should_return_gregorian_date() { - [TestMethod()] - public void should_return_solar_date() - { - string expectedResult = "1399/07/21"; - - DateTime input = new(2020, 10, 12); + DateTime expectedResult = new(2020, 10, 12); + + string input = "1399/07/21"; + + var result = DateTimeUtility.ToGregorianDate(input); + + Assert.AreEqual(expectedResult, result); + } + + [TestMethod()] + public void should_return_timespan() + { + TimeSpan expectedResult = new(2, 30, 0); + + int input = 150; + + var result = DateTimeUtility.ParseToTime(input); + + Assert.AreEqual(expectedResult, result); + } + + [TestMethod()] + public void should_return_true_for_valid_persian_date() + { + string input = "14010101"; + Assert.IsTrue(DateTimeUtility.IsValidPersianDate(input)); + + input = "14100101"; + Assert.IsTrue(DateTimeUtility.IsValidPersianDate(input)); - var result = DateTimeUtility.ToSolarDate(input); - - Assert.AreEqual(expectedResult, result); - } - - [TestMethod()] - [ExpectedException(typeof(ArgumentOutOfRangeException))] - public void should_throw_exception_for_out_of_supported_range_date() - { - DateTime input = DateTime.MinValue; - DateTimeUtility.ToSolarDate(input); - } - - [TestMethod()] - public void should_return_gregorian_date() - { - DateTime expectedResult = new(2020, 10, 12); - - string input = "1399/07/21"; - - var result = DateTimeUtility.ToGregorianDate(input); - - Assert.AreEqual(expectedResult, result); - } - - [TestMethod()] - public void should_return_timespan() - { - TimeSpan expectedResult = new(2, 30, 0); - - int input = 150; - - var result = DateTimeUtility.ParseToTime(input); - - Assert.AreEqual(expectedResult, result); - } - - [TestMethod()] - public void should_return_true_for_valid_persian_date() - { - string input = "14010101"; - Assert.IsTrue(DateTimeUtility.IsValidPersianDate(input)); - - input = "14100101"; - Assert.IsTrue(DateTimeUtility.IsValidPersianDate(input)); - - input = "00010101"; - Assert.IsTrue(DateTimeUtility.IsValidPersianDate(input)); - } - - [TestMethod()] - public void should_return_true_for_valid_persian_date_in_given_range() - { - string input = "14010101"; - string minDate = "13500101"; - string maxDate = "14030101"; - Assert.IsTrue(DateTimeUtility.IsValidPersianDate(input, minDate, maxDate)); - - input = "14010101"; - Assert.IsTrue(DateTimeUtility.IsValidPersianDate(input, minDate)); - - input = "14010101"; - Assert.IsTrue(DateTimeUtility.IsValidPersianDate(input, maxAcceptableDate: maxDate)); - } - - [TestMethod()] - public void should_return_false_for_invalid_persian_date() - { - string input = "1401011"; - Assert.IsFalse(DateTimeUtility.IsValidPersianDate(input)); - - input = "-14020101"; - Assert.IsFalse(DateTimeUtility.IsValidPersianDate(input)); - } - - [TestMethod()] - public void should_return_false_for_persian_date_outside_given_range() - { - string input = "13820101"; - string minDate = "13900101"; - string maxDate = "14030101"; - Assert.IsFalse(DateTimeUtility.IsValidPersianDate(input, minDate, maxDate)); - - input = "13891201"; - Assert.IsFalse(DateTimeUtility.IsValidPersianDate(input, minDate)); - - input = "14040101"; - Assert.IsFalse(DateTimeUtility.IsValidPersianDate(input, maxAcceptableDate: maxDate)); - } - - [TestMethod()] - public void Should_format_string_based_on_newFormat_slash() - { - string input = "14020901"; - string currentFormat = "yyyyMMdd"; - string newFormat = "yyyy/MM/dd"; - string expectedResult = "1402/09/01"; + input = "00010101"; + Assert.IsTrue(DateTimeUtility.IsValidPersianDate(input)); + } + + [TestMethod()] + public void should_return_true_for_valid_persian_date_in_given_range() + { + string input = "14010101"; + string minDate = "13500101"; + string maxDate = "14030101"; + Assert.IsTrue(DateTimeUtility.IsValidPersianDate(input, minDate, maxDate)); + + input = "14010101"; + Assert.IsTrue(DateTimeUtility.IsValidPersianDate(input, minDate)); + + input = "14010101"; + Assert.IsTrue(DateTimeUtility.IsValidPersianDate(input, maxAcceptableDate: maxDate)); + } + + [TestMethod()] + public void should_return_false_for_invalid_persian_date() + { + string input = "1401011"; + Assert.IsFalse(DateTimeUtility.IsValidPersianDate(input)); + + input = "-14020101"; + Assert.IsFalse(DateTimeUtility.IsValidPersianDate(input)); + } + + [TestMethod()] + public void should_return_false_for_persian_date_outside_given_range() + { + string input = "13820101"; + string minDate = "13900101"; + string maxDate = "14030101"; + Assert.IsFalse(DateTimeUtility.IsValidPersianDate(input, minDate, maxDate)); + + input = "13891201"; + Assert.IsFalse(DateTimeUtility.IsValidPersianDate(input, minDate)); + + input = "14040101"; + Assert.IsFalse(DateTimeUtility.IsValidPersianDate(input, maxAcceptableDate: maxDate)); + } + + [TestMethod()] + public void Should_format_string_based_on_newFormat_slash() + { + string input = "14020901"; + string currentFormat = "yyyyMMdd"; + string newFormat = "yyyy/MM/dd"; + string expectedResult = "1402/09/01"; + + string result = DateTimeUtility.Format(input, currentFormat, newFormat); + + Assert.AreEqual(expectedResult, result); + } + + [TestMethod()] + public void Should_format_string_based_on_newFormat_hyphen() + { + string input = "1402/09/01"; + string currentFormat = "yyyy/MM/dd"; + string newFormat = "yyyy-MM-dd"; + string expectedResult = "1402-09-01"; - string result = DateTimeUtility.Format(input, currentFormat, newFormat); - - Assert.AreEqual(expectedResult, result); - } - - [TestMethod()] - public void Should_format_string_based_on_newFormat_hyphen() - { - string input = "1402/09/01"; - string currentFormat = "yyyy/MM/dd"; - string newFormat = "yyyy-MM-dd"; - string expectedResult = "1402-09-01"; - - string result = DateTimeUtility.Format(input, currentFormat, newFormat); + string result = DateTimeUtility.Format(input, currentFormat, newFormat); - Assert.AreEqual(expectedResult, result); - } + Assert.AreEqual(expectedResult, result); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/Utilities/Expressions/ExpressionUtilityTests.cs b/Tests/Jinget.Core.Tests/Utilities/Expressions/ExpressionUtilityTests.cs index df7d434..64223b7 100644 --- a/Tests/Jinget.Core.Tests/Utilities/Expressions/ExpressionUtilityTests.cs +++ b/Tests/Jinget.Core.Tests/Utilities/Expressions/ExpressionUtilityTests.cs @@ -7,257 +7,256 @@ using Jinget.Core.Utilities.Expressions; using Jinget.Core.Types; -namespace Jinget.Core.ExtensionMethods.Expressions.Tests +namespace Jinget.Core.ExtensionMethods.Expressions.Tests; + +[TestClass()] +public class ExpressionUtilityTests { - [TestClass()] - public class ExpressionUtilityTests + [TestMethod()] + public void should_create_a_member_init_expression() { - [TestMethod()] - public void should_create_a_member_init_expression() - { - string[] inputs = ["Property1", "Property2"]; - string parameterName = "x"; - Expression> expectedExpression = x => new TestClass { Property1 = x.Property1, Property2 = x.Property2 }; + string[] inputs = ["Property1", "Property2"]; + string parameterName = "x"; + Expression> expectedExpression = x => new TestClass { Property1 = x.Property1, Property2 = x.Property2 }; - Expression> result = ExpressionUtility.CreateMemberInitExpression(parameterName, inputs); + Expression> result = ExpressionUtility.CreateMemberInitExpression(parameterName, inputs); - Assert.AreEqual(expectedExpression.Type, result.Type); - } + Assert.AreEqual(expectedExpression.Type, result.Type); + } - //[TestMethod()] - //public void should_create_a_member_access_expression() - //{ - // string[] inputs = ["Property1", "Property2"]; - // string parameterName = "x"; - // Expression> expectedExpression = x => new TestClass { Property1 = x.Property1, Property2 = x.Property2 }; + //[TestMethod()] + //public void should_create_a_member_access_expression() + //{ + // string[] inputs = ["Property1", "Property2"]; + // string parameterName = "x"; + // Expression> expectedExpression = x => new TestClass { Property1 = x.Property1, Property2 = x.Property2 }; - // Expression> result = ExpressionUtility.CreateMemberInitExpression(parameterName, inputs); + // Expression> result = ExpressionUtility.CreateMemberInitExpression(parameterName, inputs); - // Assert.AreEqual(expectedExpression.Type, result.Type); - //} + // Assert.AreEqual(expectedExpression.Type, result.Type); + //} - [TestMethod()] - public void should_create_a_equal_condition_expression() - { - Expression> expectedResult = x => x.Property1 == 1; - var result = ExpressionUtility.CreateEqualCondition("Property1", 1, "x"); + [TestMethod()] + public void should_create_a_equal_condition_expression() + { + Expression> expectedResult = x => x.Property1 == 1; + var result = ExpressionUtility.CreateEqualCondition("Property1", 1, "x"); - Assert.AreEqual(expectedResult.Type, result.Type); - } + Assert.AreEqual(expectedResult.Type, result.Type); + } - #region null or empty filters + #region null or empty filters - [TestMethod] - public void should_return_all_data_using_empty_string_filter() - { - string json = ""; - string expectedFilter = "x => True"; - var data = new List - { - new() { Property1=1, Property2="ali", Property3="tehran" ,Property4=true}, - new() { Property1=2, Property2="rahim", Property3="karaj" ,Property4=true}, - new() { Property1=3, Property2="vahid", Property3="urmia" ,Property4=false}, - new() { Property1=4, Property2="saeid", Property3="urmia" ,Property4=true}, - new() { Property1=5, Property2="maryam", Property3="urmia" ,Property4=false } - }.AsQueryable(); - - var filter = ExpressionUtility.ConstructBinaryExpression(json); - Assert.AreEqual(expectedFilter, filter.ToString()); - - var result = data.Where(filter).ToList(); - Assert.IsTrue(result.Count == 5); - } - - [TestMethod] - public void should_return_no_data_using_empty_string_filter() + [TestMethod] + public void should_return_all_data_using_empty_string_filter() + { + string json = ""; + string expectedFilter = "x => True"; + var data = new List { + new() { Property1=1, Property2="ali", Property3="tehran" ,Property4=true}, + new() { Property1=2, Property2="rahim", Property3="karaj" ,Property4=true}, + new() { Property1=3, Property2="vahid", Property3="urmia" ,Property4=false}, + new() { Property1=4, Property2="saeid", Property3="urmia" ,Property4=true}, + new() { Property1=5, Property2="maryam", Property3="urmia" ,Property4=false } + }.AsQueryable(); + + var filter = ExpressionUtility.ConstructBinaryExpression(json); + Assert.AreEqual(expectedFilter, filter.ToString()); + + var result = data.Where(filter).ToList(); + Assert.IsTrue(result.Count == 5); + } + + [TestMethod] + public void should_return_no_data_using_empty_string_filter() + { #nullable enable - object? json = ""; + object? json = ""; #nullable disable - string expectedFilter = "x => False"; + string expectedFilter = "x => False"; - var data = new List - { - new() { Property1=1, Property2="ali", Property3="tehran" ,Property4=true}, - new() { Property1=2, Property2="rahim", Property3="karaj" ,Property4=true}, - new() { Property1=3, Property2="vahid", Property3="urmia" ,Property4=false}, - new() { Property1=4, Property2="saeid", Property3="urmia" ,Property4=true}, - new() { Property1=5, Property2="maryam", Property3="urmia" ,Property4=false } - }.AsQueryable(); - - var filter = ExpressionUtility.ConstructBinaryExpression(json, false); - Assert.AreEqual(expectedFilter, filter.ToString()); - - var result = data.Where(filter).ToList(); - Assert.IsTrue(result.Count == 0); - } - - [TestMethod] - public void should_return_all_data_using_null_object() + var data = new List { + new() { Property1=1, Property2="ali", Property3="tehran" ,Property4=true}, + new() { Property1=2, Property2="rahim", Property3="karaj" ,Property4=true}, + new() { Property1=3, Property2="vahid", Property3="urmia" ,Property4=false}, + new() { Property1=4, Property2="saeid", Property3="urmia" ,Property4=true}, + new() { Property1=5, Property2="maryam", Property3="urmia" ,Property4=false } + }.AsQueryable(); + + var filter = ExpressionUtility.ConstructBinaryExpression(json, false); + Assert.AreEqual(expectedFilter, filter.ToString()); + + var result = data.Where(filter).ToList(); + Assert.IsTrue(result.Count == 0); + } + + [TestMethod] + public void should_return_all_data_using_null_object() + { #nullable enable - object? json = null; + object? json = null; #nullable disable - string expectedFilter = "x => True"; + string expectedFilter = "x => True"; - var data = new List - { - new() { Property1=1, Property2="ali", Property3="tehran" ,Property4=true}, - new() { Property1=2, Property2="rahim", Property3="karaj" ,Property4=true}, - new() { Property1=3, Property2="vahid", Property3="urmia" ,Property4=false}, - new() { Property1=4, Property2="saeid", Property3="urmia" ,Property4=true}, - new() { Property1=5, Property2="maryam", Property3="urmia" ,Property4=false } - }.AsQueryable(); + var data = new List + { + new() { Property1=1, Property2="ali", Property3="tehran" ,Property4=true}, + new() { Property1=2, Property2="rahim", Property3="karaj" ,Property4=true}, + new() { Property1=3, Property2="vahid", Property3="urmia" ,Property4=false}, + new() { Property1=4, Property2="saeid", Property3="urmia" ,Property4=true}, + new() { Property1=5, Property2="maryam", Property3="urmia" ,Property4=false } + }.AsQueryable(); - var filter = ExpressionUtility.ConstructBinaryExpression(json); - Assert.AreEqual(expectedFilter, filter.ToString()); + var filter = ExpressionUtility.ConstructBinaryExpression(json); + Assert.AreEqual(expectedFilter, filter.ToString()); - var result = data.Where(filter).ToList(); + var result = data.Where(filter).ToList(); - Assert.IsTrue(result.Count == 5); - Assert.IsTrue(result.First().Property1 == 1); - } + Assert.IsTrue(result.Count == 5); + Assert.IsTrue(result.First().Property1 == 1); + } - [TestMethod] - public void should_return_no_data_using_null_object() - { + [TestMethod] + public void should_return_no_data_using_null_object() + { #nullable enable - object? json = null; + object? json = null; #nullable disable - string expectedFilter = "x => False"; + string expectedFilter = "x => False"; - var data = new List - { - new() { Property1=1, Property2="ali", Property3="tehran" ,Property4=true}, - new() { Property1=2, Property2="rahim", Property3="karaj" ,Property4=true}, - new() { Property1=3, Property2="vahid", Property3="urmia" ,Property4=false}, - new() { Property1=4, Property2="saeid", Property3="urmia" ,Property4=true}, - new() { Property1=5, Property2="maryam", Property3="urmia" ,Property4=false } - }.AsQueryable(); - - var filter = ExpressionUtility.ConstructBinaryExpression(json, false); - Assert.AreEqual(expectedFilter, filter.ToString()); - - var result = data.Where(filter).ToList(); - Assert.IsTrue(result.Count == 0); - } + var data = new List + { + new() { Property1=1, Property2="ali", Property3="tehran" ,Property4=true}, + new() { Property1=2, Property2="rahim", Property3="karaj" ,Property4=true}, + new() { Property1=3, Property2="vahid", Property3="urmia" ,Property4=false}, + new() { Property1=4, Property2="saeid", Property3="urmia" ,Property4=true}, + new() { Property1=5, Property2="maryam", Property3="urmia" ,Property4=false } + }.AsQueryable(); + + var filter = ExpressionUtility.ConstructBinaryExpression(json, false); + Assert.AreEqual(expectedFilter, filter.ToString()); + + var result = data.Where(filter).ToList(); + Assert.IsTrue(result.Count == 0); + } - #endregion + #endregion - #region json string filter + #region json string filter - [TestMethod] - public void should_return_filtered_data_using_json_filter() - { - string json = @"{ + [TestMethod] + public void should_return_filtered_data_using_json_filter() + { + string json = @"{ 'Property3':'urmia', 'Property4':true }"; - string expectedFilter = "x => ((x.Property3 == \"urmia\") AndAlso (x.Property4 == True))"; + string expectedFilter = "x => ((x.Property3 == \"urmia\") AndAlso (x.Property4 == True))"; - var data = new List - { - new() { Property1=1, Property2="ali", Property3="tehran" ,Property4=true}, - new() { Property1=2, Property2="rahim", Property3="karaj" ,Property4=true}, - new() { Property1=3, Property2="vahid", Property3="urmia" ,Property4=false}, - new() { Property1=4, Property2="saeid", Property3="urmia" ,Property4=true}, - new() { Property1=5, Property2="maryam", Property3="urmia" ,Property4=false } - }.AsQueryable(); + var data = new List + { + new() { Property1=1, Property2="ali", Property3="tehran" ,Property4=true}, + new() { Property1=2, Property2="rahim", Property3="karaj" ,Property4=true}, + new() { Property1=3, Property2="vahid", Property3="urmia" ,Property4=false}, + new() { Property1=4, Property2="saeid", Property3="urmia" ,Property4=true}, + new() { Property1=5, Property2="maryam", Property3="urmia" ,Property4=false } + }.AsQueryable(); - var filter = ExpressionUtility.ConstructBinaryExpression(json); - Assert.AreEqual(expectedFilter, filter.ToString()); + var filter = ExpressionUtility.ConstructBinaryExpression(json); + Assert.AreEqual(expectedFilter, filter.ToString()); - var result = data.Where(filter).ToList(); + var result = data.Where(filter).ToList(); - Assert.IsTrue(result.Count == 1); - Assert.IsTrue(result.First().Property1 == 4); - } + Assert.IsTrue(result.Count == 1); + Assert.IsTrue(result.First().Property1 == 4); + } - #endregion + #endregion - #region filter criteria + #region filter criteria - [TestMethod] - public void should_return_filtered_data_using_single_filter_criteria() - { - List filters = - [ - new() - { - Operand = "Property2", - Operator = Enumerations.Operator.Contains, - Value = "ah" - } - ]; - string expectedFilter = "x => x.Property2.Contains(\"ah\")"; - - var data = new List + [TestMethod] + public void should_return_filtered_data_using_single_filter_criteria() + { + List filters = + [ + new() { - new() { Property1=1, Property2="ali", Property3="tehran" ,Property4=true}, - new() { Property1=2, Property2="rahim", Property3="karaj" ,Property4=true}, - new() { Property1=3, Property2="vahid", Property3="urmia" ,Property4=false}, - new() { Property1=4, Property2="saeid", Property3="urmia" ,Property4=true}, - new() { Property1=5, Property2="maryam", Property3="urmia" ,Property4=false } - }.AsQueryable(); + Operand = "Property2", + Operator = Enumerations.Operator.Contains, + Value = "ah" + } + ]; + string expectedFilter = "x => x.Property2.Contains(\"ah\")"; + + var data = new List + { + new() { Property1=1, Property2="ali", Property3="tehran" ,Property4=true}, + new() { Property1=2, Property2="rahim", Property3="karaj" ,Property4=true}, + new() { Property1=3, Property2="vahid", Property3="urmia" ,Property4=false}, + new() { Property1=4, Property2="saeid", Property3="urmia" ,Property4=true}, + new() { Property1=5, Property2="maryam", Property3="urmia" ,Property4=false } + }.AsQueryable(); - var filter = ExpressionUtility.ConstructBinaryExpression(filters); - Assert.AreEqual(expectedFilter, filter.ToString()); + var filter = ExpressionUtility.ConstructBinaryExpression(filters); + Assert.AreEqual(expectedFilter, filter.ToString()); - var result = data.Where(filter).ToList(); + var result = data.Where(filter).ToList(); - Assert.IsTrue(result.Count == 2); - Assert.IsTrue(result.First().Property1 == 2); - } + Assert.IsTrue(result.Count == 2); + Assert.IsTrue(result.First().Property1 == 2); + } - [TestMethod] - public void should_return_filtered_data_using_multiple_filter_criterias() - { - List filters = - [ - new() - { - Operand = "Property2", - Operator = Enumerations.Operator.Contains, - Value = "ah", - NextConditionCombination = Enumerations.ConditionCombiningType.AndAlso - }, - new() - { - Operand = "Property3", - Operator = Enumerations.Operator.Equal, - Value = "urmia", - NextConditionCombination = Enumerations.ConditionCombiningType.OrElse - }, - new() - { - Operand = "Property4", - Operator = Enumerations.Operator.Equal, - Value = true - }, - ]; - string expectedFilter = "x => ((x.Property2.Contains(\"ah\") AndAlso (x.Property3 == \"urmia\")) OrElse (x.Property4 == True))"; - - var data = new List + [TestMethod] + public void should_return_filtered_data_using_multiple_filter_criterias() + { + List filters = + [ + new() { - new() { Property1=1, Property2="ali", Property3="tehran" ,Property4=true}, - new() { Property1=2, Property2="rahim", Property3="karaj" ,Property4=true}, - new() { Property1=3, Property2="vahid", Property3="urmia" ,Property4=false}, - new() { Property1=4, Property2="saeid", Property3="urmia" ,Property4=true}, - new() { Property1=5, Property2="maryam", Property3="urmia" ,Property4=false } - }.AsQueryable(); - - var filter = ExpressionUtility.ConstructBinaryExpression(filters); - Assert.AreEqual(expectedFilter, filter.ToString()); + Operand = "Property2", + Operator = Enumerations.Operator.Contains, + Value = "ah", + NextConditionCombination = Enumerations.ConditionCombiningType.AndAlso + }, + new() + { + Operand = "Property3", + Operator = Enumerations.Operator.Equal, + Value = "urmia", + NextConditionCombination = Enumerations.ConditionCombiningType.OrElse + }, + new() + { + Operand = "Property4", + Operator = Enumerations.Operator.Equal, + Value = true + }, + ]; + string expectedFilter = "x => ((x.Property2.Contains(\"ah\") AndAlso (x.Property3 == \"urmia\")) OrElse (x.Property4 == True))"; + + var data = new List + { + new() { Property1=1, Property2="ali", Property3="tehran" ,Property4=true}, + new() { Property1=2, Property2="rahim", Property3="karaj" ,Property4=true}, + new() { Property1=3, Property2="vahid", Property3="urmia" ,Property4=false}, + new() { Property1=4, Property2="saeid", Property3="urmia" ,Property4=true}, + new() { Property1=5, Property2="maryam", Property3="urmia" ,Property4=false } + }.AsQueryable(); - var result = data.Where(filter).ToList(); + var filter = ExpressionUtility.ConstructBinaryExpression(filters); + Assert.AreEqual(expectedFilter, filter.ToString()); - Assert.IsTrue(result.Count == 4); - Assert.IsTrue(result.First().Property1 == 1); - } + var result = data.Where(filter).ToList(); - #endregion + Assert.IsTrue(result.Count == 4); + Assert.IsTrue(result.First().Property1 == 1); } + + #endregion } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/Utilities/Expressions/ReplaceExpressionVisitorTests.cs b/Tests/Jinget.Core.Tests/Utilities/Expressions/ReplaceExpressionVisitorTests.cs index ccb6696..26957b1 100644 --- a/Tests/Jinget.Core.Tests/Utilities/Expressions/ReplaceExpressionVisitorTests.cs +++ b/Tests/Jinget.Core.Tests/Utilities/Expressions/ReplaceExpressionVisitorTests.cs @@ -4,20 +4,19 @@ using System; using System.Linq.Expressions; -namespace Jinget.Core.Tests.ExtensionMethods.Expressions +namespace Jinget.Core.Tests.ExtensionMethods.Expressions; + +[TestClass] +public class ReplaceExpressionVisitorTests { - [TestClass] - public class ReplaceExpressionVisitorTests + [TestMethod] + public void should_replace_parameter_in_expression_tree() { - [TestMethod] - public void should_replace_parameter_in_expression_tree() - { - Expression> expression = x => x.Property1 > 0; - Expression> expectedResult = y => y.Property1 > 0; - ReplaceExpressionVisitor visitor = new(expression.Parameters[0], Expression.Parameter(typeof(TestClass), "y")); - var result = visitor.Visit(expression); + Expression> expression = x => x.Property1 > 0; + Expression> expectedResult = y => y.Property1 > 0; + ReplaceExpressionVisitor visitor = new(expression.Parameters[0], Expression.Parameter(typeof(TestClass), "y")); + var result = visitor.Visit(expression); - Assert.AreEqual(expectedResult.ToString(), result.ToString()); - } + Assert.AreEqual(expectedResult.ToString(), result.ToString()); } } diff --git a/Tests/Jinget.Core.Tests/Utilities/Http/HeaderUtilityTests.cs b/Tests/Jinget.Core.Tests/Utilities/Http/HeaderUtilityTests.cs index a133d8c..893d41c 100644 --- a/Tests/Jinget.Core.Tests/Utilities/Http/HeaderUtilityTests.cs +++ b/Tests/Jinget.Core.Tests/Utilities/Http/HeaderUtilityTests.cs @@ -1,76 +1,75 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Collections.Generic; -namespace Jinget.Core.Utilities.Http.Tests +namespace Jinget.Core.Utilities.Http.Tests; + +[TestClass()] +public class HeaderUtilityTests { - [TestClass()] - public class HeaderUtilityTests + [TestMethod()] + public void should_return_true_when_contenttype_exists() { - [TestMethod()] - public void should_return_true_when_contenttype_exists() + Dictionary headers = new() { - Dictionary headers = new() - { - { "content-type","some thing..." } - }; - var result = HeaderUtility.HasContentType(headers); - Assert.IsTrue(result); - } + { "content-type","some thing..." } + }; + var result = HeaderUtility.HasContentType(headers); + Assert.IsTrue(result); + } - [TestMethod()] - public void should_return_true_for_text_xml_contenttype_header() + [TestMethod()] + public void should_return_true_for_text_xml_contenttype_header() + { + Dictionary headers = new() { - Dictionary headers = new() - { - { "content-type","text/xml" } - }; - var result = HeaderUtility.IsXmlContentType(headers); - Assert.IsTrue(result); - } + { "content-type","text/xml" } + }; + var result = HeaderUtility.IsXmlContentType(headers); + Assert.IsTrue(result); + } - [TestMethod()] - public void should_return_true_for_application_xml_contenttype_header() + [TestMethod()] + public void should_return_true_for_application_xml_contenttype_header() + { + Dictionary headers = new() { - Dictionary headers = new() - { - { "content-type","application/xml" } - }; - var result = HeaderUtility.IsXmlContentType(headers); - Assert.IsTrue(result); - } + { "content-type","application/xml" } + }; + var result = HeaderUtility.IsXmlContentType(headers); + Assert.IsTrue(result); + } - [TestMethod()] - public void should_return_true_for_application_json_contenttype_header() + [TestMethod()] + public void should_return_true_for_application_json_contenttype_header() + { + Dictionary headers = new() { - Dictionary headers = new() - { - { "content-type","application/json" } - }; - var result = HeaderUtility.IsJsonContentType(headers); - Assert.IsTrue(result); - } + { "content-type","application/json" } + }; + var result = HeaderUtility.IsJsonContentType(headers); + Assert.IsTrue(result); + } - [TestMethod()] - public void should_return_false_for_non_xml_json_contenttype_header() + [TestMethod()] + public void should_return_false_for_non_xml_json_contenttype_header() + { + Dictionary headers = new() { - Dictionary headers = new() - { - { "content-type","some thing..." } - }; - var result = HeaderUtility.IsXmlContentType(headers); - Assert.IsFalse(result); - } + { "content-type","some thing..." } + }; + var result = HeaderUtility.IsXmlContentType(headers); + Assert.IsFalse(result); + } - [TestMethod()] - public void should_return_contenttype_header_name() + [TestMethod()] + public void should_return_contenttype_header_name() + { + string expectedResult = "content-type"; + Dictionary headers = new() { - string expectedResult = "content-type"; - Dictionary headers = new() - { - { "content-type","some thing..." } - }; - var result = HeaderUtility.GetContentTypeHeaderName(headers); - Assert.AreEqual(result, expectedResult); - } + { "content-type","some thing..." } + }; + var result = HeaderUtility.GetContentTypeHeaderName(headers); + Assert.AreEqual(result, expectedResult); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/Utilities/Http/MimeTypeMapTests.cs b/Tests/Jinget.Core.Tests/Utilities/Http/MimeTypeMapTests.cs index 323f7cd..eeb8654 100644 --- a/Tests/Jinget.Core.Tests/Utilities/Http/MimeTypeMapTests.cs +++ b/Tests/Jinget.Core.Tests/Utilities/Http/MimeTypeMapTests.cs @@ -1,30 +1,29 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace Jinget.Core.Utilities.Http.Tests +namespace Jinget.Core.Utilities.Http.Tests; + +[TestClass()] +public class MimeTypeMapTests { - [TestClass()] - public class MimeTypeMapTests + [TestMethod()] + public void should_try_return_valid_mimetype_for_givent_filename() { - [TestMethod()] - public void should_try_return_valid_mimetype_for_givent_filename() - { - bool result = MimeTypeMap.TryGetMimeType("sample.txt", out string mimeType); - Assert.IsTrue(result); - Assert.AreEqual("text/plain", mimeType); - } + bool result = MimeTypeMap.TryGetMimeType("sample.txt", out string mimeType); + Assert.IsTrue(result); + Assert.AreEqual("text/plain", mimeType); + } - [TestMethod()] - public void should_return_valid_mimetype_for_givent_filename() - { - string result = MimeTypeMap.GetMimeType("sample.txt"); - Assert.AreEqual("text/plain", result); - } + [TestMethod()] + public void should_return_valid_mimetype_for_givent_filename() + { + string result = MimeTypeMap.GetMimeType("sample.txt"); + Assert.AreEqual("text/plain", result); + } - [TestMethod()] - public void should_return_file_extension_for_given_mimetype() - { - string result = MimeTypeMap.GetExtension("text/plain"); - Assert.AreEqual(".txt", result); - } + [TestMethod()] + public void should_return_file_extension_for_given_mimetype() + { + string result = MimeTypeMap.GetExtension("text/plain"); + Assert.AreEqual(".txt", result); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/Utilities/Json/IgnorePropertiesResolverTests.cs b/Tests/Jinget.Core.Tests/Utilities/Json/IgnorePropertiesResolverTests.cs index 120c5bc..752dbf2 100644 --- a/Tests/Jinget.Core.Tests/Utilities/Json/IgnorePropertiesResolverTests.cs +++ b/Tests/Jinget.Core.Tests/Utilities/Json/IgnorePropertiesResolverTests.cs @@ -2,26 +2,25 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json; -namespace Jinget.Core.Tests.Utilities.Json +namespace Jinget.Core.Tests.Utilities.Json; + +[TestClass()] +public class IgnorePropertiesResolverTests { - [TestClass()] - public class IgnorePropertiesResolverTests + [TestMethod()] + public void should_ignore_given_properties_while_serialization() { - [TestMethod()] - public void should_ignore_given_properties_while_serialization() - { - string expected = "{\"Property1\":1,\"Property4\":false,\"InnerSingularProperty\":null,\"InnerProperty\":null,\"InnerListProperty\":null}"; + string expected = "{\"Property1\":1,\"Property4\":false,\"InnerSingularProperty\":null,\"InnerProperty\":null,\"InnerListProperty\":null}"; - var result = JsonConvert.SerializeObject(new _BaseData.TestClass - { - Property1 = 1 - }, - new JsonSerializerSettings() - { - ContractResolver = new IgnorePropertiesResolver(new[] { nameof(_BaseData.TestClass.Property2), nameof(_BaseData.TestClass.Property3) }) - }); + var result = JsonConvert.SerializeObject(new _BaseData.TestClass + { + Property1 = 1 + }, + new JsonSerializerSettings() + { + ContractResolver = new IgnorePropertiesResolver(new[] { nameof(_BaseData.TestClass.Property2), nameof(_BaseData.TestClass.Property3) }) + }); - Assert.AreEqual(expected, result); - } + Assert.AreEqual(expected, result); } } diff --git a/Tests/Jinget.Core.Tests/Utilities/Json/JsonUtilityTests.cs b/Tests/Jinget.Core.Tests/Utilities/Json/JsonUtilityTests.cs index ebae7e0..e6f68bb 100644 --- a/Tests/Jinget.Core.Tests/Utilities/Json/JsonUtilityTests.cs +++ b/Tests/Jinget.Core.Tests/Utilities/Json/JsonUtilityTests.cs @@ -2,62 +2,61 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json.Linq; -namespace Jinget.Core.Tests.Utilities.Parser.DatabaseParser +namespace Jinget.Core.Tests.Utilities.Parser.DatabaseParser; + +[TestClass] +public class JsonUtilityTests { - [TestClass] - public class JsonUtilityTests + [TestMethod()] + public void should_return_true_for_valid_json_object_string() { - [TestMethod()] - public void should_return_true_for_valid_json_object_string() - { - string sampleJson = "{ id: 1, name: \"Leanne Graham\", username: \"Bret\", address: { street: \"Kulas Light\", city: \"Gwenborough\", geo: { lat: \"-37.3159\", lng: \"81.1496\" } }}"; - var result = JsonUtility.IsValid(sampleJson); - Assert.IsTrue(result); - } - - [TestMethod()] - public void should_return_true_for_valid_json_array_string() - { - string sampleJson = "[ { id: 1, name: \"Leanne Graham\", address: { city: \"Gwenborough\" }},{ id: 2, name: \"Vahid Farahmandian\", address: { city: \"Urmia\" }} ]"; - var result = JsonUtility.IsValid(sampleJson); - Assert.IsTrue(result); - } - - [TestMethod()] - public void should_return_false_for_invalid_json() - { - string invalidJsonString = "InvalidJsonString"; - var result = JsonUtility.IsValid(invalidJsonString); - Assert.IsFalse(result); - - string emptyJsonString = ""; - result = JsonUtility.IsValid(emptyJsonString); - Assert.IsFalse(result); - - string nullJsonString = ""; - result = JsonUtility.IsValid(nullJsonString); - Assert.IsFalse(result); - } - - [TestMethod()] - public void should_unescape_escaped_json_string() - { - string escapedString = "{\\\"Id\\\":\\\"i1\\\"}"; - string expectedResult = "{\"Id\":\"i1\"}"; - var result = JsonUtility.Unescape(escapedString); - - Assert.AreEqual(expectedResult, result); - } - - [TestMethod()] - public void should_merge_two_json_string() - { - string json1 = "{\"Id\":\"i1\"}"; - string json2 = "{\"Id\":\"i2\"}"; - string expectedResult = "{\"Id\":\"i1\",\"p1\":{\"Id\":\"i2\"}}"; - var result = JsonUtility.Merge(json1, json2, "p1"); - - Assert.AreEqual(JToken.Parse(expectedResult).ToString(), JToken.Parse(result).ToString()); - } + string sampleJson = "{ id: 1, name: \"Leanne Graham\", username: \"Bret\", address: { street: \"Kulas Light\", city: \"Gwenborough\", geo: { lat: \"-37.3159\", lng: \"81.1496\" } }}"; + var result = JsonUtility.IsValid(sampleJson); + Assert.IsTrue(result); + } + + [TestMethod()] + public void should_return_true_for_valid_json_array_string() + { + string sampleJson = "[ { id: 1, name: \"Leanne Graham\", address: { city: \"Gwenborough\" }},{ id: 2, name: \"Vahid Farahmandian\", address: { city: \"Urmia\" }} ]"; + var result = JsonUtility.IsValid(sampleJson); + Assert.IsTrue(result); + } + + [TestMethod()] + public void should_return_false_for_invalid_json() + { + string invalidJsonString = "InvalidJsonString"; + var result = JsonUtility.IsValid(invalidJsonString); + Assert.IsFalse(result); + + string emptyJsonString = ""; + result = JsonUtility.IsValid(emptyJsonString); + Assert.IsFalse(result); + + string nullJsonString = ""; + result = JsonUtility.IsValid(nullJsonString); + Assert.IsFalse(result); + } + + [TestMethod()] + public void should_unescape_escaped_json_string() + { + string escapedString = "{\\\"Id\\\":\\\"i1\\\"}"; + string expectedResult = "{\"Id\":\"i1\"}"; + var result = JsonUtility.Unescape(escapedString); + + Assert.AreEqual(expectedResult, result); + } + + [TestMethod()] + public void should_merge_two_json_string() + { + string json1 = "{\"Id\":\"i1\"}"; + string json2 = "{\"Id\":\"i2\"}"; + string expectedResult = "{\"Id\":\"i1\",\"p1\":{\"Id\":\"i2\"}}"; + var result = JsonUtility.Merge(json1, json2, "p1"); + + Assert.AreEqual(JToken.Parse(expectedResult).ToString(), JToken.Parse(result).ToString()); } } diff --git a/Tests/Jinget.Core.Tests/Utilities/Json/NonPublicSetterResolverTests.cs b/Tests/Jinget.Core.Tests/Utilities/Json/NonPublicSetterResolverTests.cs index 7b56846..d2497c8 100644 --- a/Tests/Jinget.Core.Tests/Utilities/Json/NonPublicSetterResolverTests.cs +++ b/Tests/Jinget.Core.Tests/Utilities/Json/NonPublicSetterResolverTests.cs @@ -2,26 +2,25 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json; -namespace Jinget.Core.Tests.Utilities.Json +namespace Jinget.Core.Tests.Utilities.Json; + +[TestClass()] +public class NonPublicSetterResolverTests { - [TestClass()] - public class NonPublicSetterResolverTests + [TestMethod()] + public void should_ignore_given_properties_while_serialization() { - [TestMethod()] - public void should_ignore_given_properties_while_serialization() - { - string expected = "{\"Id\":1,\"Name\":\"Vahid\"}"; + string expected = "{\"Id\":1,\"Name\":\"Vahid\"}"; - var result = JsonConvert.SerializeObject(new _BaseData.ClassWithNonPublicSetterProps("Vahid") - { - Id = 1 - }, - new JsonSerializerSettings() - { - ContractResolver = new NonPublicSetterResolver() - }); + var result = JsonConvert.SerializeObject(new _BaseData.ClassWithNonPublicSetterProps("Vahid") + { + Id = 1 + }, + new JsonSerializerSettings() + { + ContractResolver = new NonPublicSetterResolver() + }); - Assert.AreEqual(expected, result); - } + Assert.AreEqual(expected, result); } } diff --git a/Tests/Jinget.Core.Tests/Utilities/JwtUtilityTests.cs b/Tests/Jinget.Core.Tests/Utilities/JwtUtilityTests.cs index 70b001c..2477eaa 100644 --- a/Tests/Jinget.Core.Tests/Utilities/JwtUtilityTests.cs +++ b/Tests/Jinget.Core.Tests/Utilities/JwtUtilityTests.cs @@ -6,66 +6,65 @@ using System.Security.Claims; using System.Threading.Tasks; -namespace Jinget.Core.Utilities.Tests +namespace Jinget.Core.Utilities.Tests; + +[TestClass()] +public class JwtUtilityTests { - [TestClass()] - public class JwtUtilityTests + [TestMethod()] + public void should_return_token_parts() { - [TestMethod()] - public void should_return_token_parts() - { - string token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiaXNzIjoiSmluZ2V0IiwiaWF0IjoxNTE2MjM5MDIyfQ.Ushn140BB6h_G4rEnZuM2VWSKmatFc4DVrvJGWlRRfE"; - var result = JwtUtility.Read(token); - Assert.IsNotNull(result.Subject); - Assert.IsNotNull(result.Issuer); - Assert.IsNotNull(result.IssuedAt); - } + string token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiaXNzIjoiSmluZ2V0IiwiaWF0IjoxNTE2MjM5MDIyfQ.Ushn140BB6h_G4rEnZuM2VWSKmatFc4DVrvJGWlRRfE"; + var result = JwtUtility.Read(token); + Assert.IsNotNull(result.Subject); + Assert.IsNotNull(result.Issuer); + Assert.IsNotNull(result.IssuedAt); + } - [TestMethod()] - public async Task should_validate_token_with_lifetime_sigingkeyAsync() - { - string token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiaXNzIjoiSmluZ2V0IiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjIwMTYyMzkwMjIsImF1ZCI6IkppbmdldC5UZXN0In0.e-GVmjCsuP6sv7csybQZbVp5HenQ1UT5AhzafYSlMFU"; - var result = await JwtUtility.IsValidAsync(token); - Assert.IsTrue(result); - } + [TestMethod()] + public async Task should_validate_token_with_lifetime_sigingkeyAsync() + { + string token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiaXNzIjoiSmluZ2V0IiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjIwMTYyMzkwMjIsImF1ZCI6IkppbmdldC5UZXN0In0.e-GVmjCsuP6sv7csybQZbVp5HenQ1UT5AhzafYSlMFU"; + var result = await JwtUtility.IsValidAsync(token); + Assert.IsTrue(result); + } - [TestMethod()] - public async Task should_validate_token_with_lifetime_sigingkey_audience_issuerAsync() - { - string token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiaXNzIjoiSmluZ2V0IiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjIwMTYyMzkwMjIsImF1ZCI6IkppbmdldC5UZXN0In0.e-GVmjCsuP6sv7csybQZbVp5HenQ1UT5AhzafYSlMFU"; - string validIssuer = "Jinget"; - IEnumerable validAudiences = new string[] { "Jinget.Test" }; + [TestMethod()] + public async Task should_validate_token_with_lifetime_sigingkey_audience_issuerAsync() + { + string token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiaXNzIjoiSmluZ2V0IiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjIwMTYyMzkwMjIsImF1ZCI6IkppbmdldC5UZXN0In0.e-GVmjCsuP6sv7csybQZbVp5HenQ1UT5AhzafYSlMFU"; + string validIssuer = "Jinget"; + IEnumerable validAudiences = new string[] { "Jinget.Test" }; - var result = await JwtUtility.IsValidAsync(token, validAudiences, validIssuer); - Assert.IsTrue(result); - } + var result = await JwtUtility.IsValidAsync(token, validAudiences, validIssuer); + Assert.IsTrue(result); + } - [TestMethod()] - [ExpectedException(typeof(SecurityTokenMalformedException))] - public async Task should_return_false_for_invalid_tokenAsync() - { - string token = "InvalidJwtToken"; - var result = await JwtUtility.IsValidAsync(token); - Assert.IsFalse(result); - } + [TestMethod()] + [ExpectedException(typeof(SecurityTokenMalformedException))] + public async Task should_return_false_for_invalid_tokenAsync() + { + string token = "InvalidJwtToken"; + var result = await JwtUtility.IsValidAsync(token); + Assert.IsFalse(result); + } - [TestMethod()] - public void should_create_a_valid_jwt_token() - { - var result = JwtUtility.Generate("vahid", ["role1,role2"], new Types.JwtModel { SecretKey = "12345678901234567890123456789012" }); - var tokenInfo = JwtUtility.Read(result); - Assert.AreEqual(tokenInfo.Claims.First(x => x.Type == ClaimTypes.NameIdentifier).Value, "vahid"); - Assert.AreEqual(tokenInfo.Claims.First(x => x.Type == ClaimTypes.Role).Value, "role1,role2"); - } + [TestMethod()] + public void should_create_a_valid_jwt_token() + { + var result = JwtUtility.Generate("vahid", ["role1,role2"], new Types.JwtModel { SecretKey = "12345678901234567890123456789012" }); + var tokenInfo = JwtUtility.Read(result); + Assert.AreEqual(tokenInfo.Claims.First(x => x.Type == ClaimTypes.NameIdentifier).Value, "vahid"); + Assert.AreEqual(tokenInfo.Claims.First(x => x.Type == ClaimTypes.Role).Value, "role1,role2"); + } - [TestMethod()] - public void should_return_specific_claim_from_token() - { - string token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiaXNzIjoiSmluZ2V0IiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjIwMTYyMzkwMjIsImF1ZCI6IkppbmdldC5UZXN0In0.e-GVmjCsuP6sv7csybQZbVp5HenQ1UT5AhzafYSlMFU"; - string expectedResult = "1234567890"; - var result = JwtUtility.GetClaim(token, JwtRegisteredClaimNames.Sub); + [TestMethod()] + public void should_return_specific_claim_from_token() + { + string token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiaXNzIjoiSmluZ2V0IiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjIwMTYyMzkwMjIsImF1ZCI6IkppbmdldC5UZXN0In0.e-GVmjCsuP6sv7csybQZbVp5HenQ1UT5AhzafYSlMFU"; + string expectedResult = "1234567890"; + var result = JwtUtility.GetClaim(token, JwtRegisteredClaimNames.Sub); - Assert.AreEqual(expectedResult, result.First().Value); - } + Assert.AreEqual(expectedResult, result.First().Value); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/Utilities/Parser/DatabaseParser/DatabaseParserUtilityTests.cs b/Tests/Jinget.Core.Tests/Utilities/Parser/DatabaseParser/DatabaseParserUtilityTests.cs index 5062fee..965420c 100644 --- a/Tests/Jinget.Core.Tests/Utilities/Parser/DatabaseParser/DatabaseParserUtilityTests.cs +++ b/Tests/Jinget.Core.Tests/Utilities/Parser/DatabaseParser/DatabaseParserUtilityTests.cs @@ -1,38 +1,37 @@ using Jinget.Core.Utilities.Parser.DatabaseParser.SqlServer; using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace Jinget.Core.Tests.Utilities.Parser.DatabaseParser +namespace Jinget.Core.Tests.Utilities.Parser.DatabaseParser; + +[TestClass] +public class DatabaseParserUtilityTests { - [TestClass] - public class DatabaseParserUtilityTests + [TestMethod()] + public void should_parse_connectionstring() { - [TestMethod()] - public void should_parse_connectionstring() - { - string connectionString = "Server=YOURSERVERNAME; Database=YOURDATABASENAME; Trusted_Connection=True; MultipleActiveResultSets=true"; + string connectionString = "Server=YOURSERVERNAME; Database=YOURDATABASENAME; Trusted_Connection=True; MultipleActiveResultSets=true"; - var result = SqlServerParserUtility.ParseConnectionString(connectionString); + var result = SqlServerParserUtility.ParseConnectionString(connectionString); - Assert.IsTrue(result.ContainsKey("Server")); - Assert.IsTrue(result.ContainsKey("Database")); - Assert.IsTrue(result.ContainsKey("Trusted_Connection")); - Assert.IsTrue(result.ContainsKey("MultipleActiveResultSets")); - } + Assert.IsTrue(result.ContainsKey("Server")); + Assert.IsTrue(result.ContainsKey("Database")); + Assert.IsTrue(result.ContainsKey("Trusted_Connection")); + Assert.IsTrue(result.ContainsKey("MultipleActiveResultSets")); + } - [TestMethod()] - public void should_return_empty_result() - { - string invalidConnectionString = "InvalidConnectionString"; - var result = SqlServerParserUtility.ParseConnectionString(invalidConnectionString); - Assert.IsTrue(result.Keys.Count == 0); + [TestMethod()] + public void should_return_empty_result() + { + string invalidConnectionString = "InvalidConnectionString"; + var result = SqlServerParserUtility.ParseConnectionString(invalidConnectionString); + Assert.IsTrue(result.Keys.Count == 0); - string emptyConnectionString = ""; - result = SqlServerParserUtility.ParseConnectionString(emptyConnectionString); - Assert.IsTrue(result.Keys.Count == 0); + string emptyConnectionString = ""; + result = SqlServerParserUtility.ParseConnectionString(emptyConnectionString); + Assert.IsTrue(result.Keys.Count == 0); - string nullConnectionString = ""; - result = SqlServerParserUtility.ParseConnectionString(nullConnectionString); - Assert.IsTrue(result.Keys.Count == 0); - } + string nullConnectionString = ""; + result = SqlServerParserUtility.ParseConnectionString(nullConnectionString); + Assert.IsTrue(result.Keys.Count == 0); } } diff --git a/Tests/Jinget.Core.Tests/Utilities/Parser/DatabaseParser/SqlServer/SqlServerParserUtilityTests.cs b/Tests/Jinget.Core.Tests/Utilities/Parser/DatabaseParser/SqlServer/SqlServerParserUtilityTests.cs index 29b5206..b06caf4 100644 --- a/Tests/Jinget.Core.Tests/Utilities/Parser/DatabaseParser/SqlServer/SqlServerParserUtilityTests.cs +++ b/Tests/Jinget.Core.Tests/Utilities/Parser/DatabaseParser/SqlServer/SqlServerParserUtilityTests.cs @@ -1,38 +1,37 @@ using Jinget.Core.Utilities.Parser.DatabaseParser.SqlServer; using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace Jinget.Core.Tests.Utilities.Parser.DatabaseParser +namespace Jinget.Core.Tests.Utilities.Parser.DatabaseParser; + +[TestClass] +public class SqlServerParserUtilityTests { - [TestClass] - public class SqlServerParserUtilityTests + [TestMethod()] + public void should_parse_connectionstring() { - [TestMethod()] - public void should_parse_connectionstring() - { - string connectionString = "Server=YOURSERVERNAME; Database=YOURDATABASENAME; Trusted_Connection=True; MultipleActiveResultSets=true"; + string connectionString = "Server=YOURSERVERNAME; Database=YOURDATABASENAME; Trusted_Connection=True; MultipleActiveResultSets=true"; - var result = SqlServerParserUtility.ParseConnectionString(connectionString); + var result = SqlServerParserUtility.ParseConnectionString(connectionString); - Assert.IsTrue(result.ContainsKey("Server")); - Assert.IsTrue(result.ContainsKey("Database")); - Assert.IsTrue(result.ContainsKey("Trusted_Connection")); - Assert.IsTrue(result.ContainsKey("MultipleActiveResultSets")); - } + Assert.IsTrue(result.ContainsKey("Server")); + Assert.IsTrue(result.ContainsKey("Database")); + Assert.IsTrue(result.ContainsKey("Trusted_Connection")); + Assert.IsTrue(result.ContainsKey("MultipleActiveResultSets")); + } - [TestMethod()] - public void should_return_empty_result() - { - string invalidConnectionString = "InvalidConnectionString"; - var result = SqlServerParserUtility.ParseConnectionString(invalidConnectionString); - Assert.IsTrue(result.Keys.Count == 0); + [TestMethod()] + public void should_return_empty_result() + { + string invalidConnectionString = "InvalidConnectionString"; + var result = SqlServerParserUtility.ParseConnectionString(invalidConnectionString); + Assert.IsTrue(result.Keys.Count == 0); - string emptyConnectionString = ""; - result = SqlServerParserUtility.ParseConnectionString(emptyConnectionString); - Assert.IsTrue(result.Keys.Count == 0); + string emptyConnectionString = ""; + result = SqlServerParserUtility.ParseConnectionString(emptyConnectionString); + Assert.IsTrue(result.Keys.Count == 0); - string nullConnectionString = ""; - result = SqlServerParserUtility.ParseConnectionString(nullConnectionString); - Assert.IsTrue(result.Keys.Count == 0); - } + string nullConnectionString = ""; + result = SqlServerParserUtility.ParseConnectionString(nullConnectionString); + Assert.IsTrue(result.Keys.Count == 0); } } diff --git a/Tests/Jinget.Core.Tests/Utilities/StringUtilityTests.cs b/Tests/Jinget.Core.Tests/Utilities/StringUtilityTests.cs index 3d27d1c..e11f461 100644 --- a/Tests/Jinget.Core.Tests/Utilities/StringUtilityTests.cs +++ b/Tests/Jinget.Core.Tests/Utilities/StringUtilityTests.cs @@ -3,35 +3,34 @@ using System.Collections.Generic; using System.Linq; -namespace Jinget.Core.Utilities.Tests +namespace Jinget.Core.Utilities.Tests; + +[TestClass()] +public class StringUtilityTests { - [TestClass()] - public class StringUtilityTests + [TestMethod()] + public void should_create_random_string_using_given_characterset() { - [TestMethod()] - public void should_create_random_string_using_given_characterset() - { - int length = 5; - IEnumerable charset = new char[] { 'a', 'b', 'c', '1' }; + int length = 5; + IEnumerable charset = new char[] { 'a', 'b', 'c', '1' }; - var result = StringUtility.GetRandomString(length, charset); + var result = StringUtility.GetRandomString(length, charset); - Assert.IsTrue(result.Length == length); - Assert.IsTrue(result.ToCharArray().All(x => charset.Contains(x))); - } + Assert.IsTrue(result.Length == length); + Assert.IsTrue(result.ToCharArray().All(x => charset.Contains(x))); + } - [TestMethod()] - public void should_return_true_for_numeric_string() - { - string input = "1234567890"; - Assert.IsTrue(StringUtility.IsDigitOnly(input)); - } + [TestMethod()] + public void should_return_true_for_numeric_string() + { + string input = "1234567890"; + Assert.IsTrue(StringUtility.IsDigitOnly(input)); + } - [TestMethod()] - public void should_return_false_for_non_numeric_string() - { - string input = "vahid123"; - Assert.IsFalse(StringUtility.IsDigitOnly(input)); - } + [TestMethod()] + public void should_return_false_for_non_numeric_string() + { + string input = "vahid123"; + Assert.IsFalse(StringUtility.IsDigitOnly(input)); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/Utilities/XmlUtilityTests.cs b/Tests/Jinget.Core.Tests/Utilities/XmlUtilityTests.cs index 6d415c4..9507e3e 100644 --- a/Tests/Jinget.Core.Tests/Utilities/XmlUtilityTests.cs +++ b/Tests/Jinget.Core.Tests/Utilities/XmlUtilityTests.cs @@ -4,145 +4,144 @@ using System.Xml; using System.Xml.Serialization; -namespace Jinget.Core.Utilities.Tests +namespace Jinget.Core.Utilities.Tests; + +[TestClass()] +public class XmlUtilityTests { - [TestClass()] - public class XmlUtilityTests + XmlSample samplexml; + SoapSample samplesoap; + [TestInitialize()] + public void Init() { - XmlSample samplexml; - SoapSample samplesoap; - [TestInitialize()] - public void Init() + samplexml = new() { - samplexml = new() + Id = 10, + Name = "Vahid", + InnerSample = new() { - Id = 10, - Name = "Vahid", - InnerSample = new() + Data = "Sample Data" + }, + InnerSampleList = + [ + new XmlSample.InnerXmlSample() { - Data = "Sample Data" + Data="Sample List Data 1" }, - InnerSampleList = - [ - new XmlSample.InnerXmlSample() - { - Data="Sample List Data 1" - }, - new XmlSample.InnerXmlSample() - { - Data="Sample List Data 2" - } - ] - }; - samplesoap = new() - { - Id = 10, - Name = "Vahid" - }; - } - - [TestMethod()] - public void should_serialize_object_to_xml() + new XmlSample.InnerXmlSample() + { + Data="Sample List Data 2" + } + ] + }; + samplesoap = new() { - XmlDocument expectedXml = new(); - expectedXml.LoadXml( - "10VahidSample DataSample List Data 1Sample List Data 2\r\n" - ); + Id = 10, + Name = "Vahid" + }; + } - var result = XmlUtility.SerializeToXml(samplexml); + [TestMethod()] + public void should_serialize_object_to_xml() + { + XmlDocument expectedXml = new(); + expectedXml.LoadXml( + "10VahidSample DataSample List Data 1Sample List Data 2\r\n" + ); - XmlDocument resultXml = new(); - resultXml.LoadXml(result); + var result = XmlUtility.SerializeToXml(samplexml); - Assert.AreEqual(expectedXml.InnerXml, resultXml.InnerXml); - } + XmlDocument resultXml = new(); + resultXml.LoadXml(result); - [TestMethod()] - public void should_serialize_object_to_xml_without_xmldeclartion() - { - XmlDocument expectedXml = new(); - expectedXml.LoadXml( - "10VahidSample DataSample List Data 1Sample List Data 2\r\n" - ); + Assert.AreEqual(expectedXml.InnerXml, resultXml.InnerXml); + } - var result = XmlUtility.SerializeToXml(samplexml, omitXmlDeclaration: true); + [TestMethod()] + public void should_serialize_object_to_xml_without_xmldeclartion() + { + XmlDocument expectedXml = new(); + expectedXml.LoadXml( + "10VahidSample DataSample List Data 1Sample List Data 2\r\n" + ); - XmlDocument resultXml = new(); - resultXml.LoadXml(result); + var result = XmlUtility.SerializeToXml(samplexml, omitXmlDeclaration: true); - Assert.AreEqual(expectedXml.InnerXml, resultXml.InnerXml); - } + XmlDocument resultXml = new(); + resultXml.LoadXml(result); - [TestMethod()] - public void should_serialize_object_to_xml_with_namespaces() - { - XmlDocument expectedXml = new(); - expectedXml.LoadXml( - "10VahidSample DataSample List Data 1Sample List Data 2\r\n" - ); + Assert.AreEqual(expectedXml.InnerXml, resultXml.InnerXml); + } - XmlSerializerNamespaces ns = new(); - ns.Add("MyNS", "https://jinget.ir"); + [TestMethod()] + public void should_serialize_object_to_xml_with_namespaces() + { + XmlDocument expectedXml = new(); + expectedXml.LoadXml( + "10VahidSample DataSample List Data 1Sample List Data 2\r\n" + ); - var result = XmlUtility.SerializeToXml(samplexml, ns: ns); + XmlSerializerNamespaces ns = new(); + ns.Add("MyNS", "https://jinget.ir"); - XmlDocument resultXml = new(); - resultXml.LoadXml(result); + var result = XmlUtility.SerializeToXml(samplexml, ns: ns); - Assert.AreEqual(expectedXml.InnerXml, resultXml.InnerXml); - } + XmlDocument resultXml = new(); + resultXml.LoadXml(result); - [TestMethod()] - public void should_deserialize_xml_descendants_to_custom_type_and_return_all_of_them() - { - List expectedObjects = - [ - new XmlSample.InnerXmlSample() - { - Data="Sample List Data 1" - }, - new XmlSample.InnerXmlSample() - { - Data="Sample List Data 2" - } - ]; + Assert.AreEqual(expectedXml.InnerXml, resultXml.InnerXml); + } - string input = "10VahidSample DataSample List Data 1Sample List Data 2\r\n"; + [TestMethod()] + public void should_deserialize_xml_descendants_to_custom_type_and_return_all_of_them() + { + List expectedObjects = + [ + new XmlSample.InnerXmlSample() + { + Data="Sample List Data 1" + }, + new XmlSample.InnerXmlSample() + { + Data="Sample List Data 2" + } + ]; - var result = XmlUtility.DeserializeXmlDescendantsAll(input); + string input = "10VahidSample DataSample List Data 1Sample List Data 2\r\n"; - Assert.AreEqual(expectedObjects.Count, result.Count); - } + var result = XmlUtility.DeserializeXmlDescendantsAll(input); - [TestMethod()] - public void should_deserialize_xml_descendants_to_custom_type_and_return_first_among_them() + Assert.AreEqual(expectedObjects.Count, result.Count); + } + + [TestMethod()] + public void should_deserialize_xml_descendants_to_custom_type_and_return_first_among_them() + { + var expectedObjects = new XmlSample.InnerXmlSample() { - var expectedObjects = new XmlSample.InnerXmlSample() - { - Data = "Sample List Data 1" - }; + Data = "Sample List Data 1" + }; - string input = "10VahidSample DataSample List Data 1Sample List Data 2\r\n"; + string input = "10VahidSample DataSample List Data 1Sample List Data 2\r\n"; - var result = XmlUtility.DeserializeXmlDescendantsFirst(input); + var result = XmlUtility.DeserializeXmlDescendantsFirst(input); - Assert.AreEqual(expectedObjects.Data, result.Data); - } + Assert.AreEqual(expectedObjects.Data, result.Data); + } - [TestMethod()] - public void should_serialize_object_to_soapxml() - { - XmlDocument expectedXml = new(); - expectedXml.LoadXml( - "\r\n \r\n \r\n 10\r\n Vahid\r\n \r\n \r\n\r\n" - ); + [TestMethod()] + public void should_serialize_object_to_soapxml() + { + XmlDocument expectedXml = new(); + expectedXml.LoadXml( + "\r\n \r\n \r\n 10\r\n Vahid\r\n \r\n \r\n\r\n" + ); - var result = XmlUtility.SerializeToSoapXml(samplesoap); + var result = XmlUtility.SerializeToSoapXml(samplesoap); - XmlDocument resultXml = new(); - resultXml.LoadXml(result); + XmlDocument resultXml = new(); + resultXml.LoadXml(result); - Assert.AreEqual(expectedXml.InnerXml, resultXml.InnerXml); - } + Assert.AreEqual(expectedXml.InnerXml, resultXml.InnerXml); } } \ No newline at end of file diff --git a/Tests/Jinget.Core.Tests/_BaseData/ClassWithNonPublicSetterProps.cs b/Tests/Jinget.Core.Tests/_BaseData/ClassWithNonPublicSetterProps.cs index c81ff8f..18fe0f0 100644 --- a/Tests/Jinget.Core.Tests/_BaseData/ClassWithNonPublicSetterProps.cs +++ b/Tests/Jinget.Core.Tests/_BaseData/ClassWithNonPublicSetterProps.cs @@ -1,8 +1,7 @@ -namespace Jinget.Core.Tests._BaseData +namespace Jinget.Core.Tests._BaseData; + +public class ClassWithNonPublicSetterProps(string name) { - public class ClassWithNonPublicSetterProps(string name) - { - public int Id { get; set; } - public string Name { get; private set; } = name; - } + public int Id { get; set; } + public string Name { get; private set; } = name; } diff --git a/Tests/Jinget.Core.Tests/_BaseData/InheritanceSample.cs b/Tests/Jinget.Core.Tests/_BaseData/InheritanceSample.cs index 57154f2..b71add0 100644 --- a/Tests/Jinget.Core.Tests/_BaseData/InheritanceSample.cs +++ b/Tests/Jinget.Core.Tests/_BaseData/InheritanceSample.cs @@ -2,30 +2,29 @@ using Microsoft.AspNetCore.Authorization; using System; -namespace Jinget.Core.Tests._BaseData +namespace Jinget.Core.Tests._BaseData; + +[Summary("Non Generic Parent")] +public class NonGenericParent { - [Summary("Non Generic Parent")] - public class NonGenericParent - { - [Summary("Sample Method 1")] - public void SampleMethod1() { } + [Summary("Sample Method 1")] + public void SampleMethod1() { } - [Authorize] - [Summary("Sample Method 2")] - public void SampleMethod2() { } + [Authorize] + [Summary("Sample Method 2")] + public void SampleMethod2() { } - [Authorize] - public void SampleMethod3() { } - } - public class GenericParent { } - public class MultiGenericParent { } + [Authorize] + public void SampleMethod3() { } +} +public class GenericParent { } +public class MultiGenericParent { } - public class GenericChildNonGenericParent : NonGenericParent { } - public class GenericChildGenericParent : GenericParent { } - public class GenericChildMultiGenericParent : MultiGenericParent { } +public class GenericChildNonGenericParent : NonGenericParent { } +public class GenericChildGenericParent : GenericParent { } +public class GenericChildMultiGenericParent : MultiGenericParent { } - public class NonGenericChildNonGenericParent : NonGenericParent { } - public class NonGenericChildGenericParent : GenericParent { } - public class NonGenericChildMultiGenericParent : MultiGenericParent { } -} +public class NonGenericChildNonGenericParent : NonGenericParent { } +public class NonGenericChildGenericParent : GenericParent { } +public class NonGenericChildMultiGenericParent : MultiGenericParent { } diff --git a/Tests/Jinget.Core.Tests/_BaseData/InvalidStruct.cs b/Tests/Jinget.Core.Tests/_BaseData/InvalidStruct.cs index a0ac74f..07ea88a 100644 --- a/Tests/Jinget.Core.Tests/_BaseData/InvalidStruct.cs +++ b/Tests/Jinget.Core.Tests/_BaseData/InvalidStruct.cs @@ -1,41 +1,40 @@ using System; -namespace Jinget.Core.Tests._BaseData +namespace Jinget.Core.Tests._BaseData; + +struct InvalidStruct : IConvertible { - struct InvalidStruct : IConvertible - { - public TypeCode GetTypeCode() => throw new NotImplementedException(); + public TypeCode GetTypeCode() => throw new NotImplementedException(); - public bool ToBoolean(IFormatProvider provider) => throw new NotImplementedException(); + public bool ToBoolean(IFormatProvider provider) => throw new NotImplementedException(); - public byte ToByte(IFormatProvider provider) => throw new NotImplementedException(); + public byte ToByte(IFormatProvider provider) => throw new NotImplementedException(); - public char ToChar(IFormatProvider provider) => throw new NotImplementedException(); + public char ToChar(IFormatProvider provider) => throw new NotImplementedException(); - public DateTime ToDateTime(IFormatProvider provider) => throw new NotImplementedException(); + public DateTime ToDateTime(IFormatProvider provider) => throw new NotImplementedException(); - public decimal ToDecimal(IFormatProvider provider) => throw new NotImplementedException(); + public decimal ToDecimal(IFormatProvider provider) => throw new NotImplementedException(); - public double ToDouble(IFormatProvider provider) => throw new NotImplementedException(); + public double ToDouble(IFormatProvider provider) => throw new NotImplementedException(); - public short ToInt16(IFormatProvider provider) => throw new NotImplementedException(); + public short ToInt16(IFormatProvider provider) => throw new NotImplementedException(); - public int ToInt32(IFormatProvider provider) => throw new NotImplementedException(); + public int ToInt32(IFormatProvider provider) => throw new NotImplementedException(); - public long ToInt64(IFormatProvider provider) => throw new NotImplementedException(); + public long ToInt64(IFormatProvider provider) => throw new NotImplementedException(); - public sbyte ToSByte(IFormatProvider provider) => throw new NotImplementedException(); + public sbyte ToSByte(IFormatProvider provider) => throw new NotImplementedException(); - public float ToSingle(IFormatProvider provider) => throw new NotImplementedException(); + public float ToSingle(IFormatProvider provider) => throw new NotImplementedException(); - public string ToString(IFormatProvider provider) => throw new NotImplementedException(); + public string ToString(IFormatProvider provider) => throw new NotImplementedException(); - public object ToType(Type conversionType, IFormatProvider provider) => throw new NotImplementedException(); + public object ToType(Type conversionType, IFormatProvider provider) => throw new NotImplementedException(); - public ushort ToUInt16(IFormatProvider provider) => throw new NotImplementedException(); + public ushort ToUInt16(IFormatProvider provider) => throw new NotImplementedException(); - public uint ToUInt32(IFormatProvider provider) => throw new NotImplementedException(); + public uint ToUInt32(IFormatProvider provider) => throw new NotImplementedException(); - public ulong ToUInt64(IFormatProvider provider) => throw new NotImplementedException(); - } + public ulong ToUInt64(IFormatProvider provider) => throw new NotImplementedException(); } diff --git a/Tests/Jinget.Core.Tests/_BaseData/Sample.cs b/Tests/Jinget.Core.Tests/_BaseData/Sample.cs index 6a81f92..dda75a6 100644 --- a/Tests/Jinget.Core.Tests/_BaseData/Sample.cs +++ b/Tests/Jinget.Core.Tests/_BaseData/Sample.cs @@ -1,90 +1,89 @@ using System; using System.Collections.Generic; -namespace Jinget.Core.Tests._BaseData +namespace Jinget.Core.Tests._BaseData; + +public class SampleInterfaceClass : ISampleInterface { - public class SampleInterfaceClass : ISampleInterface - { - } - public class Type1 - { - public int Id { get; set; } - public string Name { get; set; } - public string LastName { get; set; } - } - public class Type2 +} +public class Type1 +{ + public int Id { get; set; } + public string Name { get; set; } + public string LastName { get; set; } +} +public class Type2 +{ + public int Id { get; set; } + public string Name { get; set; } + public string SurName { get; set; } +} +public class TestClass +{ + public string GetInfo(string s1, int i1) => $"string is: {s1}, integer is: {i1}, generic type is: {typeof(T).Name}"; + + public class InnerClass { - public int Id { get; set; } - public string Name { get; set; } - public string SurName { get; set; } + public int InnerProperty1 { get; set; } + public string InnerProperty2 { get; set; } + } - public class TestClass - { - public string GetInfo(string s1, int i1) => $"string is: {s1}, integer is: {i1}, generic type is: {typeof(T).Name}"; - public class InnerClass - { - public int InnerProperty1 { get; set; } - public string InnerProperty2 { get; set; } + public int Property1 { get; set; } + public string Property2 { get; set; } + public string Property3 { get; set; } + public bool Property4 { get; set; } - } + public InnerClass InnerSingularProperty { get; set; } - public int Property1 { get; set; } - public string Property2 { get; set; } - public string Property3 { get; set; } - public bool Property4 { get; set; } + public ICollection InnerProperty { get; set; } + public List InnerListProperty { get; set; } +} - public InnerClass InnerSingularProperty { get; set; } +public class ParentType +{ + private ParentType() { } - public ICollection InnerProperty { get; set; } - public List InnerListProperty { get; set; } - } + public int Id { get; protected set; } + public SubType Sub { get; protected set; } +} - public class ParentType - { - private ParentType() { } +public class SubType +{ + private SubType() { } - public int Id { get; protected set; } - public SubType Sub { get; protected set; } - } + public int Id { get; protected set; } + public ICollection ColSubs { get; protected set; } +} - public class SubType - { - private SubType() { } +public class ColSubType +{ + private ColSubType() { } - public int Id { get; protected set; } - public ICollection ColSubs { get; protected set; } - } + public int Id { get; protected set; } + public SubType SubType { get; set; } +} +public class XmlSample +{ + public int Id { get; set; } + public string Name { get; set; } - public class ColSubType - { - private ColSubType() { } + public InnerXmlSample InnerSample { get; set; } + public List InnerSampleList { get; set; } - public int Id { get; protected set; } - public SubType SubType { get; set; } - } - public class XmlSample + public class InnerXmlSample { - public int Id { get; set; } - public string Name { get; set; } - - public InnerXmlSample InnerSample { get; set; } - public List InnerSampleList { get; set; } - - public class InnerXmlSample - { - public string Data { get; set; } - } + public string Data { get; set; } } +} - [Serializable] - public class SoapSample - { - private int id; - private string name; +[Serializable] +public class SoapSample +{ + private int id; + private string name; - public int Id { get => id; set => id = value; } - public string Name { get => name; set => name = value; } - } + public int Id { get => id; set => id = value; } + public string Name { get => name; set => name = value; } } diff --git a/Tests/Jinget.Core.Tests/_BaseData/SampleEnum.cs b/Tests/Jinget.Core.Tests/_BaseData/SampleEnum.cs index 516d4f0..897d57e 100644 --- a/Tests/Jinget.Core.Tests/_BaseData/SampleEnum.cs +++ b/Tests/Jinget.Core.Tests/_BaseData/SampleEnum.cs @@ -1,22 +1,21 @@ using System.ComponentModel.DataAnnotations; -namespace Jinget.Core.Tests._BaseData +namespace Jinget.Core.Tests._BaseData; + +internal class SampleEnum { - internal class SampleEnum + internal enum ProgrammingLanguage { - internal enum ProgrammingLanguage - { - [Display(Name = "C#")] - CSharp = 1, + [Display(Name = "C#")] + CSharp = 1, - [System.ComponentModel.Description("F#.Net")] - [Display(Name = "F#")] - FSharp = 2, + [System.ComponentModel.Description("F#.Net")] + [Display(Name = "F#")] + FSharp = 2, - [Display(Name = "C#")] - VB = 3, + [Display(Name = "C#")] + VB = 3, - Golang = 4 - } + Golang = 4 } } diff --git a/Tests/Jinget.Core.Tests/_BaseData/SampleGeneric.cs b/Tests/Jinget.Core.Tests/_BaseData/SampleGeneric.cs index afb2b92..e7391c9 100644 --- a/Tests/Jinget.Core.Tests/_BaseData/SampleGeneric.cs +++ b/Tests/Jinget.Core.Tests/_BaseData/SampleGeneric.cs @@ -1,7 +1,6 @@ -namespace Jinget.Core.Tests._BaseData +namespace Jinget.Core.Tests._BaseData; + +public class SampleGeneric { - public class SampleGeneric - { - public T Id { get; set; } - } + public T Id { get; set; } } diff --git a/Tests/Jinget.Core.Tests/_BaseData/SampleInterface.cs b/Tests/Jinget.Core.Tests/_BaseData/SampleInterface.cs index 2cd17aa..67b2510 100644 --- a/Tests/Jinget.Core.Tests/_BaseData/SampleInterface.cs +++ b/Tests/Jinget.Core.Tests/_BaseData/SampleInterface.cs @@ -1,6 +1,5 @@ -namespace Jinget.Core.Tests._BaseData +namespace Jinget.Core.Tests._BaseData; + +public interface ISampleInterface { - public interface ISampleInterface - { - } } diff --git a/Tests/Jinget.Core.Tests/_BaseData/SqlTableSample.cs b/Tests/Jinget.Core.Tests/_BaseData/SqlTableSample.cs index 197b0fd..cdedd7e 100644 --- a/Tests/Jinget.Core.Tests/_BaseData/SqlTableSample.cs +++ b/Tests/Jinget.Core.Tests/_BaseData/SqlTableSample.cs @@ -1,12 +1,11 @@ using System; -namespace Jinget.Core.Tests._BaseData +namespace Jinget.Core.Tests._BaseData; + +public class SqlTableSample { - public class SqlTableSample - { - public Guid Id { get; set; } - public string FirstName { get; set; } - public string LastName { get; set; } - public int Age { get; set; } - } + public Guid Id { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + public int Age { get; set; } } diff --git a/Tests/Jinget.Handlers.ExternalServiceHandlers.Tests/DefaultServiceHandler/JingetServiceHandlerTests.cs b/Tests/Jinget.Handlers.ExternalServiceHandlers.Tests/DefaultServiceHandler/JingetServiceHandlerTests.cs index 1002cdf..d1aa975 100644 --- a/Tests/Jinget.Handlers.ExternalServiceHandlers.Tests/DefaultServiceHandler/JingetServiceHandlerTests.cs +++ b/Tests/Jinget.Handlers.ExternalServiceHandlers.Tests/DefaultServiceHandler/JingetServiceHandlerTests.cs @@ -3,183 +3,182 @@ using Newtonsoft.Json; #pragma warning disable CS8622 // Nullability of reference types in type of parameter doesn't match the target delegate (possibly because of nullability attributes). -namespace Jinget.Handlers.ExternalServiceHandlers.DefaultServiceHandler.Tests +namespace Jinget.Handlers.ExternalServiceHandlers.DefaultServiceHandler.Tests; + +[TestClass()] +public class JingetServiceHandlerTests { - [TestClass()] - public class JingetServiceHandlerTests + [TestMethod()] + public async Task Should_configure_httpclientfactory_by_timeoutAsync() { - [TestMethod()] - public async Task Should_configure_httpclientfactory_by_timeoutAsync() + var jingetServiceHandler = new JingetServiceHandler>("https://jinget.ir", TimeSpan.FromSeconds(1)); + + jingetServiceHandler.Events.ExceptionOccurred += (object sender, Exception e) => { - var jingetServiceHandler = new JingetServiceHandler>("https://jinget.ir", TimeSpan.FromSeconds(1)); + Assert.IsTrue(e.Message.Contains("Timeout of 1 seconds")); + }; - jingetServiceHandler.Events.ExceptionOccurred += (object sender, Exception e) => - { - Assert.IsTrue(e.Message.Contains("Timeout of 1 seconds")); - }; + var result = await jingetServiceHandler.GetAsync("users"); + + Assert.IsTrue(result is null); + } + [TestMethod()] + public async Task Should_call_get_restapiAsync() + { + var jingetServiceHandler = new JingetServiceHandler>("https://jsonplaceholder.typicode.com"); + jingetServiceHandler.Events.ServiceCalled += (object sender, HttpResponseMessage e) => + { + Assert.IsTrue(e.IsSuccessStatusCode); + }; + jingetServiceHandler.Events.RawResponseReceived += (object sender, string e) => + { + Assert.IsFalse(e == ""); + }; + jingetServiceHandler.Events.ExceptionOccurred += (object sender, Exception e) => + { + Assert.IsTrue(e is null); + }; + jingetServiceHandler.Events.ResponseDeserialized += (object sender, List e) => + { + Assert.IsFalse(e is null); + }; - var result = await jingetServiceHandler.GetAsync("users"); + var result = await jingetServiceHandler.GetAsync("users"); - Assert.IsTrue(result is null); - } - [TestMethod()] - public async Task Should_call_get_restapiAsync() + Assert.IsFalse(result is null); + } + + [TestMethod()] + public async Task Should_call_post_restapiAsync() + { + var jingetServiceHandler = new JingetServiceHandler("https://jsonplaceholder.typicode.com", true); + jingetServiceHandler.Events.ServiceCalled += (object sender, HttpResponseMessage e) => { - var jingetServiceHandler = new JingetServiceHandler>("https://jsonplaceholder.typicode.com"); - jingetServiceHandler.Events.ServiceCalled += (object sender, HttpResponseMessage e) => - { - Assert.IsTrue(e.IsSuccessStatusCode); - }; - jingetServiceHandler.Events.RawResponseReceived += (object sender, string e) => - { - Assert.IsFalse(e == ""); - }; - jingetServiceHandler.Events.ExceptionOccurred += (object sender, Exception e) => - { - Assert.IsTrue(e is null); - }; - jingetServiceHandler.Events.ResponseDeserialized += (object sender, List e) => - { - Assert.IsFalse(e is null); - }; + Assert.IsTrue(e.IsSuccessStatusCode); + }; + jingetServiceHandler.Events.RawResponseReceived += (object sender, string e) => + { + Assert.IsFalse(e == ""); + }; + jingetServiceHandler.Events.ExceptionOccurred += (object sender, Exception e) => + { + Assert.IsTrue(e is null); + }; + jingetServiceHandler.Events.ResponseDeserialized += (object sender, SamplePostResponse e) => + { + Assert.IsFalse(e is null); + }; + var result = await jingetServiceHandler + .PostAsync("posts", + new + { + title = "foo", + body = "bar", + userId = 1, + }, + new Dictionary + { + {"Content-type","application/json; charset=UTF-8" } + }); - var result = await jingetServiceHandler.GetAsync("users"); + Assert.IsFalse(result is null); + } - Assert.IsFalse(result is null); - } + [TestMethod()] + public async Task Should_call_send_restapiAsync() + { + var jingetServiceHandler = new JingetServiceHandler("https://jsonplaceholder.typicode.com", true); + jingetServiceHandler.Events.ServiceCalled += (object sender, HttpResponseMessage e) => + { + Assert.IsTrue(e.IsSuccessStatusCode); + }; + jingetServiceHandler.Events.RawResponseReceived += (object sender, string e) => + { + Assert.IsFalse(e == ""); + }; + jingetServiceHandler.Events.ExceptionOccurred += (object sender, Exception e) => + { + Assert.IsTrue(e is null); + }; + jingetServiceHandler.Events.ResponseDeserialized += (object sender, SamplePutResponse e) => + { + Assert.IsFalse(e is null); + }; - [TestMethod()] - public async Task Should_call_post_restapiAsync() + var request = new HttpRequestMessage { - var jingetServiceHandler = new JingetServiceHandler("https://jsonplaceholder.typicode.com", true); - jingetServiceHandler.Events.ServiceCalled += (object sender, HttpResponseMessage e) => - { - Assert.IsTrue(e.IsSuccessStatusCode); - }; - jingetServiceHandler.Events.RawResponseReceived += (object sender, string e) => + RequestUri = new Uri("https://jsonplaceholder.typicode.com/posts/1"), + Method = HttpMethod.Put, + Content = new StringContent(JsonConvert.SerializeObject(new { - Assert.IsFalse(e == ""); - }; - jingetServiceHandler.Events.ExceptionOccurred += (object sender, Exception e) => - { - Assert.IsTrue(e is null); - }; - jingetServiceHandler.Events.ResponseDeserialized += (object sender, SamplePostResponse e) => - { - Assert.IsFalse(e is null); - }; - var result = await jingetServiceHandler - .PostAsync("posts", - new - { - title = "foo", - body = "bar", - userId = 1, - }, - new Dictionary - { - {"Content-type","application/json; charset=UTF-8" } - }); - - Assert.IsFalse(result is null); - } - - [TestMethod()] - public async Task Should_call_send_restapiAsync() - { - var jingetServiceHandler = new JingetServiceHandler("https://jsonplaceholder.typicode.com", true); - jingetServiceHandler.Events.ServiceCalled += (object sender, HttpResponseMessage e) => - { - Assert.IsTrue(e.IsSuccessStatusCode); - }; - jingetServiceHandler.Events.RawResponseReceived += (object sender, string e) => - { - Assert.IsFalse(e == ""); - }; - jingetServiceHandler.Events.ExceptionOccurred += (object sender, Exception e) => - { - Assert.IsTrue(e is null); - }; - jingetServiceHandler.Events.ResponseDeserialized += (object sender, SamplePutResponse e) => - { - Assert.IsFalse(e is null); - }; + id = 1, + title = "foo", + body = "bar", + userId = 1, + })) + }; + request.Headers.TryAddWithoutValidation("Content-type", "application/json; charset=UTF-8"); - var request = new HttpRequestMessage - { - RequestUri = new Uri("https://jsonplaceholder.typicode.com/posts/1"), - Method = HttpMethod.Put, - Content = new StringContent(JsonConvert.SerializeObject(new - { - id = 1, - title = "foo", - body = "bar", - userId = 1, - })) - }; - request.Headers.TryAddWithoutValidation("Content-type", "application/json; charset=UTF-8"); - - var result = await jingetServiceHandler.SendAsync(request); - - Assert.IsFalse(result is null); - } - - [TestMethod()] - public async Task Should_call_get_soapAsync() - { - var jingetServiceHandler = new JingetServiceHandler("http://www.dneonline.com/calculator.asmx"); - jingetServiceHandler.Events.ServiceCalled += (object sender, HttpResponseMessage e) => - { - Assert.IsTrue(e.IsSuccessStatusCode); - }; - jingetServiceHandler.Events.RawResponseReceived += (object sender, string e) => - { - Assert.IsFalse(e == ""); - }; - jingetServiceHandler.Events.ExceptionOccurred += (object sender, Exception e) => - { - Assert.IsTrue(e is null); - }; - jingetServiceHandler.Events.ResponseDeserialized += (object sender, AddResponse e) => - { - Assert.IsFalse(e is null); - }; + var result = await jingetServiceHandler.SendAsync(request); - var (envelope, request) = new SampleSOAPRequest().CreateEnvelope(); - envelope.Body.Add = new SampleSOAPRequest.SampleSOAPGet { intA = 1, intB = 2 }; + Assert.IsFalse(result is null); + } - var result = await jingetServiceHandler.PostAsync(envelope.ToString(), new Dictionary - { - {"Content-Type","text/xml" }, - {"SOAPAction","http://tempuri.org/Add" } - }); + [TestMethod()] + public async Task Should_call_get_soapAsync() + { + var jingetServiceHandler = new JingetServiceHandler("http://www.dneonline.com/calculator.asmx"); + jingetServiceHandler.Events.ServiceCalled += (object sender, HttpResponseMessage e) => + { + Assert.IsTrue(e.IsSuccessStatusCode); + }; + jingetServiceHandler.Events.RawResponseReceived += (object sender, string e) => + { + Assert.IsFalse(e == ""); + }; + jingetServiceHandler.Events.ExceptionOccurred += (object sender, Exception e) => + { + Assert.IsTrue(e is null); + }; + jingetServiceHandler.Events.ResponseDeserialized += (object sender, AddResponse e) => + { + Assert.IsFalse(e is null); + }; - Assert.IsFalse(result is null); - Assert.AreEqual(3, result.AddResult); - } + var (envelope, request) = new SampleSOAPRequest().CreateEnvelope(); + envelope.Body.Add = new SampleSOAPRequest.SampleSOAPGet { intA = 1, intB = 2 }; - //[TestMethod] - public async Task Should_post_multipart_formdataAsync() + var result = await jingetServiceHandler.PostAsync(envelope.ToString(), new Dictionary { - var jingetServiceHandler = new JingetServiceHandler("https://localhost:7027/api/upload", true); - jingetServiceHandler.Events.ServiceCalled += (object sender, HttpResponseMessage e) => - { - Assert.IsTrue(e.IsSuccessStatusCode); - }; - jingetServiceHandler.Events.ResponseDeserialized += (object sender, SamplePostResponse e) => - { - Assert.IsFalse(e is null); - }; + {"Content-Type","text/xml" }, + {"SOAPAction","http://tempuri.org/Add" } + }); + + Assert.IsFalse(result is null); + Assert.AreEqual(3, result.AddResult); + } + + //[TestMethod] + public async Task Should_post_multipart_formdataAsync() + { + var jingetServiceHandler = new JingetServiceHandler("https://localhost:7027/api/upload", true); + jingetServiceHandler.Events.ServiceCalled += (object sender, HttpResponseMessage e) => + { + Assert.IsTrue(e.IsSuccessStatusCode); + }; + jingetServiceHandler.Events.ResponseDeserialized += (object sender, SamplePostResponse e) => + { + Assert.IsFalse(e is null); + }; - List files = [ - new FileInfo("Sample Upload File1.txt") , - new FileInfo("Sample Upload File2.txt") - ]; + List files = [ + new FileInfo("Sample Upload File1.txt") , + new FileInfo("Sample Upload File2.txt") + ]; - var response = await jingetServiceHandler.UploadFileAsync("something", files); + var response = await jingetServiceHandler.UploadFileAsync("something", files); - Assert.IsFalse(string.IsNullOrWhiteSpace(response.Status)); - } + Assert.IsFalse(string.IsNullOrWhiteSpace(response.Status)); } } #pragma warning restore CS8622 // Nullability of reference types in type of parameter doesn't match the target delegate (possibly because of nullability attributes). \ No newline at end of file diff --git a/Tests/Jinget.Handlers.ExternalServiceHandlers.Tests/DefaultServiceHandler/SampleType/SampleGetResponse.cs b/Tests/Jinget.Handlers.ExternalServiceHandlers.Tests/DefaultServiceHandler/SampleType/SampleGetResponse.cs index 33f0da9..1d9da67 100644 --- a/Tests/Jinget.Handlers.ExternalServiceHandlers.Tests/DefaultServiceHandler/SampleType/SampleGetResponse.cs +++ b/Tests/Jinget.Handlers.ExternalServiceHandlers.Tests/DefaultServiceHandler/SampleType/SampleGetResponse.cs @@ -1,38 +1,37 @@ -namespace Jinget.Handlers.ExternalServiceHandlers.Tests.DefaultServiceHandler.SampleType -{ - public class SampleGetResponse - { - public int Id { get; set; } - public required string Name { get; set; } - public required string Username { get; set; } - public required string Email { get; set; } - public required Address_ Address { get; set; } - public required string Phone { get; set; } - public required string Website { get; set; } - public required Company_ Company { get; set; } +namespace Jinget.Handlers.ExternalServiceHandlers.Tests.DefaultServiceHandler.SampleType; +public class SampleGetResponse +{ + public int Id { get; set; } + public required string Name { get; set; } + public required string Username { get; set; } + public required string Email { get; set; } + public required Address_ Address { get; set; } + public required string Phone { get; set; } + public required string Website { get; set; } + public required Company_ Company { get; set; } - public class Address_ - { - public required string Street { get; set; } - public required string Suite { get; set; } - public required string City { get; set; } - public required string Zipcode { get; set; } - public required Geo_ Geo { get; set; } - } - public class Geo_ - { - public string? Lat { get; set; } - public string? Lng { get; set; } - } + public class Address_ + { + public required string Street { get; set; } + public required string Suite { get; set; } + public required string City { get; set; } + public required string Zipcode { get; set; } + public required Geo_ Geo { get; set; } + } - public class Company_ - { - public string? Name { get; set; } - public string? CatchPhrase { get; set; } - public string? Bs { get; set; } - } + public class Geo_ + { + public string? Lat { get; set; } + public string? Lng { get; set; } + } + public class Company_ + { + public string? Name { get; set; } + public string? CatchPhrase { get; set; } + public string? Bs { get; set; } } + } \ No newline at end of file diff --git a/Tests/Jinget.Handlers.ExternalServiceHandlers.Tests/DefaultServiceHandler/SampleType/SamplePostResponse.cs b/Tests/Jinget.Handlers.ExternalServiceHandlers.Tests/DefaultServiceHandler/SampleType/SamplePostResponse.cs index bcdcc20..a76ebe4 100644 --- a/Tests/Jinget.Handlers.ExternalServiceHandlers.Tests/DefaultServiceHandler/SampleType/SamplePostResponse.cs +++ b/Tests/Jinget.Handlers.ExternalServiceHandlers.Tests/DefaultServiceHandler/SampleType/SamplePostResponse.cs @@ -1,12 +1,10 @@ -namespace Jinget.Handlers.ExternalServiceHandlers.Tests.DefaultServiceHandler.SampleType -{ - public class SamplePostResponse - { - public string? Title { get; set; } - public string? Body { get; set; } - public int UserId { get; set; } - public int Id { get; set; } - public string? Status{ get; set; } - } +namespace Jinget.Handlers.ExternalServiceHandlers.Tests.DefaultServiceHandler.SampleType; +public class SamplePostResponse +{ + public string? Title { get; set; } + public string? Body { get; set; } + public int UserId { get; set; } + public int Id { get; set; } + public string? Status{ get; set; } } diff --git a/Tests/Jinget.Handlers.ExternalServiceHandlers.Tests/DefaultServiceHandler/SampleType/SamplePutResponse.cs b/Tests/Jinget.Handlers.ExternalServiceHandlers.Tests/DefaultServiceHandler/SampleType/SamplePutResponse.cs index e1dc807..7ac71f7 100644 --- a/Tests/Jinget.Handlers.ExternalServiceHandlers.Tests/DefaultServiceHandler/SampleType/SamplePutResponse.cs +++ b/Tests/Jinget.Handlers.ExternalServiceHandlers.Tests/DefaultServiceHandler/SampleType/SamplePutResponse.cs @@ -1,11 +1,9 @@ -namespace Jinget.Handlers.ExternalServiceHandlers.Tests.DefaultServiceHandler.SampleType -{ - public class SamplePutResponse - { - public string? Title { get; set; } - public string? Body { get; set; } - public int UserId { get; set; } - public int Id { get; set; } - } +namespace Jinget.Handlers.ExternalServiceHandlers.Tests.DefaultServiceHandler.SampleType; +public class SamplePutResponse +{ + public string? Title { get; set; } + public string? Body { get; set; } + public int UserId { get; set; } + public int Id { get; set; } } diff --git a/Tests/Jinget.Handlers.ExternalServiceHandlers.Tests/DefaultServiceHandler/SampleType/SampleSOAPRequest.cs b/Tests/Jinget.Handlers.ExternalServiceHandlers.Tests/DefaultServiceHandler/SampleType/SampleSOAPRequest.cs index 202a5e6..2431f9b 100644 --- a/Tests/Jinget.Handlers.ExternalServiceHandlers.Tests/DefaultServiceHandler/SampleType/SampleSOAPRequest.cs +++ b/Tests/Jinget.Handlers.ExternalServiceHandlers.Tests/DefaultServiceHandler/SampleType/SampleSOAPRequest.cs @@ -1,88 +1,78 @@ using Jinget.Core.Utilities; using System.Xml.Serialization; -namespace Jinget.Handlers.ExternalServiceHandlers.Tests.DefaultServiceHandler.SampleType +namespace Jinget.Handlers.ExternalServiceHandlers.Tests.DefaultServiceHandler.SampleType; + +/// +/// defines a full soap request for method Add inside the +/// +public class SampleSOAPRequest : SOAPRequestBase { - /// - /// defines a full soap request for method Add inside the - /// - public class SampleSOAPRequest : SOAPRequestBase + public override (Envelope envelope, SampleSOAPGet request) CreateEnvelope() { - public override (Envelope envelope, SampleSOAPGet request) CreateEnvelope() + var envelope = new Envelope { - var envelope = new Envelope - { - Header = new EnvelopeHeader(), - Body = new EnvelopeBody() - }; - return (envelope, envelope.Body.Add); - } + Header = new EnvelopeHeader(), + Body = new EnvelopeBody() + }; + return (envelope, envelope.Body.Add); + } + /// + /// Defines the envelop node in soap request + /// + [Serializable, XmlType(Namespace = "http://schemas.xmlsoap.org/soap/envelope/"), XmlRoot(Namespace = "http://schemas.xmlsoap.org/soap/envelope/")] + public class Envelope : SOAPEnvelopeBase + { /// - /// Defines the envelop node in soap request + /// add the required namespaces to envelop node. If predefined namespaces needed, then just replace ns with base.GetRequestNamespaces() /// - [Serializable, XmlType(Namespace = "http://schemas.xmlsoap.org/soap/envelope/"), XmlRoot(Namespace = "http://schemas.xmlsoap.org/soap/envelope/")] - public class Envelope : SOAPEnvelopeBase + public override string ToString() { - /// - /// add the required namespaces to envelop node. If predefined namespaces needed, then just replace ns with base.GetRequestNamespaces() - /// - public override string ToString() - { - XmlSerializerNamespaces ns = new(); - ns.Add("tem", "http://tempuri.org/"); - ns.Add("soapenv", "http://schemas.xmlsoap.org/soap/envelope/"); - - return XmlUtility.SerializeToXml(this, true, ns); - } + XmlSerializerNamespaces ns = new(); + ns.Add("tem", "http://tempuri.org/"); + ns.Add("soapenv", "http://schemas.xmlsoap.org/soap/envelope/"); - /// - /// defines the Header node inside the envelop node - /// -#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - public EnvelopeHeader Header { get; set; } -#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - - /// - /// Defines the Body node inside the envelop node - /// -#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - public EnvelopeBody Body { get; set; } -#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + return XmlUtility.SerializeToXml(this, true, ns); } /// - /// In this sample the Header node is empty + /// defines the Header node inside the envelop node /// - [Serializable, XmlType(Namespace = "http://schemas.xmlsoap.org/soap/envelope/")] - public class EnvelopeHeader - { - - } + public EnvelopeHeader Header { get; set; } /// - /// In this sample the Body node includes a node called Add + /// Defines the Body node inside the envelop node /// - [Serializable, XmlType(Namespace = "http://schemas.xmlsoap.org/soap/envelope/")] - public class EnvelopeBody - { - [XmlElement(Namespace = "http://tempuri.org/")] -#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - public SampleSOAPGet Add { get; set; } -#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - } + public EnvelopeBody Body { get; set; } + } - /// - /// In this sample the Add node includes two different nodes called intA and intB - /// - [Serializable] - public class SampleSOAPGet - { -#pragma warning disable IDE1006 // Naming Styles - public int intA { get; set; } - public int intB { get; set; } -#pragma warning restore IDE1006 // Naming Styles + /// + /// In this sample the Header node is empty + /// + [Serializable, XmlType(Namespace = "http://schemas.xmlsoap.org/soap/envelope/")] + public class EnvelopeHeader + { - } + } + + /// + /// In this sample the Body node includes a node called Add + /// + [Serializable, XmlType(Namespace = "http://schemas.xmlsoap.org/soap/envelope/")] + public class EnvelopeBody + { + [XmlElement(Namespace = "http://tempuri.org/")] + public SampleSOAPGet Add { get; set; } + } + + /// + /// In this sample the Add node includes two different nodes called intA and intB + /// + [Serializable] + public class SampleSOAPGet + { + public int intA { get; set; } + public int intB { get; set; } } } diff --git a/Tests/Jinget.Handlers.ExternalServiceHandlers.Tests/DefaultServiceHandler/SampleType/SampleSOAPResponse.cs b/Tests/Jinget.Handlers.ExternalServiceHandlers.Tests/DefaultServiceHandler/SampleType/SampleSOAPResponse.cs index ae7d581..6570636 100644 --- a/Tests/Jinget.Handlers.ExternalServiceHandlers.Tests/DefaultServiceHandler/SampleType/SampleSOAPResponse.cs +++ b/Tests/Jinget.Handlers.ExternalServiceHandlers.Tests/DefaultServiceHandler/SampleType/SampleSOAPResponse.cs @@ -1,13 +1,12 @@ using System.Xml.Serialization; -namespace Jinget.Handlers.ExternalServiceHandlers.Tests.DefaultServiceHandler.SampleType +namespace Jinget.Handlers.ExternalServiceHandlers.Tests.DefaultServiceHandler.SampleType; + +/// +/// The returned soap response should contain a node with the name same as this class +/// +[XmlRoot(Namespace = "http://tempuri.org/")] +public class AddResponse { - /// - /// The returned soap response should contain a node with the name same as this class - /// - [XmlRoot(Namespace = "http://tempuri.org/")] - public class AddResponse - { - public int AddResult { get; set; } - } + public int AddResult { get; set; } } \ No newline at end of file diff --git a/Tests/Jinget.WebAPI.Tests/SampleModel.cs b/Tests/Jinget.WebAPI.Tests/SampleModel.cs index acc3422..d33f1fd 100644 --- a/Tests/Jinget.WebAPI.Tests/SampleModel.cs +++ b/Tests/Jinget.WebAPI.Tests/SampleModel.cs @@ -1,14 +1,13 @@ using Jinget.Core.Attributes; -namespace Jinget.WebAPI.Tests +namespace Jinget.WebAPI.Tests; + +public class SampleModel { - public class SampleModel - { - public int Id { get; set; } - public required string Name { get; set; } - public required string LastName { get; set; } + public int Id { get; set; } + public required string Name { get; set; } + public required string LastName { get; set; } - [SwaggerExclude] - public string? FullName { get; set; } - } + [SwaggerExclude] + public string? FullName { get; set; } }