├── .editorconfig ├── .gitignore ├── Arch.Standard.sln ├── LICENSE ├── NuGet.config ├── NuGetPackageVerifier.json ├── README.md ├── src └── Arch.Standard │ ├── ApiResult │ ├── ApiResult.cs │ └── IApiResult.cs │ ├── Arch.Standard.csproj │ ├── Cryptography │ └── CryptoExtensions.cs │ ├── Exceptions │ ├── IStandardError.cs │ └── StandardException.cs │ ├── Extensions │ ├── ByteArrayExtensions.cs │ ├── HashExtensions.cs │ └── StringExtensions.cs │ ├── PagedList │ ├── IOrderedQueryableExtensions.cs │ ├── IPagedList.cs │ └── PagedList.cs │ └── Utils │ ├── CryptoRandom.cs │ └── Totp.cs └── test └── Arch.Standard.Tests ├── Arch.Standard.Tests.csproj ├── IPagedListTest.cs └── IStandardErrorTests.cs /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome:http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Don't use tabs for indentation. 7 | [*] 8 | indent_style = space 9 | # (Please don't specify an indent_size here; that has too many unintended consequences.) 10 | 11 | # Code files 12 | [*.{cs,csx,vb,vbx}] 13 | indent_size = 4 14 | 15 | # Xml project files 16 | [*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] 17 | indent_size = 2 18 | 19 | # Xml config files 20 | [*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}] 21 | indent_size = 2 22 | 23 | # JSON files 24 | [*.json] 25 | indent_size = 2 26 | 27 | # Dotnet code style settings: 28 | [*.{cs,vb}] 29 | # Sort using and Import directives with System.* appearing first 30 | dotnet_sort_system_directives_first = true 31 | # Avoid "this." and "Me." if not necessary 32 | dotnet_style_qualification_for_field = false:suggestion 33 | dotnet_style_qualification_for_property = false:suggestion 34 | dotnet_style_qualification_for_method = false:suggestion 35 | dotnet_style_qualification_for_event = false:suggestion 36 | 37 | # Use language keywords instead of framework type names for type references 38 | dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion 39 | dotnet_style_predefined_type_for_member_access = true:suggestion 40 | 41 | # Suggest more modern language features when available 42 | dotnet_style_object_initializer = true:suggestion 43 | dotnet_style_collection_initializer = true:suggestion 44 | dotnet_style_coalesce_expression = true:suggestion 45 | dotnet_style_null_propagation = true:suggestion 46 | dotnet_style_explicit_tuple_names = true:suggestion 47 | 48 | # CSharp code style settings: 49 | [*.cs] 50 | # Prefer "var" everywhere 51 | csharp_style_var_for_built_in_types = true:suggestion 52 | csharp_style_var_when_type_is_apparent = true:suggestion 53 | csharp_style_var_elsewhere = true:suggestion 54 | 55 | # Prefer method-like constructs to have a block body 56 | csharp_style_expression_bodied_methods = true:suggestion 57 | csharp_style_expression_bodied_constructors = true:suggestion 58 | csharp_style_expression_bodied_operators = true:suggestion 59 | 60 | # Prefer property-like constructs to have an expression-body 61 | csharp_style_expression_bodied_properties = true:suggestion 62 | csharp_style_expression_bodied_indexers = true:suggestion 63 | csharp_style_expression_bodied_accessors = true:suggestion 64 | 65 | # Suggest more modern language features when available 66 | csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion 67 | csharp_style_pattern_matching_over_as_with_null_check = true:suggestion 68 | csharp_style_inlined_variable_declaration = true:suggestion 69 | csharp_style_throw_expression = true:suggestion 70 | csharp_style_conditional_delegate_call = true:suggestion 71 | 72 | # Newline settings 73 | csharp_new_line_before_open_brace = all 74 | csharp_new_line_before_else = true 75 | csharp_new_line_before_catch = true 76 | csharp_new_line_before_finally = true 77 | csharp_new_line_before_members_in_object_initializers = true 78 | csharp_new_line_before_members_in_anonymous_types = true -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | *.VC.VC.opendb 85 | 86 | # Visual Studio profiler 87 | *.psess 88 | *.vsp 89 | *.vspx 90 | *.sap 91 | 92 | # TFS 2012 Local Workspace 93 | $tf/ 94 | 95 | # Guidance Automation Toolkit 96 | *.gpState 97 | 98 | # ReSharper is a .NET coding add-in 99 | _ReSharper*/ 100 | *.[Rr]e[Ss]harper 101 | *.DotSettings.user 102 | 103 | # JustCode is a .NET coding add-in 104 | .JustCode 105 | 106 | # TeamCity is a build add-in 107 | _TeamCity* 108 | 109 | # DotCover is a Code Coverage Tool 110 | *.dotCover 111 | 112 | # NCrunch 113 | _NCrunch_* 114 | .*crunch*.local.xml 115 | nCrunchTemp_* 116 | 117 | # MightyMoose 118 | *.mm.* 119 | AutoTest.Net/ 120 | 121 | # Web workbench (sass) 122 | .sass-cache/ 123 | 124 | # Installshield output folder 125 | [Ee]xpress/ 126 | 127 | # DocProject is a documentation generator add-in 128 | DocProject/buildhelp/ 129 | DocProject/Help/*.HxT 130 | DocProject/Help/*.HxC 131 | DocProject/Help/*.hhc 132 | DocProject/Help/*.hhk 133 | DocProject/Help/*.hhp 134 | DocProject/Help/Html2 135 | DocProject/Help/html 136 | 137 | # Click-Once directory 138 | publish/ 139 | 140 | # Publish Web Output 141 | *.[Pp]ublish.xml 142 | *.azurePubxml 143 | # TODO: Comment the next line if you want to checkin your web deploy settings 144 | # but database connection strings (with potential passwords) will be unencrypted 145 | *.pubxml 146 | *.publishproj 147 | 148 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 149 | # checkin your Azure Web App publish settings, but sensitive information contained 150 | # in these scripts will be unencrypted 151 | PublishScripts/ 152 | 153 | # NuGet Packages 154 | *.nupkg 155 | # The packages folder can be ignored because of Package Restore 156 | **/packages/* 157 | # except build/, which is used as an MSBuild target. 158 | !**/packages/build/ 159 | # Uncomment if necessary however generally it will be regenerated when needed 160 | #!**/packages/repositories.config 161 | # NuGet v3's project.json files produces more ignoreable files 162 | *.nuget.props 163 | *.nuget.targets 164 | 165 | # Microsoft Azure Build Output 166 | csx/ 167 | *.build.csdef 168 | 169 | # Microsoft Azure Emulator 170 | ecf/ 171 | rcf/ 172 | 173 | # Windows Store app package directories and files 174 | AppPackages/ 175 | BundleArtifacts/ 176 | Package.StoreAssociation.xml 177 | _pkginfo.txt 178 | 179 | # Visual Studio cache files 180 | # files ending in .cache can be ignored 181 | *.[Cc]ache 182 | # but keep track of directories ending in .cache 183 | !*.[Cc]ache/ 184 | 185 | # Others 186 | ClientBin/ 187 | ~$* 188 | *~ 189 | *.dbmdl 190 | *.dbproj.schemaview 191 | *.pfx 192 | *.publishsettings 193 | node_modules/ 194 | orleans.codegen.cs 195 | 196 | # Since there are multiple workflows, uncomment next line to ignore bower_components 197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 198 | #bower_components/ 199 | 200 | # RIA/Silverlight projects 201 | Generated_Code/ 202 | 203 | # Backup & report files from converting an old project file 204 | # to a newer Visual Studio version. Backup files are not needed, 205 | # because we have git ;-) 206 | _UpgradeReport_Files/ 207 | Backup*/ 208 | UpgradeLog*.XML 209 | UpgradeLog*.htm 210 | 211 | # SQL Server files 212 | *.mdf 213 | *.ldf 214 | 215 | # Business Intelligence projects 216 | *.rdl.data 217 | *.bim.layout 218 | *.bim_*.settings 219 | 220 | # Microsoft Fakes 221 | FakesAssemblies/ 222 | 223 | # GhostDoc plugin setting file 224 | *.GhostDoc.xml 225 | 226 | # Node.js Tools for Visual Studio 227 | .ntvs_analysis.dat 228 | 229 | # Visual Studio 6 build log 230 | *.plg 231 | 232 | # Visual Studio 6 workspace options file 233 | *.opt 234 | 235 | # Visual Studio LightSwitch build output 236 | **/*.HTMLClient/GeneratedArtifacts 237 | **/*.DesktopClient/GeneratedArtifacts 238 | **/*.DesktopClient/ModelManifest.xml 239 | **/*.Server/GeneratedArtifacts 240 | **/*.Server/ModelManifest.xml 241 | _Pvt_Extensions 242 | 243 | # Paket dependency manager 244 | .paket/paket.exe 245 | paket-files/ 246 | 247 | # FAKE - F# Make 248 | .fake/ 249 | 250 | # JetBrains Rider 251 | .idea/ 252 | *.sln.iml 253 | -------------------------------------------------------------------------------- /Arch.Standard.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26228.9 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Arch.Standard", "src\Arch.Standard\Arch.Standard.csproj", "{1895BE3B-7F81-471B-885D-FEE6025C81ED}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{F4562D4D-A918-4EF2-B3B1-D9851A398978}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{A857B0BB-30EE-4D4A-A688-CFC5EF7C027A}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Arch.Standard.Tests", "test\Arch.Standard.Tests\Arch.Standard.Tests.csproj", "{BEEEEF3D-F7EE-4506-98DD-0F984D14BBC3}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Release|Any CPU = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {1895BE3B-7F81-471B-885D-FEE6025C81ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {1895BE3B-7F81-471B-885D-FEE6025C81ED}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {1895BE3B-7F81-471B-885D-FEE6025C81ED}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {1895BE3B-7F81-471B-885D-FEE6025C81ED}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {BEEEEF3D-F7EE-4506-98DD-0F984D14BBC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {BEEEEF3D-F7EE-4506-98DD-0F984D14BBC3}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {BEEEEF3D-F7EE-4506-98DD-0F984D14BBC3}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {BEEEEF3D-F7EE-4506-98DD-0F984D14BBC3}.Release|Any CPU.Build.0 = Release|Any CPU 28 | EndGlobalSection 29 | GlobalSection(SolutionProperties) = preSolution 30 | HideSolutionNode = FALSE 31 | EndGlobalSection 32 | GlobalSection(NestedProjects) = preSolution 33 | {1895BE3B-7F81-471B-885D-FEE6025C81ED} = {F4562D4D-A918-4EF2-B3B1-D9851A398978} 34 | {BEEEEF3D-F7EE-4506-98DD-0F984D14BBC3} = {A857B0BB-30EE-4D4A-A688-CFC5EF7C027A} 35 | EndGlobalSection 36 | EndGlobal 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Arch 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NuGet.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /NuGetPackageVerifier.json: -------------------------------------------------------------------------------- 1 | { 2 | "Default": { 3 | "rules": [ 4 | "DefaultCompositeRule" 5 | ] 6 | } 7 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Standard 2 | This repo contains some core infrastructures for shared Standard domain/structure to be consumed across the Arch team's repos. 3 | -------------------------------------------------------------------------------- /src/Arch.Standard/ApiResult/ApiResult.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Arch team. All rights reserved. 2 | 3 | namespace Arch.Standard 4 | { 5 | /// 6 | /// Represents the default implementation of the interface. 7 | /// 8 | public class ApiResult : IApiResult 9 | { 10 | /// 11 | /// Gets or sets the status code. 12 | /// 13 | /// The status code. 14 | public int StatusCode { get; set; } 15 | 16 | /// 17 | /// Gets or sets the message. 18 | /// 19 | /// The message. 20 | public string Message { get; set; } 21 | } 22 | 23 | /// 24 | /// Represents the default implementation of the interface. 25 | /// 26 | /// The type of the result. 27 | public class ApiResult : ApiResult, IApiResult 28 | { 29 | /// 30 | /// Initializes a new instance of the class. 31 | /// 32 | public ApiResult() 33 | { 34 | 35 | } 36 | 37 | /// 38 | /// Initializes a new instance of the class. 39 | /// 40 | /// The result. 41 | /// The status code. 42 | /// The message. 43 | public ApiResult(TResult result, int statusCode, string message) 44 | { 45 | StatusCode = statusCode; 46 | Message = message; 47 | Result = result; 48 | } 49 | 50 | /// 51 | /// Gets or sets the result. 52 | /// 53 | /// The result. 54 | public TResult Result { get; set; } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Arch.Standard/ApiResult/IApiResult.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Arch team. All rights reserved. 2 | 3 | namespace Arch.Standard 4 | { 5 | /// 6 | /// Provides the interfaces for a empty api result. 7 | /// 8 | public interface IApiResult 9 | { 10 | /// 11 | /// Gets or sets the status code. 12 | /// 13 | /// The status code. 14 | int StatusCode { get; set; } 15 | 16 | /// 17 | /// Gets or sets the message. 18 | /// 19 | /// The message. 20 | string Message { get; set; } 21 | } 22 | 23 | /// 24 | /// Provides the interfaces for a generic api result. 25 | /// 26 | /// 27 | public interface IApiResult : IApiResult 28 | { 29 | /// 30 | /// Gets or sets the result. 31 | /// 32 | /// The result. 33 | TResult Result { get; set; } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Arch.Standard/Arch.Standard.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | This library contains some core infrastructures for shared Standard domain/structure to be consumed across the Arch team's libraries. 4 | 1.0.0 5 | rigofunc;rigofunc@outlook.com 6 | net461;netstandard1.6 7 | $(NoWarn);CS1591 8 | true 9 | true 10 | totp;apiresult;arch 11 | https://github.com/Arch/Standard 12 | https://github.com/Arch/Standard/blob/master/LICENSE 13 | git 14 | https://github.com/Arch/Standard.git 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/Arch.Standard/Cryptography/CryptoExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Arch team. All rights reserved. 2 | 3 | using System.Text; 4 | using System.Security.Cryptography; 5 | #if NET461 6 | using System.IO; 7 | #else 8 | using Org.BouncyCastle.Crypto.Engines; 9 | using Org.BouncyCastle.Crypto.Modes; 10 | using Org.BouncyCastle.Crypto.Paddings; 11 | using Org.BouncyCastle.Crypto.Parameters; 12 | #endif 13 | 14 | namespace Arch.Standard 15 | { 16 | /// 17 | /// Provides some extension methods for FCL encrpt and desrypt functionality. 18 | /// 19 | public static class CryptoExtensions 20 | { 21 | /// 22 | /// Encrypts the specified use triple DES. 23 | /// 24 | /// The input to encrypt. 25 | /// The encrypted result. 26 | public static byte[] TripleDesEncrypt(this byte[] input) 27 | { 28 | return default(byte[]); 29 | } 30 | 31 | /// 32 | /// Decrypts the specified use triple DES. 33 | /// 34 | /// The input to descrypt. 35 | /// The descrypted result. 36 | public static byte[] TripleDESDecrypt(this byte[] input) 37 | { 38 | return default(byte[]); 39 | } 40 | 41 | /// 42 | /// Encrypts the specified use DES. 43 | /// 44 | /// The input to encrypt. 45 | /// The key. 46 | /// The IV. 47 | /// The cipher mode. 48 | /// The padding mode. 49 | /// The encrypted result. 50 | public static byte[] DesEncrypt(this byte[] input, byte[] key, byte[] iv, CipherMode mode = CipherMode.CBC, PaddingMode paddingMode = PaddingMode.Zeros) 51 | { 52 | #if NET461 53 | var des = new DESCryptoServiceProvider() 54 | { 55 | Key = key, 56 | IV = iv, 57 | Mode = mode, 58 | Padding = paddingMode 59 | }; 60 | 61 | using(var ms = new MemoryStream()) 62 | { 63 | using(var cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write)) 64 | { 65 | cs.Write(input, 0, input.Length); 66 | cs.FlushFinalBlock(); 67 | return ms.ToArray(); 68 | } 69 | } 70 | #else 71 | var engine = new DesEngine(); 72 | var cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(engine), new ZeroBytePadding()); 73 | cipher.Init(true, new ParametersWithIV(new DesParameters(key), iv)); 74 | var rv = new byte[cipher.GetOutputSize(input.Length)]; 75 | var tam = cipher.ProcessBytes(input, 0, input.Length, rv, 0); 76 | cipher.DoFinal(rv, tam); 77 | 78 | return rv; 79 | #endif 80 | } 81 | 82 | /// 83 | /// Encrypts the specified use DES. 84 | /// 85 | /// The input to encrypt. 86 | /// The key. 87 | /// The IV. 88 | /// The encoding, the default value is gb2312 89 | /// The encrypted result. 90 | public static byte[] DesEncrypt(this string input, byte[] key, byte[] iv, string encoding="gb2312") => Encoding.GetEncoding(encoding).GetBytes(input).DesEncrypt(key, iv); 91 | 92 | /// 93 | /// Decrypts the specified use DES. 94 | /// 95 | /// The input to encrypt. 96 | /// The key. 97 | /// The IV. 98 | /// The cipher mode. 99 | /// The padding mode. 100 | /// The descrypted result. 101 | public static byte[] DESDecrypt(this byte[] input, byte[] key, byte[] iv, CipherMode mode = CipherMode.CBC, PaddingMode paddingMode = PaddingMode.Zeros) 102 | { 103 | #if NET461 104 | var des = new DESCryptoServiceProvider() 105 | { 106 | Key = key, 107 | IV = iv, 108 | Mode = mode, 109 | Padding = paddingMode 110 | }; 111 | 112 | using (var ms = new MemoryStream()) 113 | { 114 | using (var cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write)) 115 | { 116 | cs.Write(input, 0, input.Length); 117 | cs.FlushFinalBlock(); 118 | return ms.ToArray(); 119 | } 120 | } 121 | #else 122 | var engine = new DesEngine(); 123 | var cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(engine), new ZeroBytePadding()); 124 | cipher.Init(false, new ParametersWithIV(new DesParameters(key), iv)); 125 | var rv = new byte[cipher.GetOutputSize(input.Length)]; 126 | var tam = cipher.ProcessBytes(input, 0, input.Length, rv, 0); 127 | 128 | cipher.DoFinal(rv, tam); 129 | 130 | return rv; 131 | #endif 132 | } 133 | 134 | /// 135 | /// Decrypts the specified use DES. 136 | /// 137 | /// The input to encrypt. 138 | /// The key. 139 | /// The IV. 140 | /// The encoding, the default value is gb2312 141 | /// The descrypted result. 142 | public static byte[] DESDecrypt(this string input, byte[] key, byte[] iv, string encoding = "gb2312") => Encoding.GetEncoding(encoding).GetBytes(input).DESDecrypt(key, iv); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/Arch.Standard/Exceptions/IStandardError.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Arch team. All rights reserved. 2 | 3 | using System.Collections.Generic; 4 | 5 | namespace Arch.Standard 6 | { 7 | /// 8 | /// Defines the interface(s) for invoke error. 9 | /// 10 | /// 11 | /// The value for the "code" name/value pair is a language-independent string. 12 | /// Its value is a service-defined error code that SHOULD be human-readable. 13 | /// 14 | /// The value for the "message" name/value pair MUST be a human-readable representation of the error. 15 | /// It is intended as an aid to developers and is not suitable for exposure to end users. 16 | /// 17 | /// The value for the "target" name/value pair is the target of the particular error 18 | /// (e.g., the name of the property in error). 19 | /// 20 | /// The value for the "details" name/value pair MUST be an array of JSON objects that MUST contain name/value pairs for "code" 21 | /// and "message," and MAY contain a name/value pair for "target," as described above. 22 | /// 23 | /// The value for the "innererror" name/value pair MUST be an object. 24 | /// The contents of this object are service-defined. Services wanting to return more specific errors 25 | /// than the root-level code MUST do so by including a name/value pair for "code" and a nested "innererror." 26 | /// Each nested "innererror" object represents a higher level of detail than its parent. 27 | /// 28 | public interface IStandardError 29 | { 30 | /// 31 | /// Gets or sets the code for this error. 32 | /// 33 | /// 34 | /// The code for this error. 35 | /// 36 | string Code { get; set; } 37 | /// 38 | /// Gets or sets the message for this error. 39 | /// 40 | /// 41 | /// The message for this error. 42 | /// 43 | string Message { get; set; } 44 | /// 45 | /// Gets or sets the target of the particular error (e.g., the name of the property in error). 46 | /// 47 | /// The target of the particular error. 48 | string Target { get; set; } 49 | /// 50 | /// An object containing more specific information than the current object about the error. 51 | /// 52 | /// The inner error. 53 | IStandardError InnerError { get; set; } 54 | /// 55 | /// Gets or sets the details for this error. 56 | /// 57 | /// The details for this error. 58 | IEnumerable Details { get; set; } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Arch.Standard/Exceptions/StandardException.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Arch team. All rights reserved. 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Runtime.CompilerServices; 6 | 7 | namespace Arch.Standard 8 | { 9 | /// 10 | /// Represents an exception, which implements the interface. 11 | /// 12 | public class StandardException : Exception, IStandardError 13 | { 14 | private string _message; 15 | private List _details = new List(); 16 | 17 | /// 18 | /// Creates an indicating a failed invoke operation, with a if applicable. 19 | /// 20 | /// The code to represents the error. 21 | /// An message which description caused the operation to fail. 22 | /// The target of the particular error (e.g., the name of the property in error), the default value is the calloer member name 23 | /// An indicating a failed invoke operation, with a if applicable. 24 | public static StandardException Caused(string code, string message, [CallerMemberName]string target = null) => new StandardException 25 | { 26 | Code = code, 27 | Message = message, 28 | Target = target, 29 | }; 30 | 31 | /// 32 | /// Gets or sets the code for this error. 33 | /// 34 | /// 35 | /// The code for this error. 36 | /// 37 | public string Code { get; set; } 38 | 39 | /// 40 | /// Gets or sets the message for this error. 41 | /// 42 | /// 43 | /// The message for this error. 44 | /// 45 | public new string Message 46 | { 47 | get 48 | { 49 | if (string.IsNullOrEmpty(_message)) 50 | { 51 | return base.Message; 52 | } 53 | 54 | return _message; 55 | } 56 | set => _message = value; 57 | } 58 | 59 | /// 60 | /// Gets or sets the target of the particular error (e.g., the name of the property in error). 61 | /// 62 | /// The target of the particular error. 63 | public string Target { get; set; } 64 | 65 | /// 66 | /// Gets or sets the details for this error. 67 | /// 68 | /// The details for this error. 69 | public IEnumerable Details 70 | { 71 | get => _details; 72 | set 73 | { 74 | if (value != null) 75 | { 76 | _details.Clear(); 77 | _details.AddRange(value); 78 | } 79 | } 80 | } 81 | 82 | /// 83 | /// Gets or sets the inner error for this error. 84 | /// 85 | /// The inner error for this error. 86 | public IStandardError InnerError { get; set; } 87 | 88 | /// 89 | /// Throws this exception. 90 | /// 91 | public void Throw() => throw this; 92 | 93 | /// 94 | /// Appends an array of represents the details to current . 95 | /// 96 | /// The array of represents the details. 97 | /// Return the current instance for supporting fluent API feature. 98 | public StandardException Append(params IStandardError[] details) 99 | { 100 | if (details.Length > 0) 101 | { 102 | _details.AddRange(details); 103 | } 104 | 105 | // this for fluent API use 106 | // InvokeError.Caused(message).Append(details).Throw(); 107 | return this; 108 | } 109 | 110 | /// 111 | /// Appends an to current . 112 | /// 113 | /// The represents the details. 114 | /// Return the current instance for supporting fluent API feature. 115 | public StandardException Concat(Exception exception) 116 | { 117 | var error = new StandardException 118 | { 119 | Code = "excption", 120 | Message = exception.ToString(), 121 | }; 122 | 123 | _details.Add(error); 124 | 125 | // this for fluent API use 126 | // InvokeError.Caused(message).Append(details).Throw(); 127 | return this; 128 | } 129 | 130 | /// 131 | /// Appends an array of represents the details to current . 132 | /// 133 | /// The array of represents the details. 134 | /// Return the current instance for supporting fluent API feature. 135 | public StandardException Append(IEnumerable details) 136 | { 137 | if (details != null) 138 | { 139 | _details.AddRange(details); 140 | } 141 | 142 | return this; 143 | } 144 | 145 | /// 146 | /// Returns a that represents this instance. 147 | /// 148 | /// A that represents this instance. 149 | public override string ToString() 150 | { 151 | if(string.IsNullOrEmpty(Code) || string.IsNullOrEmpty(_message)) 152 | { 153 | return base.ToString(); 154 | } 155 | 156 | if (_details.Count == 0) 157 | { 158 | return $"{"{ "}\"Code\": \"{Code}\", \"Message\": \"{Message}\", \"Target\": \"{Target}\"{" }"}"; 159 | } 160 | else 161 | { 162 | return $"{"{ "}\"Code\": \"{Code}\", \"Message\": \"{Message}\", \"Details\": [{string.Join(",", _details)}]{" }"}"; 163 | } 164 | } 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /src/Arch.Standard/Extensions/ByteArrayExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Arch team. All rights reserved. 2 | 3 | using System; 4 | using System.Text; 5 | 6 | namespace Arch.Standard 7 | { 8 | /// 9 | /// Provides some extension methods for byte[]. 10 | /// 11 | public static class ByteArrayExtensions 12 | { 13 | /// 14 | /// Converts to base64 string. 15 | /// 16 | /// The input to convert. 17 | /// The base64 string. 18 | public static string ToBase64String(this byte[] input) => Convert.ToBase64String(input); 19 | 20 | /// 21 | /// Converts to base64 string and replace it's '+' to '-', '/' to '_' and '=' to '%3d'. 22 | /// 23 | /// The input to convert 24 | /// The base64 string and replace it's '+' to '-', '/' to '_' and '=' to '%3d' 25 | public static string ToUrlSuitable(this byte[] input) => input.ToBase64String().Replace("+", "-").Replace("/", "_").Replace("=", "%3d"); 26 | 27 | /// 28 | /// Converts byte array to hex string. 29 | /// 30 | /// The bytes to convert. 31 | /// The hex string. 32 | public static string ToHexString(this byte[] bytes) 33 | { 34 | var hex = new StringBuilder(bytes.Length * 2); 35 | foreach (var b in bytes) 36 | { 37 | hex.AppendFormat("{0:x2}", b); 38 | } 39 | 40 | return hex.ToString(); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Arch.Standard/Extensions/HashExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Arch team. All rights reserved. 2 | 3 | using System.Security.Cryptography; 4 | using System.Text; 5 | 6 | namespace Arch.Standard 7 | { 8 | /// 9 | /// Provides some extension methods for string hashing. 10 | /// 11 | public static class HashExtensions 12 | { 13 | private static byte[] _empty = new byte[0]; 14 | 15 | /// 16 | /// Creates the hash of the by the specified and . 17 | /// 18 | /// The plain text to hash. 19 | /// The hash algorithm, if specify null, will use MD5 algorithm. 20 | /// The encoding, the default value is gb2312 21 | /// The hashed value. 22 | public static byte[] Hash(this string plainText, HashAlgorithm hashAlgorithm, string encoding = "gb2312") 23 | { 24 | // get bytes from the plaintext 25 | var bytes = Encoding.GetEncoding(encoding).GetBytes(plainText); 26 | 27 | // encrypt 28 | using (var algorithm = hashAlgorithm ?? System.Security.Cryptography.MD5.Create()) 29 | { 30 | return algorithm.ComputeHash(bytes); 31 | } 32 | } 33 | 34 | /// 35 | /// Creates a MD5 hash of the specified input. 36 | /// 37 | /// The input. 38 | /// The encoding, the default value is gb2312 39 | /// The MD5 hash of the specified . 40 | public static byte[] MD5(this string input, string encoding = "gb2312") 41 | { 42 | if (string.IsNullOrEmpty(input)) 43 | return _empty; 44 | 45 | return Hash(input, System.Security.Cryptography.MD5.Create(), encoding); 46 | } 47 | 48 | /// 49 | /// Creates a SHA512 hash of the specified input. 50 | /// 51 | /// The input. 52 | /// The encoding, the default value is gb2312 53 | /// The SHA512 hash of the specified , the value is base64 string. 54 | public static byte[] Sha512(this string input, string encoding = "gb2312") 55 | { 56 | if (string.IsNullOrEmpty(input)) 57 | return _empty; 58 | 59 | return Hash(input, SHA512.Create(), encoding); 60 | } 61 | 62 | /// 63 | /// Creates a SHA256 hash of the specified input. 64 | /// 65 | /// The input. 66 | /// The encoding, the default value is gb2312 67 | /// The SHA256 hash of the specified , the value is base64 string. 68 | public static byte[] Sha256(this string input, string encoding = "gb2312") 69 | { 70 | if (string.IsNullOrEmpty(input)) 71 | return _empty; 72 | 73 | return Hash(input, SHA256.Create()); 74 | } 75 | 76 | /// 77 | /// Creates a SHA1 hash of the specified input. 78 | /// 79 | /// The input. 80 | /// The encoding, the default value is gb2312 81 | /// The hashed value. 82 | public static byte[] Sha1(this string input, string encoding = "gb2312") 83 | { 84 | if (string.IsNullOrEmpty(input)) 85 | return _empty; 86 | 87 | return Hash(input, SHA1.Create()); 88 | } 89 | 90 | /// 91 | /// Creates a SHA256 hash of the specified input. 92 | /// 93 | /// The input. 94 | /// The SHA256 hash of the specified . 95 | public static byte[] Sha256(this byte[] input) 96 | { 97 | if (input == null) 98 | { 99 | return null; 100 | } 101 | 102 | using (var sha = SHA256.Create()) 103 | { 104 | return sha.ComputeHash(input); 105 | } 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/Arch.Standard/Extensions/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Arch team. All rights reserved. 2 | 3 | using System; 4 | using System.Text; 5 | 6 | namespace Arch.Standard 7 | { 8 | /// 9 | /// Provides some extension methods for 10 | /// 11 | public static class StringExtensions 12 | { 13 | /// 14 | /// Removes trim string from the current String object. 15 | /// 16 | /// current string object 17 | /// trim string object 18 | /// 19 | /// 20 | public static string TrimStart(this string source, string trim, StringComparison stringComparison = StringComparison.Ordinal) 21 | { 22 | if (source == null) 23 | { 24 | return null; 25 | } 26 | 27 | string s = source; 28 | while (s.StartsWith(trim, stringComparison)) 29 | { 30 | s = s.Substring(trim.Length); 31 | } 32 | 33 | return s; 34 | } 35 | 36 | /// 37 | /// Removes trim string from the current String object. 38 | /// 39 | /// 40 | /// 41 | /// 42 | public static string TrimAfter(this string source, string trim) 43 | { 44 | int index = source.IndexOf(trim, StringComparison.Ordinal); 45 | if (index > 0) 46 | { 47 | source = source.Substring(0, index); 48 | } 49 | 50 | return source; 51 | } 52 | 53 | /// 54 | /// Escapes the string for MySQL. 55 | /// 56 | /// The value to escape 57 | /// The string with all quotes escaped. 58 | public static string MySQLEscape(this string value) 59 | { 60 | if (!IsQuoting(value)) 61 | return value; 62 | 63 | var sb = new StringBuilder(); 64 | foreach (var c in value) 65 | { 66 | var charClass = charClassArray[c]; 67 | if (charClass != CharKinds.None) 68 | { 69 | sb.Append("\\"); 70 | } 71 | sb.Append(c); 72 | } 73 | 74 | return sb.ToString(); 75 | } 76 | 77 | #region MySQLEscape Helpers 78 | 79 | enum CharKinds : byte 80 | { 81 | None, 82 | Quote, 83 | Backslash 84 | } 85 | 86 | private static string backslashChars = "\u005c\u00a5\u0160\u20a9\u2216\ufe68\uff3c"; 87 | private static string quoteChars = "\u0022\u0027\u0060\u00b4\u02b9\u02ba\u02bb\u02bc\u02c8\u02ca\u02cb\u02d9\u0300\u0301\u2018\u2019\u201a\u2032\u2035\u275b\u275c\uff07"; 88 | 89 | private static CharKinds[] charClassArray = MakeCharClassArray(); 90 | 91 | private static CharKinds[] MakeCharClassArray() 92 | { 93 | 94 | var a = new CharKinds[65536]; 95 | foreach (var c in backslashChars) 96 | { 97 | a[c] = CharKinds.Backslash; 98 | } 99 | foreach (var c in quoteChars) 100 | { 101 | a[c] = CharKinds.Quote; 102 | } 103 | 104 | return a; 105 | } 106 | 107 | private static bool IsQuoting(string str) 108 | { 109 | foreach (var c in str) 110 | { 111 | if (charClassArray[c] != CharKinds.None) 112 | { 113 | return true; 114 | } 115 | } 116 | 117 | return false; 118 | } 119 | 120 | #endregion 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/Arch.Standard/PagedList/IOrderedQueryableExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Arch team. All rights reserved. 2 | 3 | using System.Collections.Generic; 4 | using Arch.Standard; 5 | 6 | namespace System.Linq 7 | { 8 | /// 9 | /// Provides some extension methods for to provide paging capability. 10 | /// 11 | public static class IOrderedQueryableExtensions 12 | { 13 | /// 14 | /// Converts the specified source to by the specified and . 15 | /// 16 | /// The type of the source. 17 | /// The source to paging. 18 | /// The index of the page. 19 | /// The size of the page. 20 | /// The start index value. 21 | /// An instance of the inherited from interface. 22 | public static IPagedList ToPagedList(this IOrderedQueryable source, int pageIndex, int pageSize, int indexFrom = 0) => new PagedList(source, pageIndex, pageSize, indexFrom); 23 | 24 | /// 25 | /// Converts the specified source to by the specified , and 26 | /// 27 | /// The type of the source. 28 | /// The type of the result 29 | /// The source to convert. 30 | /// The converter to change the to . 31 | /// The page index. 32 | /// The page size. 33 | /// The start index value. 34 | /// An instance of the inherited from interface. 35 | public static IPagedList ToPagedList(this IOrderedQueryable source, Func, IEnumerable> converter, int pageIndex, int pageSize, int indexFrom = 0) => new PagedList(source, converter, pageIndex, pageSize, indexFrom); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Arch.Standard/PagedList/IPagedList.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Arch team. All rights reserved. 2 | 3 | using System.Collections.Generic; 4 | 5 | namespace Arch.Standard 6 | { 7 | /// 8 | /// Provides the interface(s) for paged list of any type. 9 | /// 10 | /// The type for paging. 11 | public interface IPagedList 12 | { 13 | /// 14 | /// Gets the index start value. 15 | /// 16 | /// The index start value. 17 | int IndexFrom { get; } 18 | /// 19 | /// Gets the page index (current). 20 | /// 21 | int PageIndex { get; } 22 | /// 23 | /// Gets the page size. 24 | /// 25 | int PageSize { get; } 26 | /// 27 | /// Gets the total count of the list of type 28 | /// 29 | int TotalCount { get; } 30 | /// 31 | /// Gets the total pages. 32 | /// 33 | int TotalPages { get; } 34 | /// 35 | /// Gets the current page items. 36 | /// 37 | IList Items { get; } 38 | /// 39 | /// Gets the has previous page. 40 | /// 41 | /// The has previous page. 42 | bool HasPreviousPage { get; } 43 | 44 | /// 45 | /// Gets the has next page. 46 | /// 47 | /// The has next page. 48 | bool HasNextPage { get; } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Arch.Standard/PagedList/PagedList.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Arch team. All rights reserved. 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | 7 | namespace Arch.Standard 8 | { 9 | /// 10 | /// Represents the default implementation of the interface. 11 | /// 12 | /// The type of the data to page 13 | public class PagedList : IPagedList 14 | { 15 | /// 16 | /// Gets or sets the index of the page. 17 | /// 18 | /// The index of the page. 19 | public int PageIndex { get; set; } 20 | /// 21 | /// Gets or sets the size of the page. 22 | /// 23 | /// The size of the page. 24 | public int PageSize { get; set; } 25 | /// 26 | /// Gets or sets the total count. 27 | /// 28 | /// The total count. 29 | public int TotalCount { get; set; } 30 | /// 31 | /// Gets or sets the total pages. 32 | /// 33 | /// The total pages. 34 | public int TotalPages { get; set; } 35 | /// 36 | /// Gets or sets the index from. 37 | /// 38 | /// The index from. 39 | public int IndexFrom { get; set; } 40 | 41 | /// 42 | /// Gets or sets the items. 43 | /// 44 | /// The items. 45 | public IList Items { get; set; } 46 | 47 | /// 48 | /// Gets the has previous page. 49 | /// 50 | /// The has previous page. 51 | public bool HasPreviousPage => PageIndex - IndexFrom > 0; 52 | 53 | /// 54 | /// Gets the has next page. 55 | /// 56 | /// The has next page. 57 | public bool HasNextPage => PageIndex - IndexFrom + 1 < TotalPages; 58 | 59 | /// 60 | /// Initializes a new instance of the class. 61 | /// 62 | /// The source. 63 | /// The index of the page. 64 | /// The size of the page. 65 | /// The index from. 66 | internal PagedList(IOrderedQueryable source, int pageIndex, int pageSize, int indexFrom) 67 | { 68 | if (indexFrom > pageIndex) 69 | { 70 | throw new ArgumentException($"indexFrom: {indexFrom} > pageIndex: {pageIndex}, must indexFrom <= pageIndex"); 71 | } 72 | 73 | PageIndex = pageIndex; 74 | PageSize = pageSize; 75 | IndexFrom = indexFrom; 76 | TotalCount = source.Count(); 77 | TotalPages = (int)Math.Ceiling(TotalCount / (double)PageSize); 78 | 79 | Items = source.Skip((PageIndex - IndexFrom) * PageSize).Take(PageSize).ToList(); 80 | } 81 | 82 | /// 83 | /// Initializes a new instance of the class. 84 | /// 85 | internal PagedList() => Items = new T[0]; 86 | } 87 | 88 | /// 89 | /// Provides the implementation of the and converter. 90 | /// 91 | /// The type of the source. 92 | /// The type of the result. 93 | internal class PagedList : IPagedList 94 | { 95 | /// 96 | /// Gets the index of the page. 97 | /// 98 | /// The index of the page. 99 | public int PageIndex { get; } 100 | /// 101 | /// Gets the size of the page. 102 | /// 103 | /// The size of the page. 104 | public int PageSize { get; } 105 | /// 106 | /// Gets the total count. 107 | /// 108 | /// The total count. 109 | public int TotalCount { get; } 110 | /// 111 | /// Gets the total pages. 112 | /// 113 | /// The total pages. 114 | public int TotalPages { get; } 115 | /// 116 | /// Gets the index from. 117 | /// 118 | /// The index from. 119 | public int IndexFrom { get; } 120 | 121 | /// 122 | /// Gets the items. 123 | /// 124 | /// The items. 125 | public IList Items { get; } 126 | 127 | /// 128 | /// Gets the has previous page. 129 | /// 130 | /// The has previous page. 131 | public bool HasPreviousPage => PageIndex - IndexFrom > 0; 132 | 133 | /// 134 | /// Gets the has next page. 135 | /// 136 | /// The has next page. 137 | public bool HasNextPage => PageIndex - IndexFrom + 1 < TotalPages; 138 | 139 | /// 140 | /// Initializes a new instance of the class. 141 | /// 142 | /// The source. 143 | /// The converter. 144 | /// The index of the page. 145 | /// The size of the page. 146 | /// The index from. 147 | public PagedList(IOrderedQueryable source, Func, IEnumerable> converter, int pageIndex, int pageSize, int indexFrom) 148 | { 149 | if (indexFrom > pageIndex) 150 | { 151 | throw new ArgumentException($"indexFrom: {indexFrom} > pageIndex: {pageIndex}, must indexFrom <= pageIndex"); 152 | } 153 | 154 | PageIndex = pageIndex; 155 | PageSize = pageSize; 156 | IndexFrom = indexFrom; 157 | TotalCount = source.Count(); 158 | TotalPages = (int)Math.Ceiling(TotalCount / (double)PageSize); 159 | 160 | var items = source.Skip((PageIndex - IndexFrom) * PageSize).Take(PageSize).ToArray(); 161 | 162 | Items = new List(converter(items)); 163 | } 164 | 165 | /// 166 | /// Initializes a new instance of the class. 167 | /// 168 | /// The source. 169 | /// The converter. 170 | public PagedList(IPagedList source, Func, IEnumerable> converter) 171 | { 172 | PageIndex = source.PageIndex; 173 | PageSize = source.PageSize; 174 | IndexFrom = source.IndexFrom; 175 | TotalCount = source.TotalCount; 176 | TotalPages = source.TotalPages; 177 | 178 | Items = new List(converter(source.Items)); 179 | } 180 | } 181 | 182 | /// 183 | /// Provides some help methods for interface. 184 | /// 185 | public static class PagedList 186 | { 187 | /// 188 | /// Creates an empty of . 189 | /// 190 | /// The type for paging 191 | /// An empty instance of . 192 | public static IPagedList Empty() => new PagedList(); 193 | /// 194 | /// Creates a new instance of from source of instance. 195 | /// 196 | /// The type of the result. 197 | /// The type of the source. 198 | /// The source. 199 | /// The converter. 200 | /// An instance of . 201 | public static IPagedList From(IPagedList source, Func, IEnumerable> converter) => new PagedList(source, converter); 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /src/Arch.Standard/Utils/CryptoRandom.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Arch team. All rights reserved. 2 | 3 | using System; 4 | using System.Text; 5 | using System.Security.Cryptography; 6 | 7 | namespace Arch.Standard.Utils 8 | { 9 | /// 10 | /// Provides the random utility which internal use random cryptography to implements the functionality. 11 | /// 12 | public class CryptoRandom 13 | { 14 | private static RandomNumberGenerator _rng = RandomNumberGenerator.Create(); 15 | 16 | /// 17 | /// Creates a random bytes, which's length specified by . 18 | /// 19 | /// The length of the bytes. 20 | /// The random bytes. 21 | public static byte[] CreateRandomBytes(int length) 22 | { 23 | var bytes = new byte[length]; 24 | _rng.GetBytes(bytes); 25 | 26 | return bytes; 27 | } 28 | 29 | /// 30 | /// Creates a random key, which's length specified by the . 31 | /// 32 | /// The length of the key. 33 | /// A random key, which's length specified by the . 34 | public static string CreateRandomKey(int length) 35 | { 36 | var bytes = new byte[length]; 37 | _rng.GetBytes(bytes); 38 | 39 | return Convert.ToBase64String(CreateRandomBytes(length)); 40 | } 41 | 42 | /// 43 | /// Creates an unique key by the specified length. 44 | /// 45 | /// The length of key. 46 | /// The unique key. 47 | public static string CreateUniqueKey(int length = 8) => CreateRandomBytes(length).ToHexString(); 48 | 49 | /// 50 | /// Creates a series number prefix by and yyyyMMddHHmmss. 51 | /// 52 | /// The prefix of the series number. 53 | /// 54 | public static string CreateSeriesNumber(string prefix = "SW") => $"{prefix}{DateTime.Now.ToString("yyyyMMddHHmmss")}{CreateUniqueKey()}"; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Arch.Standard/Utils/Totp.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Arch team. All rights reserved. 2 | 3 | using System; 4 | using System.Diagnostics; 5 | using System.Net; 6 | using System.Security.Cryptography; 7 | using System.Text; 8 | 9 | namespace Arch.Standard.Utils 10 | { 11 | /// 12 | /// https://tools.ietf.org/html/rfc6238 13 | /// 14 | public static class Totp 15 | { 16 | private static readonly DateTime _unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); 17 | private static TimeSpan _timestep = TimeSpan.FromMinutes(3); 18 | private static readonly Encoding _encoding = new UTF8Encoding(false, true); 19 | 20 | private static int ComputeTotp(HashAlgorithm hashAlgorithm, ulong timestepNumber, string modifier) 21 | { 22 | // # of 0's = length of pin 23 | const int Mod = 1000000; 24 | 25 | // See https://tools.ietf.org/html/rfc4226 26 | // We can add an optional modifier 27 | var timestepAsBytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((long)timestepNumber)); 28 | var hash = hashAlgorithm.ComputeHash(ApplyModifier(timestepAsBytes, modifier)); 29 | 30 | // Generate DT string 31 | var offset = hash[hash.Length - 1] & 0xf; 32 | Debug.Assert(offset + 4 < hash.Length); 33 | var binaryCode = (hash[offset] & 0x7f) << 24 34 | | (hash[offset + 1] & 0xff) << 16 35 | | (hash[offset + 2] & 0xff) << 8 36 | | (hash[offset + 3] & 0xff); 37 | 38 | return binaryCode % Mod; 39 | } 40 | 41 | private static byte[] ApplyModifier(byte[] input, string modifier) 42 | { 43 | if (string.IsNullOrEmpty(modifier)) 44 | { 45 | return input; 46 | } 47 | 48 | var modifierBytes = _encoding.GetBytes(modifier); 49 | var combined = new byte[checked(input.Length + modifierBytes.Length)]; 50 | Buffer.BlockCopy(input, 0, combined, 0, input.Length); 51 | Buffer.BlockCopy(modifierBytes, 0, combined, input.Length, modifierBytes.Length); 52 | return combined; 53 | } 54 | 55 | // More info: https://tools.ietf.org/html/rfc6238#section-4 56 | private static ulong GetCurrentTimeStepNumber() 57 | { 58 | var delta = DateTime.UtcNow - _unixEpoch; 59 | return (ulong)(delta.Ticks / _timestep.Ticks); 60 | } 61 | 62 | /// 63 | /// Generates code for the specified . 64 | /// 65 | /// The security token to generate code. 66 | /// The modifier. 67 | /// The generated code. 68 | public static int GenerateCode(byte[] securityToken, string modifier = null) 69 | { 70 | if (securityToken == null) 71 | { 72 | throw new ArgumentNullException(nameof(securityToken)); 73 | } 74 | 75 | // Allow a variance of no greater than 90 seconds in either direction 76 | var currentTimeStep = GetCurrentTimeStepNumber(); 77 | using (var hashAlgorithm = new HMACSHA1(securityToken)) 78 | { 79 | return ComputeTotp(hashAlgorithm, currentTimeStep, modifier); 80 | } 81 | } 82 | 83 | /// 84 | /// Validates the code for the specified . 85 | /// 86 | /// The security token for verifying. 87 | /// The code to validate. 88 | /// The modifier 89 | /// True if validate succeed, otherwise, false. 90 | public static bool ValidateCode(byte[] securityToken, int code, string modifier = null) 91 | { 92 | if (securityToken == null) 93 | { 94 | throw new ArgumentNullException(nameof(securityToken)); 95 | } 96 | 97 | // Allow a variance of no greater than 90 seconds in either direction 98 | var currentTimeStep = GetCurrentTimeStepNumber(); 99 | using (var hashAlgorithm = new HMACSHA1(securityToken)) 100 | { 101 | for (var i = -2; i <= 2; i++) 102 | { 103 | var computedTotp = ComputeTotp(hashAlgorithm, (ulong)((long)currentTimeStep + i), modifier); 104 | if (computedTotp == code) 105 | { 106 | return true; 107 | } 108 | } 109 | } 110 | 111 | // No match 112 | return false; 113 | } 114 | 115 | /// 116 | /// Generates code for the specified . 117 | /// 118 | /// The security token to generate code. 119 | /// The modifier. 120 | /// The generated code. 121 | public static int GenerateCode(string securityToken, string modifier = null) => GenerateCode(Encoding.Unicode.GetBytes(securityToken), modifier); 122 | 123 | /// 124 | /// Validates the code for the specified . 125 | /// 126 | /// The security token for verifying. 127 | /// The code to validate. 128 | /// The modifier 129 | /// True if validate succeed, otherwise, false. 130 | public static bool ValidateCode(string securityToken, int code, string modifier = null) => ValidateCode(Encoding.Unicode.GetBytes(securityToken), code, modifier); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /test/Arch.Standard.Tests/Arch.Standard.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp1.1;net461 5 | $(NoWarn);CS1591 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /test/Arch.Standard.Tests/IPagedListTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | using Xunit; 6 | using Newtonsoft.Json; 7 | 8 | namespace Arch.Standard.Tests 9 | { 10 | public class User 11 | { 12 | public int Id { get; set; } 13 | 14 | public string Username { get; set; } 15 | 16 | public string Password { get; set; } 17 | } 18 | 19 | public class IPagedListTest 20 | { 21 | private readonly IList _users; 22 | public IPagedListTest() 23 | { 24 | _users = new User[] 25 | { 26 | new User 27 | { 28 | Id = 1, 29 | Username = "rigofunc", 30 | Password = "p@ssword" 31 | }, 32 | new User 33 | { 34 | Id = 2, 35 | Username = "yingtingxu", 36 | Password = "p@ssword" 37 | } 38 | }; 39 | } 40 | 41 | [Fact] 42 | public void IPagedList_Can_Json_Serialized_And_Deserialized_Test() 43 | { 44 | var querable = _users.AsQueryable(); 45 | 46 | var pagedUsers = querable.OrderBy(u => u.Id).ToPagedList(0, 10, 0); 47 | 48 | var json = JsonConvert.SerializeObject(pagedUsers); 49 | 50 | Assert.False(string.IsNullOrEmpty(json)); 51 | 52 | var users = JsonConvert.DeserializeObject>(json); 53 | 54 | Assert.IsAssignableFrom>(users); 55 | 56 | Assert.Equal(2, users.Items.Count); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /test/Arch.Standard.Tests/IStandardErrorTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Arch team of Tencent. All rights reserved. 2 | 3 | using System; 4 | using System.Linq; 5 | using Xunit; 6 | using Newtonsoft.Json; 7 | 8 | namespace Arch.Standard.Tests 9 | { 10 | public class IStandardErrorTests 11 | { 12 | [Fact] 13 | public void IStandardError_Target_IsCallerMemberName_Test() 14 | { 15 | var error = StandardException.Caused("Code", "xUnit"); 16 | 17 | Assert.Equal(nameof(IStandardError_Target_IsCallerMemberName_Test), error.Target); 18 | Assert.Equal("xUnit", error.Message); 19 | } 20 | 21 | [Fact] 22 | public void IStandardError_Fluent_API_Feature_Test() 23 | { 24 | Assert.Throws(() => { 25 | StandardException.Caused("Code", "xunit").Append(StandardException.Caused("InnerCode", "details")).Throw(); 26 | }); 27 | } 28 | 29 | [Fact] 30 | public void IStandardError_Can_Json_Serialize_Test() 31 | { 32 | var exception = StandardException.Caused("Code", "xunit").Append(StandardException.Caused("InnerCode", "details", "InnerTarget")); 33 | 34 | var json = JsonConvert.SerializeObject(exception); 35 | 36 | Assert.False(string.IsNullOrEmpty(json)); 37 | } 38 | } 39 | } 40 | --------------------------------------------------------------------------------