Skip to content

Commit

Permalink
Merge pull request #33 from neuecc/vNext
Browse files Browse the repository at this point in the history
Ready to ship v3.0.0
  • Loading branch information
xin9le authored Apr 29, 2021
2 parents 10ee736 + 9fc664d commit c576902
Show file tree
Hide file tree
Showing 25 changed files with 205 additions and 216 deletions.
52 changes: 47 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
# CloudStructures
CloudStructures is the [Redis](https://redis.io/) client based on [StackExchange.Redis](https://github.com/StackExchange/StackExchange.Redis). **Now supports .NET Standard!!**
CloudStructures is the [Redis](https://redis.io/) client based on [StackExchange.Redis](https://github.com/StackExchange/StackExchange.Redis).

StackExchange.Redis is very pure and low level library. It's Redis driver like ADO.NET. It's very difficult to use it as raw. CloudStructures provides simple O/R (Object / Redis) mapper like [Dapper](https://github.com/StackExchange/Dapper) for ADO.NET.
StackExchange.Redis is very pure and low level library. It's Redis driver like ADO.NET. It's difficult to use it as raw. CloudStructures provides simple O/R (Object / Redis) mapper like [Dapper](https://github.com/StackExchange/Dapper) for ADO.NET.


[![Releases](https://img.shields.io/github/release/neuecc/CloudStructures.svg)](https://github.com/neuecc/CloudStructures/releases)



# Support framework
- .NET Standard 2.0
- .NET 5+
- .NET Standard 2.0+
- .NET Framework 4.6.1+



Expand Down Expand Up @@ -74,10 +76,50 @@ var result = await redis.GetAsync();


# ValueConverter
If you use this library, you must implement `IValueConverter` to serialize your original class. However, we provides default implementations using [MessagePack for C#](https://github.com/neuecc/MessagePack-CSharp) and [Utf8Json](https://github.com/neuecc/Utf8Json). Unless you pass custom `IValueConverter` to `RedisConnection` ctor, fallback to `Utf8JsonConverter` automatically. If you wanna use MessagePack version, you should install following package.
If you use this library, you *should* implement `IValueConverter` to serialize your original class. Unless you pass custom `IValueConverter` to `RedisConnection` ctor, fallback to `SystemTextJsonConverter` automatically that is default converter we provide.


## How to implement custom `IValueConverter`

```cs
using CloudStructures.Converters;
using Utf8Json;
using Utf8Json.Resolvers;

namespace HowToImplement_CustomValueConverter
{
public sealed class Utf8JsonConverter : IValueConverter
{
public byte[] Serialize<T>(T value)
=> JsonSerializer.Serialize(value, StandardResolver.AllowPrivate);

public T Deserialize<T>(byte[] value)
=> JsonSerializer.Deserialize<T>(value, StandardResolver.AllowPrivate);
}
}
```
PM> Install-Package CloudStructures.Converters.MessagePack

```cs
using CloudStructures.Converters;
using MessagePack;
using MessagePack.Resolvers;

namespace HowToImplement_CustomValueConverter
{
public sealed class MessagePackConverter : IValueConverter
{
private MessagePackSerializerOptions Options { get; }

public MessagePackConverter(MessagePackSerializerOptions options)
=> this.Options = options;

public byte[] Serialize<T>(T value)
=> MessagePackSerializer.Serialize(value, this.Options);

public T Deserialize<T>(byte[] value)
=> MessagePackSerializer.Deserialize<T>(value, this.Options);
}
}
```


Expand Down
1 change: 0 additions & 1 deletion nuget/pack.bat
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
dotnet pack ../src/CloudStructures/CloudStructures.csproj -c Release -o ../nuget/packages
dotnet pack ../src/CloudStructures.Converters.MessagePack/CloudStructures.Converters.MessagePack.csproj -c Release -o ../nuget/packages

This file was deleted.

6 changes: 0 additions & 6 deletions src/CloudStructures.sln
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ VisualStudioVersion = 16.0.31205.134
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CloudStructures", "CloudStructures\CloudStructures.csproj", "{737EFD85-803D-48F6-AFB4-4637773E32A8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CloudStructures.Converters.MessagePack", "CloudStructures.Converters.MessagePack\CloudStructures.Converters.MessagePack.csproj", "{FE910B93-6E35-4FCC-9EAD-A6C4E27D9EF5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -17,10 +15,6 @@ Global
{737EFD85-803D-48F6-AFB4-4637773E32A8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{737EFD85-803D-48F6-AFB4-4637773E32A8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{737EFD85-803D-48F6-AFB4-4637773E32A8}.Release|Any CPU.Build.0 = Release|Any CPU
{FE910B93-6E35-4FCC-9EAD-A6C4E27D9EF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FE910B93-6E35-4FCC-9EAD-A6C4E27D9EF5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FE910B93-6E35-4FCC-9EAD-A6C4E27D9EF5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FE910B93-6E35-4FCC-9EAD-A6C4E27D9EF5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
13 changes: 8 additions & 5 deletions src/CloudStructures/CloudStructures.csproj
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>8.0</LangVersion>
<Nullable>disable</Nullable>
<TargetFrameworks>netstandard2.0;netstandard2.1;net461;net5</TargetFrameworks>
<LangVersion>9.0</LangVersion>
<Nullable>enable</Nullable>
<!-- NuGet -->
<IsPackable>true</IsPackable>
<PackageId>CloudStructures</PackageId>
Expand All @@ -23,8 +23,11 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="StackExchange.Redis" Version="2.0.601" />
<PackageReference Include="Utf8Json" Version="1.3.7" />
<PackageReference Include="StackExchange.Redis" Version="2.2.4" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' != 'net5'">
<PackageReference Include="System.Text.Json" Version="5.0.2" />
</ItemGroup>

</Project>
25 changes: 24 additions & 1 deletion src/CloudStructures/Converters/PrimitiveConverter.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using StackExchange.Redis;
using System;
using StackExchange.Redis;



Expand Down Expand Up @@ -287,4 +288,26 @@ internal sealed class ByteArrayConverter : IRedisValueConverter<byte[]>
public RedisValue Serialize(byte[] value) => value;
public byte[] Deserialize(RedisValue value) => value;
}



/// <summary>
/// Provides <see cref="Memory{byte}"/> conversion function.
/// </summary>
internal sealed class MemoryByteConverter : IRedisValueConverter<Memory<byte>>
{
public RedisValue Serialize(Memory<byte> value) => value;
public Memory<byte> Deserialize(RedisValue value) => (byte[])value;
}



/// <summary>
/// Provides <see cref="ReadOnlyMemory{byte}"/> conversion function.
/// </summary>
internal sealed class ReadOnlyMemoryByteConverter : IRedisValueConverter<ReadOnlyMemory<byte>>
{
public RedisValue Serialize(ReadOnlyMemory<byte> value) => value;
public ReadOnlyMemory<byte> Deserialize(RedisValue value) => value;
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
using MessagePack;
using System.Text.Json;



namespace CloudStructures.Converters
{
/// <summary>
/// Provides value converter using MessagePack for C#.
/// Provides value converter using System.Text.Json.
/// </summary>
public sealed class MessagePackConverter : IValueConverter
public sealed class SystemTextJsonConverter : IValueConverter
{
/// <summary>
/// Serialize value to binary.
Expand All @@ -16,7 +16,7 @@ public sealed class MessagePackConverter : IValueConverter
/// <param name="value"></param>
/// <returns></returns>
public byte[] Serialize<T>(T value)
=> LZ4MessagePackSerializer.Serialize(value);
=> JsonSerializer.SerializeToUtf8Bytes(value);


/// <summary>
Expand All @@ -26,7 +26,6 @@ public byte[] Serialize<T>(T value)
/// <param name="value"></param>
/// <returns></returns>
public T Deserialize<T>(byte[] value)
=> LZ4MessagePackSerializer.Deserialize<T>(value);
=> JsonSerializer.Deserialize<T>(value)!; // forgive
}
}

32 changes: 0 additions & 32 deletions src/CloudStructures/Converters/Utf8JsonConverter.cs

This file was deleted.

16 changes: 9 additions & 7 deletions src/CloudStructures/Converters/ValueConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ internal sealed class ValueConverter
/// Creates instance.
/// </summary>
/// <param name="customConverter"></param>
public ValueConverter(IValueConverter customConverter)
=> this.CustomConverter = customConverter ?? new Utf8JsonConverter(); // fallback
public ValueConverter(IValueConverter? customConverter)
=> this.CustomConverter = customConverter ?? new SystemTextJsonConverter(); // fallback
#endregion


Expand All @@ -39,8 +39,8 @@ public ValueConverter(IValueConverter customConverter)
public RedisValue Serialize<T>(T value)
{
var converter = PrimitiveConverterCache<T>.Converter;
return converter == null
? (RedisValue)this.CustomConverter.Serialize(value)
return converter is null
? this.CustomConverter.Serialize(value)
: converter.Serialize(value);
}

Expand All @@ -54,7 +54,7 @@ public RedisValue Serialize<T>(T value)
public T Deserialize<T>(RedisValue value)
{
var converter = PrimitiveConverterCache<T>.Converter;
return converter == null
return converter is null
? this.CustomConverter.Deserialize<T>(value)
: converter.Deserialize(value);
}
Expand All @@ -70,7 +70,7 @@ private static class PrimitiveConverterCache
/// <summary>
/// Hold type and converter mapping table.
/// </summary>
public static IDictionary<Type, object> Map { get; } = new Dictionary<Type, object>
public static IReadOnlyDictionary<Type, object> Map { get; } = new Dictionary<Type, object>
{
[typeof(bool)] = new BooleanConverter(),
[typeof(bool?)] = new NullableBooleanConverter(),
Expand Down Expand Up @@ -98,6 +98,8 @@ private static class PrimitiveConverterCache
[typeof(double?)] = new NullableDoubleConverter(),
[typeof(string)] = new StringConverter(),
[typeof(byte[])] = new ByteArrayConverter(),
[typeof(Memory<byte>)] = new MemoryByteConverter(),
[typeof(ReadOnlyMemory<byte>)] = new ReadOnlyMemoryByteConverter(),
};
}

Expand All @@ -111,7 +113,7 @@ private static class PrimitiveConverterCache<T>
/// <summary>
/// Gets converter.
/// </summary>
public static IRedisValueConverter<T> Converter { get; }
public static IRedisValueConverter<T>? Converter { get; }


/// <summary>
Expand Down
15 changes: 4 additions & 11 deletions src/CloudStructures/Internals/EnumerableExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,7 @@ internal static class EnumerableExtensions
/// <param name="source"></param>
/// <returns></returns>
public static bool IsEmpty<T>(this IEnumerable<T> source)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
return !source.Any();
}
=> !source.Any();


/// <summary>
Expand All @@ -37,9 +33,6 @@ public static bool IsEmpty<T>(this IEnumerable<T> source)
/// <returns></returns>
public static IEnumerable<TResult> Select<T, TState, TResult>(this IEnumerable<T> source, TState state, Func<T, TState, TResult> selector)
{
if (source == null) throw new ArgumentNullException(nameof(source));
if (selector == null) throw new ArgumentNullException(nameof(selector));

foreach (var x in source)
yield return selector(x, state);
}
Expand All @@ -52,13 +45,13 @@ public static IEnumerable<TResult> Select<T, TState, TResult>(this IEnumerable<T
/// <param name="source"></param>
/// <param name="nullToEmpty">If true, returns empty sequence when source collection is null. If false, throws <see cref="ArgumentNullException"/></param>
/// <returns></returns>
public static IEnumerable<T> Materialize<T>(this IEnumerable<T> source, bool nullToEmpty = true)
public static IEnumerable<T> Materialize<T>(this IEnumerable<T>? source, bool nullToEmpty = true)
{
if (source == null)
if (source is null)
{
if (nullToEmpty)
return Enumerable.Empty<T>();
throw new ArgumentNullException("source is null.");
throw new ArgumentNullException(nameof(source));
}
if (source is ICollection<T>) return source;
if (source is IReadOnlyCollection<T>) return source;
Expand Down
6 changes: 0 additions & 6 deletions src/CloudStructures/Internals/RedisOperationHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ internal static class RedisOperationHelpers
public static async Task ExecuteWithExpiryAsync<TRedis, TArgs>(this TRedis structure, Func<IDatabaseAsync, TArgs, Task> command, TArgs args, TimeSpan? expiry, CommandFlags flags)
where TRedis : IRedisStructure
{
if (structure == null) throw new ArgumentNullException(nameof(structure));
if (command == null) throw new ArgumentNullException(nameof(command));

if (expiry.HasValue)
{
//--- Execute multiple commands in tracsaction
Expand Down Expand Up @@ -60,9 +57,6 @@ public static async Task ExecuteWithExpiryAsync<TRedis, TArgs>(this TRedis struc
public static async Task<TResult> ExecuteWithExpiryAsync<TRedis, TArgs, TResult>(this TRedis structure, Func<IDatabaseAsync, TArgs, Task<TResult>> command, TArgs args, TimeSpan? expiry, CommandFlags flags)
where TRedis : IRedisStructure
{
if (structure == null) throw new ArgumentNullException(nameof(structure));
if (command == null) throw new ArgumentNullException(nameof(command));

if (expiry.HasValue)
{
//--- Execute multiple commands in tracsaction
Expand Down
7 changes: 3 additions & 4 deletions src/CloudStructures/RedisConfig.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using StackExchange.Redis;
using StackExchange.Redis;



Expand Down Expand Up @@ -54,8 +53,8 @@ public RedisConfig(string name, string connectionString, int? database = default
/// <param name="database"></param>
public RedisConfig(string name, ConfigurationOptions options, int? database = default)
{
this.Name = name ?? throw new ArgumentNullException(nameof(name));
this.Options = options ?? throw new ArgumentNullException(nameof(options));
this.Name = name;
this.Options = options;
this.Database = database ?? options.DefaultDatabase;
}
#endregion
Expand Down
Loading

0 comments on commit c576902

Please sign in to comment.