├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── README_zh_cn.md
├── SharpRedis.sln
├── alipay.png
├── examples
├── Example_NET30
│ ├── Example_NET30.csproj
│ ├── Program.cs
│ └── Properties
│ │ └── AssemblyInfo.cs
├── Example_NET46
│ ├── App.config
│ ├── Example_NET46.csproj
│ ├── Program.cs
│ └── Properties
│ │ └── AssemblyInfo.cs
├── Example_NET8
│ ├── Example_NET8.csproj
│ ├── LocalCache.cs
│ ├── Program.cs
│ └── ProgramLocalCache.cs
└── Example_NET9
│ ├── Example_NET9.csproj
│ └── Program.cs
├── src
├── SharpRedis.Autofac
│ ├── RegistrationExtensions.cs
│ └── SharpRedis.Autofac.csproj
├── SharpRedis.DependencyInjection
│ ├── RegistrationExtensions.cs
│ └── SharpRedis.DependencyInjection.csproj
├── SharpRedis.DependencyInjectionKeyedService
│ ├── RegistrationExtensions.cs
│ └── SharpRedis.DependencyInjectionKeyedService.csproj
├── SharpRedis.Unity
│ ├── RegistrationExtensions.cs
│ └── SharpRedis.Unity.csproj
└── SharpRedis
│ ├── Commands
│ ├── BitmapCommands.cs
│ ├── ConnectionCommands.cs
│ ├── GeospatialCommands.cs
│ ├── HashCommands.cs
│ ├── HyperLogLogCommands.cs
│ ├── KeyCommands.cs
│ ├── ListCommands.cs
│ ├── PubSubCommands.cs
│ ├── ScriptCommands.cs
│ ├── ServerCommands.cs
│ ├── SetCommands.cs
│ ├── SortedSetCommands.cs
│ ├── StreamCommands.cs
│ ├── StringCommands.cs
│ └── TransactionCommands.cs
│ ├── Exceptions
│ ├── RedisConnectionException.cs
│ ├── RedisException.cs
│ └── RedisInitializationException.cs
│ ├── Extensions
│ ├── ClientSideCachingExtensions.cs
│ ├── ConnectionExtensions.cs
│ ├── ConvertExtensions.cs
│ ├── DataPacketExtensions.cs
│ ├── Extend.cs
│ ├── RedisExtensions.cs
│ ├── SharpConsole.cs
│ ├── StringExtensions.cs
│ ├── net30
│ │ ├── Action.cs
│ │ ├── Redis.cs
│ │ └── RedisSwitchDatabase.cs
│ ├── net30_35_40_45
│ │ └── Array.cs
│ └── net35_30
│ │ ├── CancellationToken.cs
│ │ ├── CancellationTokenSource.cs
│ │ ├── ConcurrentDictionary.cs
│ │ ├── ConcurrentQueue.cs
│ │ ├── ConcurrentStack.cs
│ │ └── StructuralEqualityComparer.cs
│ ├── Models
│ ├── BitFieldArg.cs
│ ├── ChannelMode.cs
│ ├── ClientSideCacheKey.cs
│ ├── CommandPacket.cs
│ ├── ConnectionOptions.cs
│ ├── Delegates.cs
│ ├── Enums.cs
│ ├── OnReceiveModel.cs
│ ├── Standard
│ │ ├── IBitFieldArg.cs
│ │ ├── IBitFieldArgEncoding.cs
│ │ ├── IBitFieldArgIncrement.cs
│ │ ├── IBitFieldArgOffset.cs
│ │ ├── IBitFieldArgOverflow.cs
│ │ └── IBitFieldArgValue.cs
│ └── StreamTrimOptions.cs
│ ├── Network
│ ├── DefaultConnection.cs
│ ├── Pool
│ │ ├── DefaultPool.cs
│ │ └── MasterSlavePool.cs
│ ├── Standard
│ │ ├── BaseConnection.cs
│ │ ├── BaseConnectionPool.cs
│ │ ├── IConnection.cs
│ │ └── IConnectionPool.cs
│ └── SubConnection.cs
│ ├── Provider
│ ├── Calls
│ │ ├── ClientSideCachingCall.cs
│ │ ├── DefaultCall.cs
│ │ ├── MasterSlaveCall.cs
│ │ ├── PipeliningCall.cs
│ │ ├── SwitchDatabaseCall.cs
│ │ └── TransactionCall.cs
│ ├── Redis.cs
│ ├── RedisPipelining.cs
│ ├── RedisSwitchDatabase.cs
│ ├── RedisTransaction.cs
│ ├── Standard
│ │ ├── BaseCall.cs
│ │ ├── BaseRedis.cs
│ │ ├── BaseType.cs
│ │ ├── ClientSideCachingStandard.cs
│ │ └── FeatureRedis.cs
│ └── Types
│ │ ├── Bitmap
│ │ ├── RedisBitmap.cs
│ │ └── RedisBitmapAsync.cs
│ │ ├── Geospatial
│ │ ├── RedisGeospatialIndices.cs
│ │ ├── RedisGeospatialIndicesAsync.cs
│ │ └── RedisGeospatialIndicesSpan.cs
│ │ ├── Hash
│ │ ├── RedisHash.cs
│ │ ├── RedisHashAsync.cs
│ │ └── RedisHashSpan.cs
│ │ ├── HyperLogLog
│ │ ├── RedisHyperLogLog.cs
│ │ ├── RedisHyperLogLogAsync.cs
│ │ └── RedisHyperLogLogSpan.cs
│ │ ├── Key
│ │ ├── RedisKey.cs
│ │ └── RedisKeyAsync.cs
│ │ ├── List
│ │ ├── RedisList.cs
│ │ ├── RedisListAsync.cs
│ │ └── RedisListSpan.cs
│ │ ├── PubSub
│ │ ├── RedisPubSub.cs
│ │ ├── RedisPubSubAsync.cs
│ │ └── RedisPubSubSpan.cs
│ │ ├── RedisConnection.cs
│ │ ├── Script
│ │ ├── RedisScript.cs
│ │ └── RedisScriptAsync.cs
│ │ ├── Server
│ │ ├── RedisServer.cs
│ │ └── RedisServerAsync.cs
│ │ ├── Set
│ │ ├── RedisSet.cs
│ │ ├── RedisSetAsync.cs
│ │ └── RedisSetSpan.cs
│ │ ├── SortedSet
│ │ ├── RedisSortedSet.cs
│ │ ├── RedisSortedSetAsync.cs
│ │ └── RedisSortedSetSpan.cs
│ │ ├── Stream
│ │ ├── RedisStream.cs
│ │ ├── RedisStreamAsync.cs
│ │ └── RedisStreamSpan.cs
│ │ └── String
│ │ ├── RedisString.cs
│ │ ├── RedisStringAsync.cs
│ │ └── RedisStringSpan.cs
│ ├── SharpRedis.csproj
│ └── Values
│ ├── BooleanValue.cs
│ ├── CoordinateValue.cs
│ ├── FunctionInfoValue.cs
│ ├── FunctionStatsValue.cs
│ ├── GeoRadiusValue.cs
│ ├── LcsValue.cs
│ ├── MemberScoreValue.cs
│ ├── NumberValue.cs
│ ├── ScanValue.cs
│ ├── ScoreRankValue.cs
│ ├── StreamValue.cs
│ ├── TransactionValue.cs
│ ├── XAutoClaimValue.cs
│ ├── XInfoConsumersValue.cs
│ ├── XInfoGroupsValue.cs
│ ├── XInfoStreamFullValue.cs
│ └── XInfoStreamValue.cs
├── test
└── NET8_Test
│ ├── NET8_Test.csproj
│ ├── RedisProvider.cs
│ └── Types
│ ├── GeoTest.cs
│ ├── HashTest.cs
│ ├── ListTest.cs
│ ├── ScriptTest.cs
│ ├── SetTest.cs
│ ├── SortedSetTest.cs
│ └── StringTest.cs
└── wechat.png
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 SharpRedis Project
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.
--------------------------------------------------------------------------------
/SharpRedis.sln:
--------------------------------------------------------------------------------
1 | Microsoft Visual Studio Solution File, Format Version 12.00
2 | # Visual Studio Version 17
3 | VisualStudioVersion = 17.10.35027.167
4 | MinimumVisualStudioVersion = 10.0.40219.1
5 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{954381ED-C4AD-45EB-AD53-C764813E0605}"
6 | EndProject
7 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{AF6960AD-895B-4D10-8444-F0550606B52F}"
8 | EndProject
9 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharpRedis", "src\SharpRedis\SharpRedis.csproj", "{AA255161-C3F4-498B-8104-A92E908398B6}"
10 | EndProject
11 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example_NET30", "examples\Example_NET30\Example_NET30.csproj", "{B8FBAFFC-7324-405D-A63E-6FC6C2CB583B}"
12 | EndProject
13 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example_NET46", "examples\Example_NET46\Example_NET46.csproj", "{7A5B557D-2A2D-4A11-9CAE-9AFF8097EA7C}"
14 | EndProject
15 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Example_NET8", "examples\Example_NET8\Example_NET8.csproj", "{56FD24A1-C7D9-4078-81F0-58175D91CFA9}"
16 | EndProject
17 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{25AA3EFE-8ACA-4534-A87E-A7ECA043C89F}"
18 | EndProject
19 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NET8_Test", "test\NET8_Test\NET8_Test.csproj", "{3D38F0BC-A5C7-49FE-8141-2C44B6E811AA}"
20 | EndProject
21 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharpRedis.Autofac", "src\SharpRedis.Autofac\SharpRedis.Autofac.csproj", "{0B8182F7-0231-4260-8B94-416D64F55504}"
22 | EndProject
23 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharpRedis.Unity", "src\SharpRedis.Unity\SharpRedis.Unity.csproj", "{1700E6DB-20DE-4BB8-B196-4C9E9495AD27}"
24 | EndProject
25 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpRedis.DependencyInjection", "src\SharpRedis.DependencyInjection\SharpRedis.DependencyInjection.csproj", "{C93AAC1A-BF01-4351-A73E-6D83D9E3EE7D}"
26 | EndProject
27 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpRedis.DependencyInjectionKeyedService", "src\SharpRedis.DependencyInjectionKeyedService\SharpRedis.DependencyInjectionKeyedService.csproj", "{BF90AB6F-46F4-49F4-AF9B-EEF710F765DD}"
28 | EndProject
29 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example_NET9", "examples\Example_NET9\Example_NET9.csproj", "{4E0B764B-88A1-4348-BA7C-CF1D1693D7E5}"
30 | EndProject
31 | Global
32 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
33 | Debug|Any CPU = Debug|Any CPU
34 | Release|Any CPU = Release|Any CPU
35 | EndGlobalSection
36 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
37 | {AA255161-C3F4-498B-8104-A92E908398B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
38 | {AA255161-C3F4-498B-8104-A92E908398B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
39 | {AA255161-C3F4-498B-8104-A92E908398B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
40 | {AA255161-C3F4-498B-8104-A92E908398B6}.Release|Any CPU.Build.0 = Release|Any CPU
41 | {B8FBAFFC-7324-405D-A63E-6FC6C2CB583B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
42 | {B8FBAFFC-7324-405D-A63E-6FC6C2CB583B}.Debug|Any CPU.Build.0 = Debug|Any CPU
43 | {B8FBAFFC-7324-405D-A63E-6FC6C2CB583B}.Release|Any CPU.ActiveCfg = Release|Any CPU
44 | {B8FBAFFC-7324-405D-A63E-6FC6C2CB583B}.Release|Any CPU.Build.0 = Release|Any CPU
45 | {7A5B557D-2A2D-4A11-9CAE-9AFF8097EA7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
46 | {7A5B557D-2A2D-4A11-9CAE-9AFF8097EA7C}.Debug|Any CPU.Build.0 = Debug|Any CPU
47 | {7A5B557D-2A2D-4A11-9CAE-9AFF8097EA7C}.Release|Any CPU.ActiveCfg = Release|Any CPU
48 | {7A5B557D-2A2D-4A11-9CAE-9AFF8097EA7C}.Release|Any CPU.Build.0 = Release|Any CPU
49 | {56FD24A1-C7D9-4078-81F0-58175D91CFA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
50 | {56FD24A1-C7D9-4078-81F0-58175D91CFA9}.Debug|Any CPU.Build.0 = Debug|Any CPU
51 | {56FD24A1-C7D9-4078-81F0-58175D91CFA9}.Release|Any CPU.ActiveCfg = Release|Any CPU
52 | {56FD24A1-C7D9-4078-81F0-58175D91CFA9}.Release|Any CPU.Build.0 = Release|Any CPU
53 | {3D38F0BC-A5C7-49FE-8141-2C44B6E811AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
54 | {3D38F0BC-A5C7-49FE-8141-2C44B6E811AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
55 | {3D38F0BC-A5C7-49FE-8141-2C44B6E811AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
56 | {3D38F0BC-A5C7-49FE-8141-2C44B6E811AA}.Release|Any CPU.Build.0 = Release|Any CPU
57 | {0B8182F7-0231-4260-8B94-416D64F55504}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
58 | {0B8182F7-0231-4260-8B94-416D64F55504}.Debug|Any CPU.Build.0 = Debug|Any CPU
59 | {0B8182F7-0231-4260-8B94-416D64F55504}.Release|Any CPU.ActiveCfg = Release|Any CPU
60 | {0B8182F7-0231-4260-8B94-416D64F55504}.Release|Any CPU.Build.0 = Release|Any CPU
61 | {1700E6DB-20DE-4BB8-B196-4C9E9495AD27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
62 | {1700E6DB-20DE-4BB8-B196-4C9E9495AD27}.Debug|Any CPU.Build.0 = Debug|Any CPU
63 | {1700E6DB-20DE-4BB8-B196-4C9E9495AD27}.Release|Any CPU.ActiveCfg = Release|Any CPU
64 | {1700E6DB-20DE-4BB8-B196-4C9E9495AD27}.Release|Any CPU.Build.0 = Release|Any CPU
65 | {C93AAC1A-BF01-4351-A73E-6D83D9E3EE7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
66 | {C93AAC1A-BF01-4351-A73E-6D83D9E3EE7D}.Debug|Any CPU.Build.0 = Debug|Any CPU
67 | {C93AAC1A-BF01-4351-A73E-6D83D9E3EE7D}.Release|Any CPU.ActiveCfg = Release|Any CPU
68 | {C93AAC1A-BF01-4351-A73E-6D83D9E3EE7D}.Release|Any CPU.Build.0 = Release|Any CPU
69 | {BF90AB6F-46F4-49F4-AF9B-EEF710F765DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
70 | {BF90AB6F-46F4-49F4-AF9B-EEF710F765DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
71 | {BF90AB6F-46F4-49F4-AF9B-EEF710F765DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
72 | {BF90AB6F-46F4-49F4-AF9B-EEF710F765DD}.Release|Any CPU.Build.0 = Release|Any CPU
73 | {4E0B764B-88A1-4348-BA7C-CF1D1693D7E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
74 | {4E0B764B-88A1-4348-BA7C-CF1D1693D7E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
75 | {4E0B764B-88A1-4348-BA7C-CF1D1693D7E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
76 | {4E0B764B-88A1-4348-BA7C-CF1D1693D7E5}.Release|Any CPU.Build.0 = Release|Any CPU
77 | EndGlobalSection
78 | GlobalSection(SolutionProperties) = preSolution
79 | HideSolutionNode = FALSE
80 | EndGlobalSection
81 | GlobalSection(NestedProjects) = preSolution
82 | {AA255161-C3F4-498B-8104-A92E908398B6} = {954381ED-C4AD-45EB-AD53-C764813E0605}
83 | {B8FBAFFC-7324-405D-A63E-6FC6C2CB583B} = {AF6960AD-895B-4D10-8444-F0550606B52F}
84 | {7A5B557D-2A2D-4A11-9CAE-9AFF8097EA7C} = {AF6960AD-895B-4D10-8444-F0550606B52F}
85 | {56FD24A1-C7D9-4078-81F0-58175D91CFA9} = {AF6960AD-895B-4D10-8444-F0550606B52F}
86 | {3D38F0BC-A5C7-49FE-8141-2C44B6E811AA} = {25AA3EFE-8ACA-4534-A87E-A7ECA043C89F}
87 | {0B8182F7-0231-4260-8B94-416D64F55504} = {954381ED-C4AD-45EB-AD53-C764813E0605}
88 | {1700E6DB-20DE-4BB8-B196-4C9E9495AD27} = {954381ED-C4AD-45EB-AD53-C764813E0605}
89 | {C93AAC1A-BF01-4351-A73E-6D83D9E3EE7D} = {954381ED-C4AD-45EB-AD53-C764813E0605}
90 | {BF90AB6F-46F4-49F4-AF9B-EEF710F765DD} = {954381ED-C4AD-45EB-AD53-C764813E0605}
91 | {4E0B764B-88A1-4348-BA7C-CF1D1693D7E5} = {AF6960AD-895B-4D10-8444-F0550606B52F}
92 | EndGlobalSection
93 | GlobalSection(ExtensibilityGlobals) = postSolution
94 | SolutionGuid = {47F37E65-68EA-49EA-B6BC-D45DE1E856FD}
95 | EndGlobalSection
96 | EndGlobal
97 |
--------------------------------------------------------------------------------
/alipay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/q7164518/SharpRedis/77755066436b6e8cfb08d469a1256e1a59f998f3/alipay.png
--------------------------------------------------------------------------------
/examples/Example_NET30/Example_NET30.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {B8FBAFFC-7324-405D-A63E-6FC6C2CB583B}
8 | Exe
9 | Example_NET30
10 | Example_NET30
11 | v3.0
12 | 512
13 | true
14 |
15 |
16 | AnyCPU
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 | true
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | {58ed8253-a396-4934-8b60-9330a5a46d46}
47 | SharpRedis
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/examples/Example_NET30/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Threading;
5 | using SharpRedis;
6 |
7 | namespace Example_NET30
8 | {
9 | internal class Program
10 | {
11 | static void Main(string[] args)
12 | {
13 | var redis = Redis.UseStandalone(f =>
14 | {
15 | f.Password = "123456";
16 | f.MaxPoolSize = 300;
17 | });
18 | redis.Server.FlushAll();
19 | redis.String.Set("k1", "k1");
20 | redis.String.Set("num", "1");
21 | redis.Hash.HSet("h", "f", "嘿嘿");
22 | redis.List.RPush("list", new string[] { "123", "456" });
23 |
24 |
25 | for (int i = 0; i < 300; i++)
26 | {
27 | new Thread(() =>
28 | {
29 | int indexx = i;
30 | int iii = indexx % 2;
31 | while (true)
32 | {
33 | var k1 = redis.String.Get("k1");
34 | if (k1 != "k1") Console.WriteLine("k1错误");
35 |
36 | redis.String.Incr("num");
37 |
38 | var hf = redis.Hash.HGet("h", "f");
39 | if (hf != "嘿嘿") Console.WriteLine("hash错误");
40 |
41 | var list = redis.List.LIndex("list", iii);
42 | if (iii == 0 && list != "123") Console.WriteLine("list错误");
43 | if (iii == 1 && list != "456") Console.WriteLine("list错误");
44 | }
45 | }).Start();
46 | }
47 | Console.WriteLine("启动成功, NET3.0");
48 | Console.ReadLine();
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/examples/Example_NET30/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的一般信息由以下
6 | // 控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("Example_NET30")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Example_NET30")]
13 | [assembly: AssemblyCopyright("Copyright © 2024")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // 将 ComVisible 设置为 false 会使此程序集中的类型
18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
19 | //请将此类型的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("b8fbaffc-7324-405d-a63e-6fc6c2cb583b")]
24 |
25 | // 程序集的版本信息由下列四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 生成号
30 | // 修订号
31 | //
32 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
33 | //通过使用 "*",如下所示:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/examples/Example_NET46/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/examples/Example_NET46/Example_NET46.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {7A5B557D-2A2D-4A11-9CAE-9AFF8097EA7C}
8 | Exe
9 | Example_NET46
10 | Example_NET46
11 | v4.6
12 | 512
13 | true
14 | true
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | {58ed8253-a396-4934-8b60-9330a5a46d46}
55 | SharpRedis
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/examples/Example_NET46/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 | using SharpRedis;
8 |
9 | namespace Example_NET46
10 | {
11 | internal class Program
12 | {
13 | static void Main(string[] args)
14 | {
15 | Console.ReadLine();
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/examples/Example_NET46/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的一般信息由以下
6 | // 控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("Example_NET46")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Example_NET46")]
13 | [assembly: AssemblyCopyright("Copyright © 2024")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // 将 ComVisible 设置为 false 会使此程序集中的类型
18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
19 | //请将此类型的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("7a5b557d-2a2d-4a11-9cae-9aff8097ea7c")]
24 |
25 | // 程序集的版本信息由下列四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 生成号
30 | // 修订号
31 | //
32 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
33 | //通过使用 "*",如下所示:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/examples/Example_NET8/Example_NET8.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 | True
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/examples/Example_NET8/LocalCache.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Caching.Memory;
2 | using SharpRedis;
3 | using System.Diagnostics.CodeAnalysis;
4 |
5 | namespace Example_NET8;
6 |
7 | sealed public class LocalCache : ClientSideCachingStandard
8 | {
9 | private readonly MemoryCache _cache;
10 |
11 | public LocalCache()
12 | {
13 | this._cache = new MemoryCache(new MemoryCacheOptions { });
14 | }
15 |
16 | public override ClientSideCachingMode Mode => ClientSideCachingMode.Broadcasting;
17 |
18 | public override string[]? KeyPatterns => ["localcache_test*"];
19 |
20 | public override string[]? WithoutKeyPatterns => ["nocache*"];
21 |
22 | public override string[]? KeyPrefixes => ["localcache_test:"];
23 |
24 | protected override bool Clear()
25 | {
26 | this._cache.Clear();
27 | return true;
28 | }
29 |
30 | protected override bool Delete(in ClientSideCacheKey key)
31 | {
32 | this._cache.Remove(key);
33 | return true;
34 | }
35 |
36 | protected override bool Set(in ClientSideCacheKey key, object value)
37 | {
38 | this._cache.Set(key, value);
39 | return true;
40 | }
41 |
42 | protected override bool TryGet(in ClientSideCacheKey key, [NotNullWhen(true)] out object? value)
43 | {
44 | return this._cache.TryGetValue(key, out value);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/examples/Example_NET8/Program.cs:
--------------------------------------------------------------------------------
1 | using SharpRedis;
2 | var redis = Redis.UseStandalone(f =>
3 | {
4 | f.Password = "123456";
5 | f.MaxPoolSize = 300;
6 | });
7 |
8 | //redis.PubSub.Subscribe("test", static (a, b) =>
9 | //{
10 | // Console.WriteLine($"Channel: {a}, Data: {b}");
11 | // return Task.CompletedTask;
12 | //});
13 |
14 | //var chang = await redis.String.GetAsync("chang");
15 | //;
16 | await redis.Server.FlushAllAsync();
17 | await redis.String.SetAsync("k1", "k1");
18 | await redis.String.SetAsync("num", "1");
19 | await redis.Hash.HSetAsync("h", "f", "嘿嘿");
20 | await redis.List.RPushAsync("list", ["123", "456"]);
21 |
22 |
23 | for (int i = 0; i < 300; i++)
24 | {
25 | new Thread(async () =>
26 | {
27 | int indexx = i;
28 | int iii = indexx % 2;
29 | while (true)
30 | {
31 | var k1 = await redis.String.GetAsync("k1");
32 | if (k1 != "k1") Console.WriteLine("k1错误");
33 |
34 | await redis.String.IncrAsync("num");
35 |
36 | var hf = await redis.Hash.HGetAsync("h", "f");
37 | if (hf != "嘿嘿") Console.WriteLine("hash错误");
38 |
39 | var list = await redis.List.LIndexAsync("list", iii);
40 | if (iii == 0 && list != "123") Console.WriteLine("list错误");
41 | if (iii == 1 && list != "456") Console.WriteLine("list错误");
42 | }
43 | }).Start();
44 | }
45 | Console.WriteLine("启动成功.NET8");
46 | Console.ReadLine();
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 | ////using Autofac;
73 | ////using Example_NET8;
74 | ////using SharpRedis;
75 | ////using SharpRedis.Autofac;
76 |
77 | ////#region Autofac
78 | ////{
79 | //// var builder = new ContainerBuilder();
80 | //// builder.AddSharpRedisStandalone(option =>
81 | //// {
82 | //// option.Password = "123456";
83 | //// });
84 |
85 | //// builder.AddSharpRedisStandalone(option =>
86 | //// {
87 | //// option.Password = "123456";
88 | //// }, "localCache");
89 |
90 | //// var container = builder.Build();
91 |
92 | //// {
93 | //// var redis = container.Resolve();
94 | //// var ok = await redis.String.SetAsync("key1", "Hello SharpRedis.Autofac");
95 | //// var get = await redis.String.GetAsync("key1");
96 |
97 | //// var redisString = container.Resolve();
98 | //// get = await redisString.GetAsync("key1");
99 | //// }
100 |
101 | //// {
102 | //// var redis = container.ResolveNamed("localCache");
103 | //// var ok = await redis.String.SetAsync("localcache_test:key1", "Hello SharpRedis.Autofac, LocalCache");
104 | //// var get = await redis.String.GetAsync("localcache_test:key1");
105 | //// get = await redis.String.GetAsync("localcache_test:key1");
106 |
107 | //// var redisString = container.ResolveNamed("localCache");
108 | //// get = await redisString.GetAsync("localcache_test:key1");
109 | //// get = await redisString.GetAsync("none:key");
110 | //// }
111 | ////}
112 | ////#endregion
113 |
114 | ////#region Unity
115 |
116 | ////#endregion
117 |
118 | ////Console.ReadLine();
--------------------------------------------------------------------------------
/examples/Example_NET8/ProgramLocalCache.cs:
--------------------------------------------------------------------------------
1 | //using Autofac;
2 | //using Example_NET8;
3 | //using SharpRedis;
4 | //using SharpRedis.Autofac;
5 |
6 | //#region Autofac
7 | //{
8 | // var builder = new ContainerBuilder();
9 | // builder.AddSharpRedisStandalone(option =>
10 | // {
11 | // option.Password = "123456";
12 | // });
13 |
14 | // builder.AddSharpRedisStandalone(option =>
15 | // {
16 | // option.Password = "123456";
17 | // }, "localCache");
18 |
19 | // var container = builder.Build();
20 |
21 | // {
22 | // using var fdsf = new CancellationTokenSource();
23 | // fdsf.CancelAfter(TimeSpan.FromSeconds(5));
24 | // var redis = container.Resolve();
25 | // var ok = await redis.String.SetAsync("key1", "Hello SharpRedis.Autofac", fdsf.Token);
26 | // var get = await redis.String.GetAsync("key1");
27 |
28 | // var redisString = container.Resolve();
29 | // get = await redisString.GetAsync("key1");
30 | // }
31 |
32 | // {
33 | // var redis = container.ResolveNamed("localCache");
34 | // var ok = await redis.String.SetAsync("localcache_test:key1", "Hello SharpRedis.Autofac, LocalCache");
35 | // var get = await redis.String.GetAsync("localcache_test:key1");
36 | // get = await redis.String.GetAsync("localcache_test:key1");
37 |
38 | // var redisString = container.ResolveNamed("localCache");
39 | // get = await redisString.GetAsync("localcache_test:key1");
40 | // get = await redisString.GetAsync("none:key");
41 | // while (true)
42 | // {
43 | // //Console.WriteLine(await redis.String.GetAsync("localcache_test:key1"));
44 | // Console.WriteLine(await redis.String.MGetAsync(["localcache_test:key1","ffds"]));
45 | // Console.ReadLine();
46 | // }
47 | // }
48 | //}
49 | //#endregion
50 |
51 | //#region Unity
52 |
53 | //#endregion
54 |
55 | //Console.ReadLine();
--------------------------------------------------------------------------------
/examples/Example_NET9/Example_NET9.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | enable
7 | enable
8 | True
9 | True
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/examples/Example_NET9/Program.cs:
--------------------------------------------------------------------------------
1 | using SharpRedis;
2 | var redis = Redis.UseStandalone(f =>
3 | {
4 | f.Password = "123456";
5 | f.MaxPoolSize = 300;
6 | });
7 |
8 | await redis.Server.FlushAllAsync();
9 | await redis.String.SetAsync("k1", "k1");
10 | await redis.String.SetAsync("num", "1");
11 | await redis.Hash.HSetAsync("h", "f", "嘿嘿");
12 | await redis.List.RPushAsync("list", ["123", "456"]);
13 |
14 |
15 | for (int i = 0; i < 300; i++)
16 | {
17 | new Thread(async () =>
18 | {
19 | int indexx = i;
20 | int iii = indexx % 2;
21 | while (true)
22 | {
23 | var k1 = await redis.String.GetAsync("k1");
24 | if (k1 != "k1") Console.WriteLine("k1错误");
25 |
26 | await redis.String.IncrAsync("num");
27 |
28 | var hf = await redis.Hash.HGetAsync("h", "f");
29 | if (hf != "嘿嘿") Console.WriteLine("hash错误");
30 |
31 | var list = await redis.List.LIndexAsync("list", iii);
32 | if (iii == 0 && list != "123") Console.WriteLine("list错误");
33 | if (iii == 1 && list != "456") Console.WriteLine("list错误");
34 | }
35 | }).Start();
36 | }
37 | Console.WriteLine("启动成功.NET9");
38 | Console.ReadLine();
--------------------------------------------------------------------------------
/src/SharpRedis.Autofac/SharpRedis.Autofac.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0;netstandard2.1;net5.0;net6.0;net7.0;net8.0
5 | SharpRedis.Autofac
6 | SharpRedis.Autofac
7 | 0.0.7.0
8 | Kwong
9 | A pure asynchronous driver of high performance high throughput Redis driver for C#
10 | SharpRedis.Autofac;SharpRedis;sharpredis;Redis;redis;Redics;RedisClient;RedisHelper;csredis;csharpredis;redisclients;C#Redis;Kwong;kwong;q7164518
11 | false
12 | true
13 | True
14 | Kwong
15 | True
16 | https://github.com/q7164518/SharpRedis
17 | https://github.com/q7164518/SharpRedis
18 | git
19 |
20 |
21 |
22 | enable
23 |
24 |
25 | enable
26 |
27 |
28 | enable
29 |
30 |
31 | enable
32 |
33 |
34 | enable
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/SharpRedis.DependencyInjection/RegistrationExtensions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using System;
3 |
4 | namespace SharpRedis.DependencyInjection
5 | {
6 | ///
7 | /// SharpRedis Microsoft.Extensions.DependencyInjection Extensions
8 | ///
9 | public static class RegistrationExtensions
10 | {
11 | ///
12 | /// Connect singleton Redis and register with Microsoft.Extensions.DependencyInjection ServiceCollection
13 | /// 连接单例Redis, 并注册到Microsoft.Extensions.DependencyInjection ServiceCollection
14 | ///
15 | /// IServiceCollection
16 | /// connection string
17 | /// 连接字符串
18 | ///
19 | /// optionsAction
20 | ///
21 | #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
22 | public static IServiceCollection AddSharpRedisStandalone(this IServiceCollection services, string connectionString, Action? optionsAction = null)
23 | #else
24 | public static IServiceCollection AddSharpRedisStandalone(this IServiceCollection services, string connectionString, Action optionsAction = null)
25 | #endif
26 | {
27 | var redis = Redis.UseStandalone(connectionString, optionsAction);
28 |
29 | return services.AddSingleton(redis)
30 | .RegisterTypes();
31 | }
32 |
33 | ///
34 | /// Connect singleton Redis and register with Microsoft.Extensions.DependencyInjection ServiceCollection
35 | /// 连接单例Redis, 并注册到Microsoft.Extensions.DependencyInjection ServiceCollection
36 | ///
37 | /// IServiceCollection
38 | /// optionsAction
39 | ///
40 | public static IServiceCollection AddSharpRedisStandalone(this IServiceCollection services, Action optionsAction)
41 | {
42 | return services.AddSharpRedisStandalone(string.Empty, optionsAction);
43 | }
44 |
45 | ///
46 | /// Connect singleton Redis and register with Microsoft.Extensions.DependencyInjection ServiceCollection
47 | /// 连接单例Redis, 并注册到Microsoft.Extensions.DependencyInjection ServiceCollection
48 | ///
49 | /// The local cache implements generics
50 | /// 本地缓存实现泛型
51 | ///
52 | /// IServiceCollection
53 | /// connection string
54 | /// 连接字符串
55 | ///
56 | /// optionsAction
57 | ///
58 | #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
59 | public static IServiceCollection AddSharpRedisStandalone(this IServiceCollection services, string connectionString, Action? optionsAction = null)
60 | #else
61 | public static IServiceCollection AddSharpRedisStandalone(this IServiceCollection services, string connectionString, Action optionsAction = null)
62 | #endif
63 | where TCache : ClientSideCachingStandard
64 | {
65 | return services.AddSingleton()
66 | .AddSingleton(c =>
67 | {
68 | var cache = c.GetService();
69 | var redis = Redis.UseStandalone(connectionString, options =>
70 | {
71 | optionsAction?.Invoke(options);
72 | options.SetClientSideCaching(cache);
73 | });
74 | return redis;
75 | })
76 | .RegisterTypes();
77 | }
78 |
79 | ///
80 | /// Connect singleton Redis and register with Microsoft.Extensions.DependencyInjection ServiceCollection
81 | /// 连接单例Redis, 并注册到Microsoft.Extensions.DependencyInjection ServiceCollection
82 | ///
83 | /// The local cache implements generics
84 | /// 本地缓存实现泛型
85 | ///
86 | /// IServiceCollection
87 | /// optionsAction
88 | ///
89 | public static IServiceCollection AddSharpRedisStandalone(this IServiceCollection services, Action optionsAction)
90 | where TCache : ClientSideCachingStandard
91 | {
92 | return services.AddSharpRedisStandalone(string.Empty, optionsAction);
93 | }
94 |
95 | private static IServiceCollection RegisterTypes(this IServiceCollection services)
96 | {
97 | return services.AddSingleton(c => c.GetService().String)
98 | .AddSingleton(c => c.GetService().Hash)
99 | .AddSingleton(c => c.GetService().List)
100 | .AddSingleton(c => c.GetService().Set)
101 | .AddSingleton(c => c.GetService().SortedSet)
102 | .AddSingleton(c => c.GetService().Bitmap)
103 | .AddSingleton(c => c.GetService().HyperLogLog)
104 | .AddSingleton(c => c.GetService().Geospatial)
105 | .AddSingleton(c => c.GetService().Script)
106 | .AddSingleton(c => c.GetService().Connection)
107 | .AddSingleton(c => c.GetService().Key)
108 | .AddSingleton(c => c.GetService().Server)
109 | .AddSingleton(c => c.GetService().PubSub)
110 | .AddSingleton(c => c.GetService().Stream);
111 | }
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/src/SharpRedis.DependencyInjection/SharpRedis.DependencyInjection.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0;netstandard2.1;net5.0;net6.0;net7.0;net8.0
5 | SharpRedis.DependencyInjection
6 | SharpRedis.DependencyInjection
7 | 0.0.7.0
8 | Kwong
9 | A pure asynchronous driver of high performance high throughput Redis driver for C#
10 | SharpRedis.DependencyInjection;SharpRedis;sharpredis;Redis;redis;Redics;RedisClient;RedisHelper;csredis;csharpredis;redisclients;C#Redis;Kwong;kwong;q7164518
11 | false
12 | true
13 | True
14 | Kwong
15 | True
16 | https://github.com/q7164518/SharpRedis
17 | https://github.com/q7164518/SharpRedis
18 | git
19 |
20 |
21 |
22 | enable
23 |
24 |
25 | enable
26 |
27 |
28 | enable
29 |
30 |
31 | enable
32 |
33 |
34 | enable
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/SharpRedis.DependencyInjectionKeyedService/SharpRedis.DependencyInjectionKeyedService.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0;netstandard2.1;net5.0;net6.0;net7.0;net8.0
5 | SharpRedis.DependencyInjectionKeyedService
6 | SharpRedis.DependencyInjectionKeyedService
7 | 0.0.7.0
8 | Kwong
9 | A pure asynchronous driver of high performance high throughput Redis driver for C#
10 | SharpRedis.DependencyInjectionKeyedService;SharpRedis;sharpredis;Redis;redis;Redics;RedisClient;RedisHelper;csredis;csharpredis;redisclients;C#Redis;Kwong;kwong;q7164518
11 | false
12 | true
13 | True
14 | Kwong
15 | True
16 | https://github.com/q7164518/SharpRedis
17 | https://github.com/q7164518/SharpRedis
18 | git
19 |
20 |
21 |
22 | enable
23 |
24 |
25 | enable
26 |
27 |
28 | enable
29 |
30 |
31 | enable
32 |
33 |
34 | enable
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/SharpRedis.Unity/SharpRedis.Unity.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0;netstandard2.1;net5.0;net6.0;net7.0;net8.0
5 | SharpRedis.Unity
6 | SharpRedis.Unity
7 | 0.0.7.0
8 | Kwong
9 | A pure asynchronous driver of high performance high throughput Redis driver for C#
10 | SharpRedis.Unity;SharpRedis;sharpredis;Redis;redis;Redics;RedisClient;RedisHelper;csredis;csharpredis;redisclients;C#Redis;Kwong;kwong;q7164518
11 | false
12 | true
13 | True
14 | Kwong
15 | True
16 | https://github.com/q7164518/SharpRedis
17 | https://github.com/q7164518/SharpRedis
18 | git
19 |
20 |
21 |
22 | enable
23 |
24 |
25 | enable
26 |
27 |
28 | enable
29 |
30 |
31 | enable
32 |
33 |
34 | enable
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/SharpRedis/Commands/BitmapCommands.cs:
--------------------------------------------------------------------------------
1 | using SharpRedis.Models;
2 |
3 | namespace SharpRedis.Commands
4 | {
5 | internal static class BitmapCommands
6 | {
7 | static internal CommandPacket SetBit(string key, uint offset, bool value)
8 | {
9 | return new CommandPacket("SETBIT", CommandMode.Write)
10 | .WriteKey(key)
11 | .WriteArg(offset)
12 | .WriteValue(value, "1")
13 | .WriteValue(!value, "0");
14 | }
15 |
16 | internal static CommandPacket GetBit(string key, uint offset)
17 | {
18 | return new CommandPacket("GETBIT", CommandMode.Read | CommandMode.WithClientSideCache)
19 | .WriteKey(key)
20 | .WriteArg(offset);
21 | }
22 |
23 | internal static CommandPacket BitPos(string key, bool bit, long? start = null, long? end = null, ByteBit bb = ByteBit.None)
24 | {
25 | if (!start.HasValue && end.HasValue) throw new RedisException("Setting only the end location is not allowed");
26 | return new CommandPacket("BITPOS", CommandMode.Read | CommandMode.WithClientSideCache)
27 | .WriteKey(key)
28 | .WriteValue(bit, "1")
29 | .WriteValue(!bit, "0")
30 | .WriteArg(start ?? 0)
31 | .WriteArg(end ?? -1)
32 | .WriteArg(bb == ByteBit.Bit, "BIT")
33 | .WriteArg(bb == ByteBit.Byte, "BYTE");
34 | }
35 |
36 | internal static CommandPacket BitOp(BitOperation bitOperation, string destkey, params string[] keys)
37 | {
38 | if (keys is null || keys.Length == 0) throw new RedisException("Ensure that at least one key participates in the calculation");
39 | if (bitOperation != BitOperation.Not && keys.Length <= 1) throw new RedisException("A non-NOT bit operation requires at least two keys");
40 | return new CommandPacket("BITOP", CommandMode.Write)
41 | .WriteArg(bitOperation is BitOperation.And, "AND")
42 | .WriteArg(bitOperation is BitOperation.Or, "OR")
43 | .WriteArg(bitOperation is BitOperation.Xor, "XOR")
44 | .WriteArg(bitOperation is BitOperation.Not, "NOT")
45 | .WriteKey(destkey)
46 | .WriteKeys(keys);
47 | }
48 |
49 | internal static CommandPacket BitCount(string key, long? start = null, long? end = null, ByteBit bb = ByteBit.None)
50 | {
51 | if (!start.HasValue && end.HasValue) throw new RedisException("Setting only the end location is not allowed");
52 | return new CommandPacket("BITCOUNT", CommandMode.Read | CommandMode.WithClientSideCache)
53 | .WriteKey(key)
54 | .WriteArg(start ?? 0)
55 | .WriteArg(end ?? -1)
56 | .WriteArg(bb == ByteBit.Bit, "BIT")
57 | .WriteArg(bb == ByteBit.Byte, "BYTE");
58 | }
59 |
60 | internal static CommandPacket BitField(string key, params IBitFieldArg[] args)
61 | {
62 | if (args is null || args.Length == 0) throw new RedisException("The BITFIELD command parameter cannot be empty");
63 | var command = new CommandPacket("BITFIELD", CommandMode.Write).WriteKey(key);
64 | for (uint i = 0; i < args.Length; i++)
65 | {
66 | if (args[i] is null) throw new RedisException("The BITFIELD command is null");
67 | command.WriteValues(args[i].Convert());
68 | }
69 | return command;
70 | }
71 |
72 | internal static CommandPacket BitField_Ro(string key, params IBitFieldArg[] args)
73 | {
74 | if (args is null || args.Length == 0) throw new RedisException("The BITFIELD command parameter cannot be empty");
75 | var command = new CommandPacket("BITFIELD_RO", CommandMode.Read | CommandMode.WithClientSideCache).WriteKey(key);
76 | for (uint i = 0; i < args.Length; i++)
77 | {
78 | if (args[i] is null) throw new RedisException("The BITFIELD command is null");
79 | if (args[i].ArgType != BitFieldArgType.Get) throw new RedisException("The BITFIELD_RO command supports only the GET arg");
80 | command.WriteValues(args[i].Convert());
81 | }
82 | return command;
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/SharpRedis/Commands/ConnectionCommands.cs:
--------------------------------------------------------------------------------
1 | using SharpRedis.Models;
2 |
3 | namespace SharpRedis.Commands
4 | {
5 | internal static class ConnectionCommands
6 | {
7 | #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
8 | internal static CommandPacket Auth(string? user, string? password)
9 | #else
10 | internal static CommandPacket Auth(string user, string password)
11 | #endif
12 | {
13 | return new CommandPacket("AUTH", CommandMode.Connection)
14 | #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
15 | .WriteArg(!string.IsNullOrEmpty(user), user!)
16 | .WriteArg(!string.IsNullOrEmpty(password), password!);
17 | #else
18 | .WriteArg(!string.IsNullOrEmpty(user), user)
19 | .WriteArg(!string.IsNullOrEmpty(password), password);
20 | #endif
21 | }
22 |
23 | #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
24 | internal static CommandPacket Hello(RespVersion protover, string? user, string? password, string? clientname)
25 | #else
26 | internal static CommandPacket Hello(RespVersion protover, string user, string password, string clientname)
27 | #endif
28 | {
29 | var command = new CommandPacket("HELLO", CommandMode.Connection)
30 | .WriteArg((int)protover)
31 | .WriteArg(!string.IsNullOrEmpty(user) || !string.IsNullOrEmpty(password), "AUTH")
32 | #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
33 | .WriteValue(!string.IsNullOrEmpty(user), user!)
34 | #else
35 | .WriteValue(!string.IsNullOrEmpty(user), user)
36 | #endif
37 | .WriteValue(string.IsNullOrEmpty(user), "default")
38 | #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
39 | .WriteValue(!string.IsNullOrEmpty(password), password!);
40 | #else
41 | .WriteValue(!string.IsNullOrEmpty(password), password);
42 | #endif
43 | if (!string.IsNullOrEmpty(clientname))
44 | {
45 | command.WriteArg("SETNAME")
46 | .WriteValue(clientname);
47 | }
48 | return command;
49 | }
50 |
51 | internal static CommandPacket Echo(TValue message) where TValue : class
52 | {
53 | return new CommandPacket("ECHO", CommandMode.Connection)
54 | .WriteValue(message);
55 | }
56 |
57 | internal static CommandPacket Select(uint index)
58 | {
59 | return new CommandPacket("SELECT", CommandMode.Connection)
60 | .WriteArg(index);
61 | }
62 |
63 | internal static CommandPacket ClientSetName(string clientname)
64 | {
65 | return new CommandPacket("CLIENT", CommandMode.Connection)
66 | .WriteArg("SETNAME")
67 | .WriteValue(clientname);
68 | }
69 |
70 | internal static CommandPacket ClientGetName()
71 | => new CommandPacket("CLIENT", CommandMode.Connection).WriteArg("GETNAME");
72 |
73 | #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
74 | internal static CommandPacket Ping(string? message)
75 | #else
76 | internal static CommandPacket Ping(string message)
77 | #endif
78 | {
79 | return new CommandPacket("PING", CommandMode.Connection | CommandMode.WithoutActiveTime)
80 | #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
81 | .WriteValue(!string.IsNullOrEmpty(message), message!);
82 | #else
83 | .WriteValue(!string.IsNullOrEmpty(message), message);
84 | #endif
85 | }
86 |
87 | internal static CommandPacket ClientId() => new CommandPacket("CLIENT", CommandMode.Connection).WriteArg("ID");
88 |
89 | #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
90 | internal static CommandPacket ClientTracking(bool onOff, long clientId, string[]? prefixes = null, bool bcast = false, bool optin = false, bool optout = false, bool noloop = false)
91 | #else
92 | internal static CommandPacket ClientTracking(bool onOff, long clientId, string[] prefixes = null, bool bcast = false, bool optin = false, bool optout = false, bool noloop = false)
93 | #endif
94 | {
95 | var command = new CommandPacket("CLIENT", CommandMode.Connection)
96 | .WriteArg("TRACKING")
97 | .WriteArg(onOff, "ON")
98 | .WriteArg(!onOff, "OFF")
99 | .WriteArg("REDIRECT", clientId);
100 |
101 | if (prefixes?.Length > 0)
102 | {
103 | for (uint i = 0; i < prefixes.Length; i++)
104 | {
105 | command.WriteArg("PREFIX", prefixes[i]);
106 | }
107 | }
108 | command.WriteArg(bcast, "BCAST")
109 | .WriteArg(optin, "OPTIN")
110 | .WriteArg(optout, "OPTOUT")
111 | .WriteArg(noloop, "NOLOOP");
112 | return command;
113 | }
114 |
115 | internal static CommandPacket ClientCaching(bool yn)
116 | {
117 | return new CommandPacket("CLIENT", CommandMode.Connection)
118 | .WriteArg("CACHING")
119 | .WriteValue(yn, "YES")
120 | .WriteValue(!yn, "NO");
121 | }
122 |
123 | internal static CommandPacket ClientGetRedir()
124 | => new CommandPacket("CLIENT", CommandMode.Connection).WriteArg("GETREDIR");
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/src/SharpRedis/Commands/HyperLogLogCommands.cs:
--------------------------------------------------------------------------------
1 | using SharpRedis.Models;
2 |
3 | namespace SharpRedis.Commands
4 | {
5 | internal static class HyperLogLogCommands
6 | {
7 | internal static CommandPacket PFAdd(string key, params TElement[] elements) where TElement : class
8 | {
9 | return new CommandPacket("PFADD", CommandMode.Write)
10 | .WriteKey(key)
11 | .WriteValues(elements);
12 | }
13 |
14 | #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
15 | internal static CommandPacket PFCount(string key, string[]? keys)
16 | #else
17 | internal static CommandPacket PFCount(string key, string[] keys)
18 | #endif
19 | {
20 | return new CommandPacket("PFCOUNT", CommandMode.Read | CommandMode.WithClientSideCache)
21 | .WriteKey(key)
22 | #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
23 | .WriteKeys(keys?.Length > 0, keys!);
24 | #else
25 | .WriteKeys(keys?.Length > 0, keys);
26 | #endif
27 | }
28 |
29 | #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
30 | internal static CommandPacket PFMerge(string destkey, string? sourceKey, string[]? sourcekeys)
31 | #else
32 | internal static CommandPacket PFMerge(string destkey, string sourceKey, string[] sourcekeys)
33 | #endif
34 | {
35 | return new CommandPacket("PFMERGE", CommandMode.Write)
36 | .WriteKey(destkey)
37 | #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
38 | .WriteKey(!string.IsNullOrEmpty(sourceKey), sourceKey!)
39 | .WriteKeys(sourcekeys?.Length > 0, sourcekeys!);
40 | #else
41 | .WriteKey(!string.IsNullOrEmpty(sourceKey), sourceKey)
42 | .WriteKeys(sourcekeys?.Length > 0, sourcekeys);
43 | #endif
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/SharpRedis/Commands/PubSubCommands.cs:
--------------------------------------------------------------------------------
1 | #if NET5_0_OR_GREATER
2 | #pragma warning disable IDE0090
3 | #endif
4 | using SharpRedis.Models;
5 |
6 | namespace SharpRedis.Commands
7 | {
8 | internal static class PubSubCommands
9 | {
10 | internal static CommandPacket Publish(string channel, TMessage message) where TMessage : class
11 | {
12 | return new CommandPacket("PUBLISH", CommandMode.Pub)
13 | .WriteValue(channel)
14 | .WriteValue(message);
15 | }
16 |
17 | internal static CommandPacket SPublish(string shardChannel, TMessage message) where TMessage : class
18 | {
19 | return new CommandPacket("SPUBLISH", CommandMode.Pub)
20 | .WriteValue(shardChannel)
21 | .WriteValue(message);
22 | }
23 |
24 | internal static CommandPacket Subscribe() => new CommandPacket("SUBSCRIBE", CommandMode.Sub | CommandMode.WithoutResult);
25 |
26 | internal static CommandPacket SSubscribe() => new CommandPacket("SSUBSCRIBE", CommandMode.Sub | CommandMode.WithoutResult);
27 |
28 | internal static CommandPacket PSubscribe() => new CommandPacket("PSUBSCRIBE", CommandMode.Sub | CommandMode.WithoutResult);
29 |
30 | internal static CommandPacket UnSubscribe() => new CommandPacket("UNSUBSCRIBE", CommandMode.UnSub | CommandMode.WithoutResult);
31 |
32 | internal static CommandPacket PUnSubscribe() => new CommandPacket("PUNSUBSCRIBE", CommandMode.UnSub | CommandMode.WithoutResult);
33 |
34 | internal static CommandPacket SUnSubscribe() => new CommandPacket("SUNSUBSCRIBE", CommandMode.UnSub | CommandMode.WithoutResult);
35 |
36 | #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
37 | internal static CommandPacket PubSubChannels(string? pattern)
38 | #else
39 | internal static CommandPacket PubSubChannels(string pattern)
40 | #endif
41 | {
42 | return new CommandPacket("PUBSUB", CommandMode.Pub)
43 | .WriteArg("CHANNELS")
44 | #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
45 | .WriteValue(!string.IsNullOrEmpty(pattern), pattern!);
46 | #else
47 | .WriteValue(!string.IsNullOrEmpty(pattern), pattern);
48 | #endif
49 | }
50 |
51 | internal static CommandPacket PubSubNumPAt() => new CommandPacket("PUBSUB", CommandMode.Pub).WriteArg("NUMPAT");
52 |
53 | internal static CommandPacket PubSubNumSub(string[] channels)
54 | {
55 | return new CommandPacket("PUBSUB", CommandMode.Pub)
56 | .WriteArg("NUMSUB")
57 | .WriteValues(channels);
58 | }
59 |
60 | #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
61 | internal static CommandPacket PubSubShardChannels(string? pattern)
62 | #else
63 | internal static CommandPacket PubSubShardChannels(string pattern)
64 | #endif
65 | {
66 | return new CommandPacket("PUBSUB", CommandMode.Pub)
67 | .WriteArg("SHARDCHANNELS")
68 | #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
69 | .WriteValue(!string.IsNullOrEmpty(pattern), pattern!);
70 | #else
71 | .WriteValue(!string.IsNullOrEmpty(pattern), pattern);
72 | #endif
73 | }
74 |
75 | internal static CommandPacket PubSubShardNumSub(string[] shardchannels)
76 | {
77 | return new CommandPacket("PUBSUB", CommandMode.Pub)
78 | .WriteArg("SHARDNUMSUB")
79 | .WriteValues(shardchannels);
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/SharpRedis/Commands/ServerCommands.cs:
--------------------------------------------------------------------------------
1 | #if NET5_0_OR_GREATER
2 | #pragma warning disable IDE0090
3 | #endif
4 | using SharpRedis.Models;
5 |
6 | namespace SharpRedis.Commands
7 | {
8 | internal static class ServerCommands
9 | {
10 | internal static CommandPacket FlushAll(FlushingMode mode)
11 | {
12 | return new CommandPacket("FLUSHALL", CommandMode.Server | CommandMode.Write)
13 | .WriteArg(mode == FlushingMode.Sync, "SYNC")
14 | .WriteArg(mode == FlushingMode.Async, "ASYNC");
15 | }
16 |
17 | internal static CommandPacket FlushDb(FlushingMode mode)
18 | {
19 | return new CommandPacket("FLUSHDB", CommandMode.Server | CommandMode.Write)
20 | .WriteArg(mode == FlushingMode.Sync, "SYNC")
21 | .WriteArg(mode == FlushingMode.Async, "ASYNC");
22 | }
23 |
24 | internal static CommandPacket Save()
25 | => new CommandPacket("SAVE", CommandMode.Server);
26 |
27 | internal static CommandPacket BgSave(bool schedule)
28 | => new CommandPacket("BGSAVE", CommandMode.Server).WriteArg(schedule, "SCHEDULE");
29 |
30 | internal static CommandPacket Info(params string[] sections)
31 | {
32 | return new CommandPacket("INFO", CommandMode.Server)
33 | .WriteArgs(sections);
34 | }
35 |
36 | internal static CommandPacket DbSize()
37 | {
38 | return new CommandPacket("DBSIZE", CommandMode.Server | CommandMode.Read);
39 | }
40 |
41 | internal static CommandPacket LastSave()
42 | {
43 | return new CommandPacket("LASTSAVE", CommandMode.Server);
44 | }
45 |
46 | internal static CommandPacket BgRewriteAof()
47 | {
48 | return new CommandPacket("BGREWRITEAOF", CommandMode.Server);
49 | }
50 |
51 | internal static CommandPacket CommandCount()
52 | {
53 | return new CommandPacket("COMMAND", CommandMode.Server).WriteArg("COUNT");
54 | }
55 |
56 | internal static CommandPacket CommandGetKeys(params string[] command)
57 | {
58 | return new CommandPacket("COMMAND", CommandMode.Server)
59 | .WriteArg("GETKEYS")
60 | .WriteArgs(command);
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/SharpRedis/Commands/SetCommands.cs:
--------------------------------------------------------------------------------
1 | using SharpRedis.Models;
2 |
3 | namespace SharpRedis.Commands
4 | {
5 | internal static class SetCommands
6 | {
7 | internal static CommandPacket SAdd(string key, params TMember[] members) where TMember : class
8 | {
9 | return new CommandPacket("SADD", CommandMode.Write)
10 | .WriteKey(key)
11 | .WriteValues(members);
12 | }
13 |
14 | internal static CommandPacket SCard(string key)
15 | {
16 | return new CommandPacket("SCARD", CommandMode.Read | CommandMode.WithClientSideCache)
17 | .WriteKey(key);
18 | }
19 |
20 | internal static CommandPacket SDiff(string[] keys)
21 | {
22 | return new CommandPacket("SDIFF", CommandMode.Read | CommandMode.WithClientSideCache)
23 | .WriteKeys(keys);
24 | }
25 |
26 | internal static CommandPacket SDiffStore(string destinationKey, string[] keys)
27 | {
28 | return new CommandPacket("SDIFFSTORE", CommandMode.Write)
29 | .WriteKey(destinationKey)
30 | .WriteKeys(keys);
31 | }
32 |
33 | internal static CommandPacket SInter(string[] keys)
34 | {
35 | return new CommandPacket("SINTER", CommandMode.Read | CommandMode.WithClientSideCache)
36 | .WriteKeys(keys);
37 | }
38 |
39 | internal static CommandPacket SInterCard(string[] keys, ulong limit)
40 | {
41 | return new CommandPacket("SINTERCARD", CommandMode.Read | CommandMode.WithClientSideCache)
42 | .WriteArg(keys.Length)
43 | .WriteKeys(keys)
44 | .WriteArg(limit > 0, "LIMIT", limit);
45 | }
46 |
47 | internal static CommandPacket SInterStore(string destinationKey, string[] keys)
48 | {
49 | return new CommandPacket("SINTERSTORE", CommandMode.Write)
50 | .WriteKey(destinationKey)
51 | .WriteKeys(keys);
52 | }
53 |
54 | internal static CommandPacket SIsMember(string key, TMember member) where TMember : class
55 | {
56 | return new CommandPacket("SISMEMBER", CommandMode.Read | CommandMode.WithClientSideCache)
57 | .WriteKey(key)
58 | .WriteValue(member);
59 | }
60 |
61 | internal static CommandPacket SMembers(string key)
62 | {
63 | return new CommandPacket("SMEMBERS", CommandMode.Read | CommandMode.WithClientSideCache)
64 | .WriteKey(key);
65 | }
66 |
67 | internal static CommandPacket SMIsMember(string key, params TMember[] members) where TMember : class
68 | {
69 | return new CommandPacket("SMISMEMBER", CommandMode.Read | CommandMode.WithClientSideCache)
70 | .WriteKey(key)
71 | .WriteValues(members);
72 | }
73 |
74 | internal static CommandPacket SMove(string source, string destination, TMember member) where TMember : class
75 | {
76 | return new CommandPacket("SMOVE", CommandMode.Write)
77 | .WriteKey(source)
78 | .WriteKey(destination)
79 | .WriteValue(member);
80 | }
81 |
82 | internal static CommandPacket SPop(string key, ulong count)
83 | {
84 | if (count <= 0) throw new RedisException("Count cannot be 0");
85 | return new CommandPacket("SPOP", CommandMode.Write)
86 | .WriteKey(key)
87 | .WriteArg(count > 1, count);
88 | }
89 |
90 | internal static CommandPacket SRandMember(string key, long count)
91 | {
92 | return new CommandPacket("SRANDMEMBER", CommandMode.Read)
93 | .WriteKey(key)
94 | .WriteArg(count != 0, count);
95 | }
96 |
97 | internal static CommandPacket SRem(string key, params TMember[] members) where TMember : class
98 | {
99 | return new CommandPacket("SREM", CommandMode.Write)
100 | .WriteKey(key)
101 | .WriteValues(members);
102 | }
103 |
104 | internal static CommandPacket SUnion(string[] keys)
105 | {
106 | return new CommandPacket("SUNION", CommandMode.Read | CommandMode.WithClientSideCache)
107 | .WriteKeys(keys);
108 | }
109 |
110 | internal static CommandPacket SUnionStore(string destination, string[] keys)
111 | {
112 | return new CommandPacket("SUNIONSTORE", CommandMode.Write)
113 | .WriteKey(destination)
114 | .WriteKeys(keys);
115 | }
116 |
117 | #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
118 | internal static CommandPacket SScan(string key, long cursor, string? pattern, ulong? count)
119 | #else
120 | internal static CommandPacket SScan(string key, long cursor, string pattern, ulong? count)
121 | #endif
122 | {
123 | return new CommandPacket("SSCAN", CommandMode.Read)
124 | .WriteKey(key)
125 | .WriteArg(cursor)
126 | #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
127 | .WriteArg(!string.IsNullOrEmpty(pattern), "MATCH", pattern!)
128 | #else
129 | .WriteArg(!string.IsNullOrEmpty(pattern), "MATCH", pattern)
130 | #endif
131 | .WriteArg(count.HasValue, "COUNT", count ?? 0);
132 | }
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/src/SharpRedis/Commands/TransactionCommands.cs:
--------------------------------------------------------------------------------
1 | using SharpRedis.Models;
2 |
3 | namespace SharpRedis.Commands
4 | {
5 | internal static class TransactionCommands
6 | {
7 | static internal CommandPacket Discard()
8 | {
9 | return new CommandPacket("DISCARD", CommandMode.Transaction);
10 | }
11 |
12 | static internal CommandPacket Exec()
13 | {
14 | return new CommandPacket("EXEC", CommandMode.Transaction);
15 | }
16 |
17 | static internal CommandPacket Multi()
18 | {
19 | return new CommandPacket("MULTI", CommandMode.Transaction);
20 | }
21 |
22 | static internal CommandPacket Watch(params string[] keys)
23 | {
24 | return new CommandPacket("WATCH", CommandMode.Transaction)
25 | #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
26 | .WriteKeys(keys?.Length > 0, keys!);
27 | #else
28 | .WriteKeys(keys?.Length > 0, keys);
29 | #endif
30 | }
31 |
32 | static internal CommandPacket Unwatch()
33 | {
34 | return new CommandPacket("UNWATCH", CommandMode.Transaction);
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/SharpRedis/Exceptions/RedisConnectionException.cs:
--------------------------------------------------------------------------------
1 | #if NET8_0
2 | #pragma warning disable IDE0290
3 | #endif
4 | using System;
5 |
6 | namespace SharpRedis
7 | {
8 | public sealed class RedisConnectionException : Exception
9 | {
10 | public RedisConnectionException(string msg)
11 | : base(msg)
12 | {
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/SharpRedis/Exceptions/RedisException.cs:
--------------------------------------------------------------------------------
1 | #if NET8_0
2 | #pragma warning disable IDE0290
3 | #endif
4 | using System;
5 |
6 | namespace SharpRedis
7 | {
8 | public sealed class RedisException : Exception
9 | {
10 | public RedisException(string msg)
11 | : base(msg)
12 | {
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/SharpRedis/Exceptions/RedisInitializationException.cs:
--------------------------------------------------------------------------------
1 | #if NET8_0
2 | #pragma warning disable IDE0290
3 | #endif
4 | using System;
5 |
6 | namespace SharpRedis
7 | {
8 | public sealed class RedisInitializationException : Exception
9 | {
10 | public RedisInitializationException(string msg)
11 | : base(msg)
12 | {
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/SharpRedis/Extensions/ConnectionExtensions.cs:
--------------------------------------------------------------------------------
1 | #if NET8_0_OR_GREATER
2 | #pragma warning disable IDE0300
3 | #endif
4 | using SharpRedis.Commands;
5 | using SharpRedis.Network.Standard;
6 | using System;
7 |
8 | namespace SharpRedis.Extensions
9 | {
10 | internal static class ConnectionExtensions
11 | {
12 | private static readonly string[] _separator = new string[] { "\r\n" };
13 |
14 | #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
15 | internal static bool Auth(IConnection connection, string? user, string? password)
16 | #else
17 | internal static bool Auth(IConnection connection, string user, string password)
18 | #endif
19 | {
20 | if (string.IsNullOrEmpty(password)) return true;
21 | var result = connection.ExecuteCommand(ConnectionCommands.Auth(user, password), default);
22 | if (result is Exception ex) throw ex;
23 | if (result is byte[] bytes)
24 | {
25 | if ((bytes[0] == 79 || bytes[0] == 111)
26 | && (bytes[1] == 75 || bytes[1] == 107)) return true;
27 | }
28 | return false;
29 | }
30 |
31 | internal static string GetRedisVersion(IConnection connection)
32 | {
33 | var infoResult = connection.ExecuteCommand(ServerCommands.Info("server", "|", "grep", "redis_version"), default);
34 | if (infoResult is string serverInfo)
35 | {
36 | if (string.IsNullOrEmpty(serverInfo)) return string.Empty;
37 | var infoArray = serverInfo.Split(ConnectionExtensions._separator, StringSplitOptions.None);
38 | for (uint i = 0; i < infoArray.Length; i++)
39 | {
40 | if (infoArray[i].StartsWith("redis_version:", StringComparison.OrdinalIgnoreCase))
41 | {
42 | #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
43 | return infoArray[i][14..];
44 | #else
45 | return infoArray[i].Substring(14);
46 | #endif
47 | }
48 | }
49 | }
50 | return string.Empty;
51 | }
52 |
53 | #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
54 | internal static bool Hello(IConnection connection, RespVersion respVersion, string? user, string? password)
55 | #else
56 | internal static bool Hello(IConnection connection, RespVersion respVersion, string user, string password)
57 | #endif
58 | {
59 | var helloResult = connection.ExecuteCommand(ConnectionCommands.Hello(respVersion, user, password, connection.ConnectionName), default);
60 | if (helloResult is Exception ex) throw ex;
61 | if (helloResult != null && helloResult != DBNull.Value)
62 | {
63 | return true;
64 | }
65 | return false;
66 | }
67 |
68 | internal static bool SetClientName(IConnection connection)
69 | {
70 | var setNameResult = connection.ExecuteCommand(ConnectionCommands.ClientSetName(connection.ConnectionName), default);
71 | if (setNameResult is byte[] bytes)
72 | {
73 | if ((bytes[0] == 79 || bytes[0] == 111)
74 | && (bytes[1] == 75 || bytes[1] == 107)) return true;
75 | }
76 | return false;
77 | }
78 |
79 | internal static long ClientId(IConnection connection)
80 | {
81 | return ConvertExtensions.To(connection.ExecuteCommand(ConnectionCommands.ClientId(), default), ResultType.Int64, connection.Encoding);
82 | }
83 |
84 | ///
85 | /// Idle ping
86 | ///
87 | ///
88 | ///
89 | internal static bool Ping(IConnection connection)
90 | {
91 | try
92 | {
93 | var pingMsg = $"SharpRedis_{Guid.NewGuid():N}_Ping";
94 | var pingResult = connection.ExecuteCommand(ConnectionCommands.Ping(pingMsg), default);
95 | var pintResultString = ConvertExtensions.To(pingResult, ResultType.String, connection.Encoding);
96 | if (pingMsg.Equals(pintResultString, StringComparison.OrdinalIgnoreCase))
97 | {
98 | return true;
99 | }
100 | return false;
101 | }
102 | catch (Exception ex)
103 | {
104 | SharpConsole.WriteError($"Idle Exception, message: {ex.Message}");
105 | return false;
106 | }
107 | }
108 |
109 | internal static bool Select(IConnection connection, ushort index)
110 | {
111 | var selectResult = connection.ExecuteCommand(ConnectionCommands.Select(index), default);
112 | if (selectResult is byte[] bytes)
113 | {
114 | if ((bytes[0] == 79 || bytes[0] == 111)
115 | && (bytes[1] == 75 || bytes[1] == 107)) return true;
116 | }
117 | return false;
118 | }
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/src/SharpRedis/Extensions/SharpConsole.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpRedis.Extensions
4 | {
5 | internal static class SharpConsole
6 | {
7 | private static readonly object _lock = new object();
8 |
9 | internal static void WriteError(string errorMessage)
10 | {
11 | lock (SharpConsole._lock)
12 | {
13 | Console.BackgroundColor = ConsoleColor.Red;
14 | Console.ForegroundColor = ConsoleColor.White;
15 | Console.Write("Error: ");
16 | Console.BackgroundColor = ConsoleColor.Black;
17 | Console.ForegroundColor = ConsoleColor.Red;
18 | Console.WriteLine($" Time: {DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}. {errorMessage}");
19 | Console.ForegroundColor = ConsoleColor.Gray;
20 | }
21 | }
22 |
23 | internal static void WriteInfo(string message)
24 | {
25 | lock (SharpConsole._lock)
26 | {
27 | Console.BackgroundColor = ConsoleColor.Green;
28 | Console.ForegroundColor = ConsoleColor.White;
29 | Console.Write("Info: ");
30 | Console.BackgroundColor = ConsoleColor.Black;
31 | Console.ForegroundColor = ConsoleColor.Green;
32 | Console.WriteLine($" Time: {DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}. {message}");
33 | Console.ForegroundColor = ConsoleColor.Gray;
34 | }
35 | }
36 |
37 | internal static void WriteWarning(string warningMessage)
38 | {
39 | lock (SharpConsole._lock)
40 | {
41 | Console.BackgroundColor = ConsoleColor.Yellow;
42 | Console.ForegroundColor = ConsoleColor.Black;
43 | Console.Write("Warning: ");
44 | Console.BackgroundColor = ConsoleColor.Black;
45 | Console.ForegroundColor = ConsoleColor.Yellow;
46 | Console.WriteLine($" Time: {DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}. {warningMessage}");
47 | Console.ForegroundColor = ConsoleColor.Gray;
48 | }
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/SharpRedis/Extensions/StringExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpRedis.Extensions
4 | {
5 | unsafe public static class StringExtensions
6 | {
7 | public static bool Matches(string input, params string[] patterns)
8 | {
9 | var _input = input?.Trim();
10 | if (patterns is null || patterns.Length is 0 || string.IsNullOrEmpty(_input)) return false;
11 | fixed (char* pInput = _input)
12 | for (uint i = 0; i < patterns.Length; i++)
13 | fixed (char* pPattern = patterns[i])
14 | if (StringExtensions.MatchesRecursive(pInput, pPattern)) return true;
15 | return false;
16 | }
17 |
18 | private static bool MatchesRecursive(char* input, char* pattern)
19 | {
20 | if (*input == '\0' && *pattern == '\0') return true;
21 | if (*pattern == '\0') return false;
22 |
23 | if (*input == '\0')
24 | {
25 | while (*pattern == '*') pattern++;
26 | return *pattern == '\0';
27 | }
28 |
29 | if (*pattern == '*')
30 | {
31 | return StringExtensions.MatchesRecursive(input + 1, pattern) || StringExtensions.MatchesRecursive(input, pattern + 1);
32 | }
33 | else if (*pattern == '?')
34 | {
35 | return StringExtensions.MatchesRecursive(input + 1, pattern + 1);
36 | }
37 | else if (*pattern == '[')
38 | {
39 | char* closingBracket = pattern;
40 | while (*closingBracket != ']' && *closingBracket != '\0') closingBracket++;
41 | if (*closingBracket == '\0') throw new ArgumentException("Invalid pattern: missing ']'");
42 |
43 | char* temp = pattern + 1;
44 | while (temp < closingBracket)
45 | {
46 | if (*temp == *input) return StringExtensions.MatchesRecursive(input + 1, closingBracket + 1);
47 | temp++;
48 | }
49 | return false;
50 | }
51 | else
52 | {
53 | return *input == *pattern && StringExtensions.MatchesRecursive(input + 1, pattern + 1);
54 | }
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/SharpRedis/Extensions/net30/Action.cs:
--------------------------------------------------------------------------------
1 | #if NET30
2 | #pragma warning disable IDE0130
3 | namespace System
4 | {
5 | public delegate void Action(T1 arg1, T2 arg2);
6 | }
7 | #endif
--------------------------------------------------------------------------------
/src/SharpRedis/Extensions/net30_35_40_45/Array.cs:
--------------------------------------------------------------------------------
1 | #if LOW_NET || NET40 || NET45
2 | #pragma warning disable IDE0130
3 | namespace SharpRedis
4 | {
5 | internal static class Array
6 | {
7 | public static T[] Empty()
8 | {
9 | return EmptyArray.Value;
10 | }
11 | }
12 |
13 | internal static class EmptyArray
14 | {
15 | public static readonly T[] Value = new T[0];
16 | }
17 | }
18 | #endif
19 |
--------------------------------------------------------------------------------
/src/SharpRedis/Extensions/net35_30/CancellationToken.cs:
--------------------------------------------------------------------------------
1 | #if LOW_NET
2 | #pragma warning disable IDE0130
3 | using System;
4 | using System.Threading;
5 |
6 | namespace SharpRedis
7 | {
8 | public readonly struct CancellationToken
9 | {
10 | private readonly CancellationTokenSource _source;
11 |
12 | public bool IsCancellationRequested
13 | {
14 | get
15 | {
16 | if (this._source is null) return false;
17 | return this._source.IsCancellationRequested;
18 | }
19 | }
20 |
21 | public WaitHandle WaitHandle
22 | {
23 | get
24 | {
25 | if (this._source == null) return CancellationTokenSource._neverCanceledSource.WaitHandle;
26 | return this._source.WaitHandle;
27 | }
28 | }
29 |
30 | public static CancellationToken None => default;
31 |
32 | internal CancellationToken(CancellationTokenSource source)
33 | {
34 | this._source = source;
35 | }
36 |
37 | public void ThrowIfCancellationRequested()
38 | {
39 | if (this.IsCancellationRequested)
40 | {
41 | throw new OperationCanceledException("The operation has timed out.");
42 | }
43 | }
44 |
45 | public override bool Equals(object obj)
46 | {
47 | if (obj is CancellationToken token)
48 | {
49 | return this.Equals(token);
50 | }
51 | return false;
52 | }
53 |
54 | public bool Equals(CancellationToken other)
55 | {
56 | if (this._source == null && other._source == null) return true;
57 | return this._source.Equals(other._source);
58 | }
59 |
60 | public override int GetHashCode()
61 | {
62 | return this._source.GetHashCode();
63 | }
64 |
65 | public static bool operator ==(CancellationToken left, CancellationToken right)
66 | {
67 | return left.Equals(right);
68 | }
69 |
70 | public static bool operator !=(CancellationToken left, CancellationToken right)
71 | {
72 | return !(left == right);
73 | }
74 | }
75 | }
76 | #endif
77 |
--------------------------------------------------------------------------------
/src/SharpRedis/Extensions/net35_30/CancellationTokenSource.cs:
--------------------------------------------------------------------------------
1 | #if LOW_NET
2 | #pragma warning disable IDE0130
3 | using System;
4 | using System.Threading;
5 |
6 | namespace SharpRedis
7 | {
8 | public sealed class CancellationTokenSource : IDisposable
9 | {
10 | private volatile bool _isCancellationRequested;
11 | private readonly CancellationToken _cancellationToken;
12 | private volatile Timer _timer;
13 | private volatile ManualResetEvent _kernelEvent;
14 | private bool _disposedValue;
15 |
16 | internal static readonly CancellationTokenSource _neverCanceledSource = new CancellationTokenSource();
17 |
18 | public CancellationToken Token
19 | {
20 | get
21 | {
22 | if (this._disposedValue) throw new ObjectDisposedException(nameof(CancellationTokenSource));
23 | return this._cancellationToken;
24 | }
25 | }
26 |
27 | public WaitHandle WaitHandle
28 | {
29 | get
30 | {
31 | if (this._disposedValue) throw new ObjectDisposedException(nameof(CancellationTokenSource));
32 | if (this._kernelEvent != null) return this._kernelEvent;
33 | var mre = new ManualResetEvent(false);
34 | if (Interlocked.CompareExchange(ref this._kernelEvent, mre, null) != null)
35 | {
36 | (mre as IDisposable).Dispose();
37 | }
38 |
39 | if (this.IsCancellationRequested)
40 | {
41 | this._kernelEvent.Set();
42 | }
43 | return this._kernelEvent;
44 | }
45 | }
46 |
47 | public bool IsCancellationRequested => this._isCancellationRequested;
48 |
49 | public CancellationTokenSource()
50 | {
51 | this._cancellationToken = new CancellationToken(this);
52 | }
53 |
54 | public void Cancel()
55 | {
56 | if (this._disposedValue) throw new ObjectDisposedException(nameof(CancellationTokenSource));
57 | lock (this)
58 | {
59 | if (this._isCancellationRequested) return;
60 | this._isCancellationRequested = true;
61 | this._kernelEvent?.Set();
62 | this._timer?.Dispose();
63 | this._timer = null;
64 | }
65 | }
66 |
67 | public void CancelAfter(int millisecondsDelay)
68 | {
69 | if (this._disposedValue) throw new ObjectDisposedException(nameof(CancellationTokenSource));
70 | lock (this)
71 | {
72 | if (this._isCancellationRequested) return;
73 | this._timer?.Dispose();
74 | this._timer = null;
75 | this._timer = new Timer(_ => this.Cancel(), null, millisecondsDelay, Timeout.Infinite);
76 | }
77 | }
78 |
79 | public void CancelAfter(TimeSpan dueTime)
80 | {
81 | if (this._disposedValue) throw new ObjectDisposedException(nameof(CancellationTokenSource));
82 | lock (this)
83 | {
84 | if (this._isCancellationRequested) return;
85 | this._timer?.Dispose();
86 | this._timer = null;
87 | this._timer = new Timer(_ => this.Cancel(), null, (int)dueTime.TotalMilliseconds, Timeout.Infinite);
88 | }
89 | }
90 |
91 | private void Dispose(bool disposing)
92 | {
93 | if (!this._disposedValue)
94 | {
95 | this._disposedValue = true;
96 | if (disposing)
97 | {
98 | if (this._kernelEvent != null)
99 | {
100 | var mre = Interlocked.Exchange(ref this._kernelEvent, null);
101 | if (mre != null) (mre as IDisposable).Dispose();
102 | }
103 | this._timer?.Dispose();
104 | }
105 | this._timer = null;
106 | }
107 | }
108 |
109 | public void Dispose()
110 | {
111 | this.Dispose(disposing: true);
112 | GC.SuppressFinalize(this);
113 | }
114 |
115 | ~CancellationTokenSource()
116 | {
117 | this.Dispose(disposing: false);
118 | }
119 | }
120 | }
121 | #endif
--------------------------------------------------------------------------------
/src/SharpRedis/Extensions/net35_30/ConcurrentDictionary.cs:
--------------------------------------------------------------------------------
1 | #if LOW_NET
2 | #pragma warning disable IDE0130
3 | using System.Collections.Generic;
4 |
5 | namespace System.Collections.Concurrent
6 | {
7 | internal sealed class ConcurrentDictionary : IEnumerable>
8 | {
9 | private readonly int _numLocks;
10 | private readonly object[] _locks;
11 | private readonly Dictionary[] _dictionaries;
12 |
13 | internal int Count
14 | {
15 | get
16 | {
17 | int count = 0;
18 | for (int i = 0; i < _numLocks; i++)
19 | {
20 | lock (this._locks[i])
21 | {
22 | count += this._dictionaries[i].Count;
23 | }
24 | }
25 | return count;
26 | }
27 | }
28 |
29 | internal bool IsEmpty
30 | {
31 | get
32 | {
33 | for (uint i = 0; i < this._numLocks; i++)
34 | {
35 | lock (this._locks[i])
36 | {
37 | if (this._dictionaries[i].Count > 0)
38 | {
39 | return false;
40 | }
41 | }
42 | }
43 | return true;
44 | }
45 | }
46 |
47 | internal IEnumerable Keys
48 | {
49 | get
50 | {
51 | var keys = new List();
52 | for (int i = 0; i < this._numLocks; i++)
53 | {
54 | lock (this._locks[i])
55 | {
56 | keys.AddRange(this._dictionaries[i].Keys);
57 | }
58 | }
59 | return keys;
60 | }
61 | }
62 |
63 | internal IEnumerable Values
64 | {
65 | get
66 | {
67 | var values = new List();
68 | for (int i = 0; i < this._numLocks; i++)
69 | {
70 | lock (this._locks[i])
71 | {
72 | values.AddRange(this._dictionaries[i].Values);
73 | }
74 | }
75 | return values;
76 | }
77 | }
78 |
79 | internal ConcurrentDictionary(int concurrencyLevel = 16, int initialCapacity = 101)
80 | {
81 | this._numLocks = concurrencyLevel;
82 | this._locks = new object[this._numLocks];
83 | this._dictionaries = new Dictionary[this._numLocks];
84 |
85 | for (uint i = 0; i < this._numLocks; i++)
86 | {
87 | this._locks[i] = new object();
88 | this._dictionaries[i] = new Dictionary(initialCapacity / _numLocks);
89 | }
90 | }
91 |
92 | private int GetLockIndex(TKey key)
93 | {
94 | return (key.GetHashCode() & 0x7FFFFFFF) % this._numLocks;
95 | }
96 |
97 | internal bool TryAdd(TKey key, TValue value)
98 | {
99 | int lockIndex = this.GetLockIndex(key);
100 | lock (this._locks[lockIndex])
101 | {
102 | if (this._dictionaries[lockIndex].ContainsKey(key))
103 | {
104 | return false;
105 | }
106 | this._dictionaries[lockIndex][key] = value;
107 | return true;
108 | }
109 | }
110 |
111 | internal bool TryUpdate(TKey key, TValue newValue, TValue comparisonValue)
112 | {
113 | int lockIndex = this.GetLockIndex(key);
114 | lock (this._locks[lockIndex])
115 | {
116 | if (this._dictionaries[lockIndex].TryGetValue(key, out var existingValue) && EqualityComparer.Default.Equals(existingValue, comparisonValue))
117 | {
118 | this._dictionaries[lockIndex][key] = newValue;
119 | return true;
120 | }
121 | return false;
122 | }
123 | }
124 |
125 | internal bool TryRemove(TKey key, out TValue value)
126 | {
127 | int lockIndex = this.GetLockIndex(key);
128 | lock (this._locks[lockIndex])
129 | {
130 | if (this._dictionaries[lockIndex].TryGetValue(key, out value))
131 | {
132 | this._dictionaries[lockIndex].Remove(key);
133 | return true;
134 | }
135 | return false;
136 | }
137 | }
138 |
139 | internal bool TryGetValue(TKey key, out TValue value)
140 | {
141 | int lockIndex = this.GetLockIndex(key);
142 | lock (this._locks[lockIndex])
143 | {
144 | return this._dictionaries[lockIndex].TryGetValue(key, out value);
145 | }
146 | }
147 |
148 | internal TValue this[TKey key]
149 | {
150 | get
151 | {
152 | if (this.TryGetValue(key, out var value))
153 | {
154 | return value;
155 | }
156 | throw new KeyNotFoundException();
157 | }
158 | set
159 | {
160 | int lockIndex = this.GetLockIndex(key);
161 | lock (this._locks[lockIndex])
162 | {
163 | this._dictionaries[lockIndex][key] = value;
164 | }
165 | }
166 | }
167 |
168 | internal bool ContainsKey(TKey key)
169 | {
170 | return this.TryGetValue(key, out _);
171 | }
172 |
173 | internal void Clear()
174 | {
175 | for (int i = 0; i < _numLocks; i++)
176 | {
177 | lock (this._locks[i])
178 | {
179 | this._dictionaries[i].Clear();
180 | }
181 | }
182 | }
183 |
184 | public IEnumerator> GetEnumerator()
185 | {
186 | for (int i = 0; i < this._numLocks; i++)
187 | {
188 | lock (this._locks[i])
189 | {
190 | foreach (var kvp in this._dictionaries[i])
191 | {
192 | yield return kvp;
193 | }
194 | }
195 | }
196 | }
197 |
198 | IEnumerator IEnumerable.GetEnumerator()
199 | {
200 | return GetEnumerator();
201 | }
202 | }
203 | }
204 | #endif
205 |
--------------------------------------------------------------------------------
/src/SharpRedis/Extensions/net35_30/ConcurrentQueue.cs:
--------------------------------------------------------------------------------
1 | #if LOW_NET
2 | #pragma warning disable IDE0130
3 | using System.Threading;
4 |
5 | namespace System.Collections.Concurrent
6 | {
7 | internal sealed class ConcurrentQueue
8 | {
9 | private Node _head;
10 | private Node _tail;
11 |
12 | internal bool IsEmpty
13 | {
14 | get
15 | {
16 | return this._head._next == null;
17 | }
18 | }
19 |
20 | internal ConcurrentQueue()
21 | {
22 | this._head = new Node(default);
23 | this._tail = _head;
24 | }
25 |
26 | internal void Enqueue(T item)
27 | {
28 | var newNode = new Node(item);
29 | while (true)
30 | {
31 | Node oldTail = this._tail;
32 | Node oldTailNext = oldTail._next;
33 |
34 | if (this._tail == oldTail)
35 | {
36 | if (oldTailNext == null)
37 | {
38 | if (Interlocked.CompareExchange(ref oldTail._next, newNode, null) == null)
39 | {
40 | _ = Interlocked.CompareExchange(ref this._tail, newNode, oldTail);
41 | return;
42 | }
43 | }
44 | else
45 | {
46 | _ = Interlocked.CompareExchange(ref this._tail, oldTailNext, oldTail);
47 | }
48 | }
49 | }
50 | }
51 |
52 | internal bool TryDequeue(out T result)
53 | {
54 | result = default;
55 | while (true)
56 | {
57 | var oldHead = this._head;
58 | var oldTail = this._tail;
59 | var oldHeadNext = oldHead._next;
60 |
61 | if (oldHead == this._head)
62 | {
63 | if (oldHead == oldTail)
64 | {
65 | if (oldHeadNext == null) return false;
66 | _ = Interlocked.CompareExchange(ref this._tail, oldHeadNext, oldTail);
67 | }
68 | else
69 | {
70 | result = oldHeadNext._value;
71 | if (Interlocked.CompareExchange(ref this._head, oldHeadNext, oldHead) == oldHead)
72 | {
73 | return true;
74 | }
75 | }
76 | }
77 | }
78 | }
79 |
80 | internal bool TryPeek(out T result)
81 | {
82 | var oldHeadNext = this._head._next;
83 | if (oldHeadNext == null)
84 | {
85 | result = default;
86 | return false;
87 | }
88 | result = oldHeadNext._value;
89 | return true;
90 | }
91 |
92 | internal int Count
93 | {
94 | get
95 | {
96 | int count = 0;
97 | var current = this._head._next;
98 | while (current != null)
99 | {
100 | count++;
101 | current = current._next;
102 | }
103 | return count;
104 | }
105 | }
106 |
107 | internal void Clear()
108 | {
109 | this._head = new Node(default);
110 | this._tail = this._head;
111 | }
112 |
113 | private sealed class Node
114 | {
115 | internal T _value;
116 | internal Node _next;
117 |
118 | internal Node(T value)
119 | {
120 | this._value = value;
121 | this._next = null;
122 | }
123 | }
124 | }
125 | }
126 | #endif
127 |
--------------------------------------------------------------------------------
/src/SharpRedis/Extensions/net35_30/ConcurrentStack.cs:
--------------------------------------------------------------------------------
1 | #if LOW_NET
2 | #pragma warning disable IDE0130
3 | using System.Collections.Generic;
4 | using System.Threading;
5 |
6 | namespace System.Collections.Concurrent
7 | {
8 | internal sealed class ConcurrentStack
9 | {
10 | private Node _head = null;
11 |
12 | internal bool IsEmpty => this._head == null;
13 |
14 | internal ConcurrentStack()
15 | {
16 | }
17 |
18 | internal void Push(T item)
19 | {
20 | var newNode = new Node(item);
21 | while (true)
22 | {
23 | var oldHead = this._head;
24 | newNode._next = oldHead;
25 | if (Interlocked.CompareExchange(ref this._head, newNode, oldHead) == oldHead)
26 | {
27 | return;
28 | }
29 | }
30 | }
31 |
32 | internal bool TryPop(out T result)
33 | {
34 | while (true)
35 | {
36 | var oldHead = this._head;
37 | if (oldHead == null)
38 | {
39 | result = default;
40 | return false;
41 | }
42 |
43 | Node newHead = oldHead._next;
44 | if (Interlocked.CompareExchange(ref this._head, newHead, oldHead) == oldHead)
45 | {
46 | result = oldHead._value;
47 | return true;
48 | }
49 | }
50 | }
51 |
52 | internal bool TryPeek(out T result)
53 | {
54 | var oldHead = this._head;
55 | if (oldHead == null)
56 | {
57 | result = default;
58 | return false;
59 | }
60 | result = oldHead._value;
61 | return true;
62 | }
63 |
64 | internal int Count
65 | {
66 | get
67 | {
68 | int count = 0;
69 | var current = this._head;
70 | while (current != null)
71 | {
72 | count++;
73 | current = current._next;
74 | }
75 | return count;
76 | }
77 | }
78 |
79 | internal void Clear()
80 | {
81 | this._head = null;
82 | }
83 |
84 | internal T[] ToArray()
85 | {
86 | var list = new List();
87 | var current = this._head;
88 | while (current != null)
89 | {
90 | list.Add(current._value);
91 | current = current._next;
92 | }
93 | list.Reverse();
94 | return list.ToArray();
95 | }
96 |
97 | private sealed class Node
98 | {
99 | internal T _value;
100 | internal Node _next;
101 |
102 | public Node(T value)
103 | {
104 | this._value = value;
105 | this._next = null;
106 | }
107 | }
108 | }
109 | }
110 | #endif
111 |
--------------------------------------------------------------------------------
/src/SharpRedis/Extensions/net35_30/StructuralEqualityComparer.cs:
--------------------------------------------------------------------------------
1 | #if LOW_NET
2 | #pragma warning disable IDE0130
3 | namespace System.Collections.StructuralComparisons
4 | {
5 | internal static class StructuralEqualityComparer
6 | {
7 | static internal bool Equals(byte[] array1, byte[] array2)
8 | {
9 | if (array1 == array2) return true;
10 |
11 | if (array1 == null || array2 == null || array1.Length != array2.Length)
12 | return false;
13 |
14 | for (uint i = 0; i < array1.Length; i++)
15 | {
16 | if (array1[i] != array2[i])
17 | return false;
18 | }
19 | return true;
20 | }
21 | }
22 | }
23 | #endif
24 |
--------------------------------------------------------------------------------
/src/SharpRedis/Models/BitFieldArg.cs:
--------------------------------------------------------------------------------
1 | #pragma warning disable IDE0130
2 |
3 | namespace SharpRedis
4 | {
5 | ///
6 | /// BitField Arg
7 | ///
8 | public sealed class BitFieldArg : IBitFieldArg, IBitFieldArgEncoding>, IBitFieldArgOffset, //GET
9 | IBitFieldArgEncoding>, IBitFieldArgOffset, IBitFieldArgValue, //SET
10 | IBitFieldArgEncoding>, IBitFieldArgOffset, IBitFieldArgIncrement, //Increment
11 | IBitFieldArgOverflow //OVERFLOW
12 | {
13 | private readonly string[] _args;
14 | private int _currentIndex = 0;
15 | private readonly BitFieldArgType _type;
16 |
17 | BitFieldArgType IBitFieldArg.ArgType => this._type;
18 |
19 | private BitFieldArg(int argsSize, string argName, BitFieldArgType type)
20 | {
21 | this._args = new string[argsSize];
22 | this.Write(argName);
23 | this._type = type;
24 | }
25 |
26 | #region Creates
27 | ///
28 | /// Create a GET arg
29 | /// 创建一个GET参数
30 | ///
31 | ///
32 | public static IBitFieldArgEncoding> CreateGet()
33 | {
34 | return new BitFieldArg(3, "GET", BitFieldArgType.Get);
35 | }
36 |
37 | ///
38 | /// Create a SET arg
39 | /// 创建一个SET参数
40 | ///
41 | ///
42 | public static IBitFieldArgEncoding> CreateSet()
43 | {
44 | return new BitFieldArg(4, "SET", BitFieldArgType.Set);
45 | }
46 |
47 | ///
48 | /// Create a OVERFLOW arg
49 | /// 创建一个OVERFLOW参数
50 | ///
51 | ///
52 | public static IBitFieldArgOverflow CreateOverflow()
53 | {
54 | return new BitFieldArg(2, "OVERFLOW", BitFieldArgType.Overflow);
55 | }
56 |
57 | ///
58 | /// Create a INCRBY arg
59 | /// 创建一个INCRBY参数
60 | ///
61 | ///
62 | public static IBitFieldArgEncoding> CreateIncrement()
63 | {
64 | return new BitFieldArg(4, "INCRBY", BitFieldArgType.Increment);
65 | }
66 | #endregion
67 |
68 | #region Get
69 | IBitFieldArgOffset IBitFieldArgEncoding>.Signed(uint u)
70 | {
71 | if (u <= 0) throw new RedisException("Minimum support 1");
72 | if (u >= 65) throw new RedisException("Maximum support 64");
73 | this.Write($"i{u}");
74 | return this;
75 | }
76 |
77 | IBitFieldArgOffset IBitFieldArgEncoding>.Unsigned(uint u)
78 | {
79 | if (u <= 0) throw new RedisException("Minimum support 1");
80 | if (u >= 64) throw new RedisException("Maximum support 63");
81 | this.Write($"u{u}");
82 | return this;
83 | }
84 |
85 | IBitFieldArg IBitFieldArgOffset.Offset(uint offset)
86 | {
87 | this.Write(offset.ToString());
88 | return this;
89 | }
90 |
91 | IBitFieldArg IBitFieldArgOffset.MultipliedOffset(uint offset)
92 | {
93 | this.Write($"#{offset}");
94 | return this;
95 | }
96 | #endregion
97 |
98 | #region Set
99 | IBitFieldArgOffset IBitFieldArgEncoding>.Signed(uint u)
100 | {
101 | if (u <= 0) throw new RedisException("Minimum support 1");
102 | if (u >= 65) throw new RedisException("Maximum support 64");
103 | this.Write($"i{u}");
104 | return this;
105 | }
106 |
107 | IBitFieldArgOffset IBitFieldArgEncoding>.Unsigned(uint u)
108 | {
109 | if (u <= 0) throw new RedisException("Minimum support 1");
110 | if (u >= 64) throw new RedisException("Maximum support 63");
111 | this.Write($"u{u}");
112 | return this;
113 | }
114 |
115 | IBitFieldArgValue IBitFieldArgOffset.Offset(uint offset)
116 | {
117 | this.Write(offset.ToString());
118 | return this;
119 | }
120 |
121 | IBitFieldArgValue IBitFieldArgOffset.MultipliedOffset(uint offset)
122 | {
123 | this.Write($"#{offset}");
124 | return this;
125 | }
126 |
127 | IBitFieldArg IBitFieldArgValue.Value(long value)
128 | {
129 | this.Write(value.ToString());
130 | return this;
131 | }
132 | #endregion
133 |
134 | #region Overflow
135 | IBitFieldArg IBitFieldArgOverflow.Wrap()
136 | {
137 | this._args[this._currentIndex++] = "WRAP";
138 | return this;
139 | }
140 |
141 | IBitFieldArg IBitFieldArgOverflow.Sat()
142 | {
143 | this._args[this._currentIndex++] = "SAT";
144 | return this;
145 | }
146 |
147 | IBitFieldArg IBitFieldArgOverflow.Fail()
148 | {
149 | this._args[this._currentIndex++] = "FAIL";
150 | return this;
151 | }
152 | #endregion
153 |
154 | #region Increment
155 | IBitFieldArgOffset IBitFieldArgEncoding>.Signed(uint u)
156 | {
157 | if (u <= 0) throw new RedisException("Minimum support 1");
158 | if (u >= 65) throw new RedisException("Maximum support 64");
159 | this.Write($"i{u}");
160 | return this;
161 | }
162 |
163 | IBitFieldArgOffset IBitFieldArgEncoding>.Unsigned(uint u)
164 | {
165 | if (u <= 0) throw new RedisException("Minimum support 1");
166 | if (u >= 64) throw new RedisException("Maximum support 63");
167 | this.Write($"u{u}");
168 | return this;
169 | }
170 |
171 | IBitFieldArgIncrement IBitFieldArgOffset.Offset(uint offset)
172 | {
173 | this.Write(offset.ToString());
174 | return this;
175 | }
176 |
177 | IBitFieldArgIncrement IBitFieldArgOffset.MultipliedOffset(uint offset)
178 | {
179 | this.Write($"#{offset}");
180 | return this;
181 | }
182 |
183 | IBitFieldArg IBitFieldArgIncrement.Increment(long increment)
184 | {
185 | this.Write(increment.ToString());
186 | return this;
187 | }
188 | #endregion
189 |
190 | string[] IBitFieldArg.Convert() => this._args;
191 |
192 | private void Write(string arg)
193 | {
194 | this._args[this._currentIndex++] = arg;
195 | }
196 | }
197 | }
198 |
--------------------------------------------------------------------------------
/src/SharpRedis/Models/ChannelMode.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpRedis.Models
4 | {
5 | internal readonly struct ChannelMode : IEquatable
6 | {
7 | internal ChannelModeEnum Mode { get; }
8 | internal string Channel { get; }
9 |
10 | internal ChannelMode(string channel, in ChannelModeEnum mode)
11 | {
12 | this.Mode = mode;
13 | this.Channel = channel;
14 | }
15 |
16 | public override int GetHashCode()
17 | {
18 | return this.Channel.GetHashCode() ^ this.Mode.GetHashCode();
19 | }
20 |
21 | public bool Equals(ChannelMode other)
22 | {
23 | return this.Channel == other.Channel && this.Mode == other.Mode;
24 | }
25 |
26 | #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
27 | public override bool Equals(object? obj)
28 | #else
29 | public override bool Equals(object obj)
30 | #endif
31 | {
32 | if (obj == null) return false;
33 | if (obj is ChannelMode cm)
34 | {
35 | return cm.Equals(this);
36 | }
37 | return false;
38 | }
39 |
40 | public override string ToString()
41 | {
42 | return this.Channel;
43 | }
44 |
45 | public static bool operator ==(ChannelMode left, ChannelMode right)
46 | {
47 | return left.Equals(right);
48 | }
49 |
50 | public static bool operator !=(ChannelMode left, ChannelMode right)
51 | {
52 | return !left.Equals(right);
53 | }
54 |
55 | public static implicit operator string(in ChannelMode cm)
56 | {
57 | return cm.Channel;
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/SharpRedis/Models/ClientSideCacheKey.cs:
--------------------------------------------------------------------------------
1 | #pragma warning disable IDE0130
2 | using System;
3 |
4 | namespace SharpRedis
5 | {
6 | public readonly struct ClientSideCacheKey : IEquatable
7 | {
8 | private readonly string[] _keys;
9 | private readonly long _keyHash;
10 |
11 | internal ClientSideCacheKey(string[] keys, long keyHash)
12 | {
13 | this._keys = keys;
14 | this._keyHash = keyHash;
15 | }
16 |
17 | internal bool ContainsKey(string key)
18 | {
19 | for (uint i = 0; i < this._keys.Length; i++)
20 | {
21 | if (this._keys[i] == key) return true;
22 | }
23 | return false;
24 | }
25 |
26 | internal string[] GetKeys()
27 | {
28 | return this._keys;
29 | }
30 |
31 | public override int GetHashCode()
32 | {
33 | return this._keyHash.GetHashCode();
34 | }
35 |
36 | public bool Equals(ClientSideCacheKey other)
37 | {
38 | return other._keyHash == this._keyHash;
39 | }
40 |
41 | #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
42 | public override bool Equals(object? obj)
43 | #else
44 | public override bool Equals(object obj)
45 | #endif
46 | {
47 | if (obj == null) return false;
48 | if (obj is ClientSideCacheKey item)
49 | {
50 | return item.Equals(this);
51 | }
52 | return false;
53 | }
54 |
55 | public override string ToString()
56 | {
57 | return this._keyHash.ToString();
58 | }
59 |
60 | public static bool operator ==(ClientSideCacheKey left, ClientSideCacheKey right)
61 | {
62 | return left.Equals(right);
63 | }
64 |
65 | public static bool operator !=(ClientSideCacheKey left, ClientSideCacheKey right)
66 | {
67 | return !left.Equals(right);
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/SharpRedis/Models/Delegates.cs:
--------------------------------------------------------------------------------
1 | #pragma warning disable IDE0130
2 | #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
3 | #nullable enable
4 | #endif
5 | #if !LOW_NET
6 | using System.Threading.Tasks;
7 | #endif
8 |
9 | namespace SharpRedis
10 | {
11 | #region Sync NET3.0 NET3.5
12 | #if LOW_NET
13 | ///
14 | /// Receive subscription event
15 | /// 收到订阅消息事件
16 | ///
17 | /// Subscribed channel
18 | /// 订阅的通道名称
19 | ///
20 | /// Data received
21 | /// 收到的数据
22 | ///
23 | public delegate void OnReceive(string channel, object data);
24 |
25 | ///
26 | /// Receive subscription event
27 | /// 收到订阅消息事件
28 | ///
29 | /// Subscribes the client to the given patterns
30 | /// 订阅的模式
31 | ///
32 | /// Subscribed channel
33 | /// 订阅的通道名称
34 | ///
35 | /// Data received
36 | /// 收到的数据
37 | ///
38 | public delegate void POnReceive(string pattern, string channel, object data);
39 | #endif
40 | #endregion
41 |
42 | #region Async
43 | #if !LOW_NET
44 | ///
45 | /// Receive subscription event
46 | /// 收到订阅消息异步事件
47 | ///
48 | /// Subscribed channel
49 | /// 订阅的通道名称
50 | ///
51 | /// Data received
52 | /// 收到的数据
53 | ///
54 | public delegate Task OnReceive(string channel, object data);
55 |
56 | ///
57 | /// Receive subscription event
58 | /// 收到订阅消息异步事件
59 | ///
60 | /// Subscribes the client to the given patterns.
61 | /// Subscribed channel
62 | /// 订阅的通道名称
63 | ///
64 | ///
65 | /// Data received
66 | /// 收到的数据
67 | ///
68 | ///
69 | public delegate Task POnReceive(string pattern, string channel, object data);
70 | #endif
71 | #endregion
72 | }
73 |
--------------------------------------------------------------------------------
/src/SharpRedis/Models/OnReceiveModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpRedis.Models
4 | {
5 | internal sealed class OnReceiveModel
6 | where TOnReceive : Delegate
7 | {
8 | private readonly ResultDataType _subscribeDataType;
9 | private readonly TOnReceive _onReceive;
10 |
11 | internal ResultDataType DataType => this._subscribeDataType;
12 |
13 | internal TOnReceive OnReceive => this._onReceive;
14 |
15 | internal OnReceiveModel(ResultDataType subscribeDataType, TOnReceive onReceive)
16 | {
17 | this._subscribeDataType = subscribeDataType;
18 | this._onReceive = onReceive;
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/SharpRedis/Models/Standard/IBitFieldArg.cs:
--------------------------------------------------------------------------------
1 | #pragma warning disable IDE0130
2 |
3 | namespace SharpRedis
4 | {
5 | ///
6 | /// BitField args
7 | ///
8 | public interface IBitFieldArg
9 | {
10 | ///
11 | /// Get arg type
12 | /// 获得参数类型
13 | ///
14 | BitFieldArgType ArgType { get; }
15 |
16 | ///
17 | /// Convert to args
18 | ///
19 | ///
20 | string[] Convert();
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/SharpRedis/Models/Standard/IBitFieldArgEncoding.cs:
--------------------------------------------------------------------------------
1 | #pragma warning disable IDE0130
2 |
3 | namespace SharpRedis
4 | {
5 | public interface IBitFieldArgEncoding
6 | {
7 | ///
8 | /// Writes an unsigned integer
9 | /// 写入无符号整数
10 | ///
11 | /// number
12 | ///
13 | T Unsigned(uint u);
14 |
15 | ///
16 | /// Writes an signed integer
17 | /// 写入有符号整数
18 | ///
19 | /// number
20 | ///
21 | T Signed(uint u);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/SharpRedis/Models/Standard/IBitFieldArgIncrement.cs:
--------------------------------------------------------------------------------
1 | #pragma warning disable IDE0130
2 |
3 | namespace SharpRedis
4 | {
5 | public interface IBitFieldArgIncrement
6 | {
7 | ///
8 | /// Write number increment
9 | /// 写入自增值
10 | ///
11 | /// increment
12 | ///
13 | IBitFieldArg Increment(long increment);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/SharpRedis/Models/Standard/IBitFieldArgOffset.cs:
--------------------------------------------------------------------------------
1 | #pragma warning disable IDE0130
2 |
3 | namespace SharpRedis
4 | {
5 | public interface IBitFieldArgOffset
6 | {
7 | ///
8 | /// Set offset
9 | /// 设置偏移量
10 | ///
11 | /// offset
12 | ///
13 | T Offset(uint offset);
14 |
15 | ///
16 | /// if the offset is prefixed with a # character, the specified offset is multiplied by the integer encoding's width
17 | /// 指定的偏移量将乘以整数编码的宽度
18 | ///
19 | /// offset
20 | ///
21 | T MultipliedOffset(uint offset);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/SharpRedis/Models/Standard/IBitFieldArgOverflow.cs:
--------------------------------------------------------------------------------
1 | #pragma warning disable IDE0130
2 |
3 | namespace SharpRedis
4 | {
5 | public interface IBitFieldArgOverflow
6 | {
7 | ///
8 | /// Wrap around, both with signed and unsigned integers. In the case of unsigned integers, wrapping is like performing the operation modulo the maximum value the integer can contain (the C standard behavior). With signed integers instead wrapping means that overflows restart towards the most negative value and underflows towards the most positive ones, so for example if an i8 integer is set to the value 127, incrementing it by 1 will yield -128
9 | /// 环绕,有符号和无符号整数。对于无符号整数,换行就像执行对整数可以包含的最大值取模的运算(C 标准行为)。使用有符号整数而不是换行意味着上溢重新开始朝向最大负值,下溢朝向最大正值,因此例如,如果 i8 整数设置为值 127,则将其递增 1 将产生 -128
10 | ///
11 | ///
12 | IBitFieldArg Wrap();
13 |
14 | ///
15 | /// Uses saturation arithmetic, that is, on underflows the value is set to the minimum integer value, and on overflows to the maximum integer value. For example incrementing an i8 integer starting from value 120 with an increment of 10, will result into the value 127, and further increments will always keep the value at 127. The same happens on underflows, but towards the value is blocked at the most negative value
16 | /// 使用饱和算术,即下溢时将值设置为最小整数值,上溢时将值设置为最大整数值。例如,从值 120 开始递增 i8 整数,增量为 10,将得到值 127,进一步的增量将始终使该值保持在 127。下溢时也会发生同样的情况,但下溢的方向是该值被阻止在最大负值
17 | ///
18 | ///
19 | IBitFieldArg Sat();
20 |
21 | ///
22 | /// In this mode no operation is performed on overflows or underflows detected. The corresponding return value is set to NULL to signal the condition to the caller
23 | /// 在此模式下,检测到上溢或下溢时不执行任何操作。相应的返回值设置为 NULL 以向调用者发出信号通知
24 | ///
25 | ///
26 | IBitFieldArg Fail();
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/SharpRedis/Models/Standard/IBitFieldArgValue.cs:
--------------------------------------------------------------------------------
1 | #pragma warning disable IDE0130
2 |
3 | namespace SharpRedis
4 | {
5 | public interface IBitFieldArgValue
6 | {
7 | ///
8 | /// Write number value
9 | /// 写入数值
10 | ///
11 | /// value
12 | ///
13 | IBitFieldArg Value(long value);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/SharpRedis/Models/StreamTrimOptions.cs:
--------------------------------------------------------------------------------
1 | #pragma warning disable IDE0130
2 | #if NET5_0_OR_GREATER
3 | #pragma warning disable IDE0090
4 | #endif
5 | namespace SharpRedis
6 | {
7 | public sealed class StreamTrimOptions : System.IEquatable
8 | {
9 | private readonly static StreamTrimOptions _empty = new StreamTrimOptions();
10 |
11 | private readonly StreamTrimMode _trimMode;
12 | private readonly StreamTrimStrategy _trimStrategy;
13 | private readonly string _threshold;
14 | private readonly ulong _limit;
15 |
16 | internal StreamTrimMode TrimMode => this._trimMode;
17 |
18 | internal StreamTrimStrategy TrimStrategy => this._trimStrategy;
19 |
20 | internal string Threshold => this._threshold;
21 |
22 | internal ulong Limit => this._limit;
23 |
24 | ///
25 | /// Gets empty StreamTrimOptions
26 | /// 获得一个空的修剪配置
27 | ///
28 | public static StreamTrimOptions Empty => StreamTrimOptions._empty;
29 |
30 | private StreamTrimOptions()
31 | {
32 | this._threshold = string.Empty;
33 | this._trimMode = StreamTrimMode.None;
34 | this._trimStrategy = StreamTrimStrategy.None;
35 | }
36 |
37 | ///
38 | /// Create StreamTrimOptions
39 | ///
40 | /// MAXLEN | MINID
41 | /// = | ~
42 | /// threshold
43 | /// limit count. The default 0 indicates no limit
44 | /// Available since: 6.2.0
45 | /// 删除个数, 默认0表示无限制
46 | /// 支持此参数的Redis版本: 6.2.0+
47 | ///
48 | public StreamTrimOptions(StreamTrimMode trimMode, StreamTrimStrategy trimStrategy, string threshold, ulong limit = 0)
49 | {
50 | this._trimMode = trimMode;
51 | this._trimStrategy = trimStrategy;
52 | this._threshold = threshold;
53 | this._limit = limit;
54 | }
55 |
56 | public override string ToString()
57 | {
58 | if (this._limit > 0)
59 | {
60 | return $"{this._trimMode.ToString().ToUpper()} {this._trimStrategy.ToString().ToUpper()} {this._threshold} LIMIT {this._limit}";
61 | }
62 | else
63 | {
64 | return $"{this._trimMode.ToString().ToUpper()} {this._trimStrategy.ToString().ToUpper()} {this._threshold}";
65 | }
66 | }
67 |
68 | public override int GetHashCode()
69 | {
70 | return this._trimMode.GetHashCode() ^ this._trimStrategy.GetHashCode() ^ this._limit.GetHashCode() ^ this._threshold.GetHashCode();
71 | }
72 |
73 | #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
74 | public override bool Equals(object? obj)
75 | #else
76 | public override bool Equals(object obj)
77 | #endif
78 | {
79 | if (obj is StreamTrimOptions other)
80 | {
81 | return other == this;
82 | }
83 | return false;
84 | }
85 |
86 | #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
87 | public bool Equals(StreamTrimOptions? other)
88 | #else
89 | public bool Equals(StreamTrimOptions other)
90 | #endif
91 | {
92 | if (other is null) return false;
93 | return this._threshold == other._threshold
94 | && this._limit == other._limit
95 | && this._trimMode == other._trimMode
96 | && this._trimStrategy == other._trimStrategy;
97 | }
98 |
99 | ///
100 | /// Create StreamTrimOptions
101 | ///
102 | /// MAXLEN | MINID
103 | /// = | ~
104 | /// threshold
105 | /// limit count. The default 0 indicates no limit
106 | /// Available since: 6.2.0
107 | /// 删除个数, 默认0表示无限制
108 | /// 支持此参数的Redis版本: 6.2.0+
109 | ///
110 | public static StreamTrimOptions Create(StreamTrimMode trimMode, StreamTrimStrategy trimStrategy, string threshold, ulong limit = 0)
111 | {
112 | return new StreamTrimOptions(trimMode, trimStrategy, threshold, limit);
113 | }
114 |
115 | public static bool operator ==(StreamTrimOptions left, StreamTrimOptions right)
116 | {
117 | return left.Equals(right);
118 | }
119 |
120 | public static bool operator !=(StreamTrimOptions left, StreamTrimOptions right)
121 | {
122 | return !left.Equals(right);
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/src/SharpRedis/Network/DefaultConnection.cs:
--------------------------------------------------------------------------------
1 | using SharpRedis.Network.Standard;
2 | using System.Text;
3 |
4 | namespace SharpRedis.Network
5 | {
6 | internal sealed class DefaultConnection : BaseConnection
7 | {
8 | private readonly int _slaveIndex;
9 |
10 | internal int SlaveIndex => this._slaveIndex;
11 |
12 | #if NETSTANDARD2_1_OR_GREATER || NET5_0_OR_GREATER
13 | internal DefaultConnection(Encoding encoding, ConnectionOptions connectionOptions, byte[]? _prefix, int slaveIndex = -1)
14 | #else
15 | internal DefaultConnection(Encoding encoding, ConnectionOptions connectionOptions, byte[] _prefix, int slaveIndex = -1)
16 | #endif
17 | : base(encoding, connectionOptions, ConnectionType.Master, _prefix)
18 | {
19 | this._slaveIndex = slaveIndex;
20 | }
21 |
22 | ~DefaultConnection()
23 | {
24 | base.Dispose(true);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/SharpRedis/Network/Pool/DefaultPool.cs:
--------------------------------------------------------------------------------
1 | #if !LOW_NET
2 | using System.Threading.Tasks;
3 | using System.Threading;
4 | #endif
5 | using SharpRedis.Network.Standard;
6 |
7 | namespace SharpRedis.Network.Pool
8 | {
9 | internal sealed class DefaultPool : BaseConnectionPool
10 | {
11 | internal DefaultPool(ConnectionOptions masterConnectionOptions)
12 | : base(masterConnectionOptions)
13 | {
14 | base._idleThread.Start();
15 | }
16 |
17 | public sealed override void ReturnSlaveConnection(DefaultConnection connection)
18 | {
19 | throw new System.NotSupportedException();
20 | }
21 |
22 | public sealed override DefaultConnection GetSlaveConnection(CancellationToken cancellationToken)
23 | {
24 | throw new System.NotSupportedException();
25 | }
26 |
27 | #if !LOW_NET
28 | public sealed override Task GetSlaveConnectionAsync(CancellationToken cancellationToken)
29 | {
30 | throw new System.NotSupportedException();
31 | }
32 | #endif
33 |
34 | ~DefaultPool()
35 | {
36 | base.Dispose(true);
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/SharpRedis/Network/Standard/IConnection.cs:
--------------------------------------------------------------------------------
1 | #if !LOW_NET
2 | using System.Threading.Tasks;
3 | using System.Threading;
4 | #endif
5 | using SharpRedis.Models;
6 | using System;
7 | using System.Text;
8 |
9 | namespace SharpRedis.Network.Standard
10 | {
11 | internal interface IConnection : IDisposable
12 | {
13 | #region Properties
14 | bool Connected { get; }
15 |
16 | ConnectionOptions ConnectionOptions { get; }
17 |
18 | ConnectionType Type { get; }
19 |
20 | long ConnectionId { get; }
21 |
22 | string ConnectionName { get; }
23 |
24 | DateTime LastActiveTime { get; }
25 |
26 | ushort CurrentDataBaseIndex { get; }
27 |
28 | bool Tracking { get; set; }
29 |
30 | long RedirectConnectionId { get; set; }
31 |
32 | Encoding Encoding { get; }
33 | #endregion
34 |
35 | #region Methods
36 | void ResetBuffer();
37 |
38 | bool Connect();
39 |
40 | bool SwitchDatabaseIndex(ushort databaseIndex);
41 |
42 | #if NETSTANDARD2_1_OR_GREATER || NET5_0_OR_GREATER
43 | object? ExecuteCommand(CommandPacket command, CancellationToken cancellationToken);
44 |
45 | object? ExecuteCommands(CommandPacket[] commands, CancellationToken cancellationToken);
46 |
47 | Task