添加excel导出模式!基于配置,string[]自动添加split特性!消除警告,后续再写文档!
example/ExampleApeart.Handler/eventmodels/EventDemoModelHandler.cs
diff --git a/example/ExampleApeart.Handler/eventmodels/EventDemoModelHandler.cs b/example/ExampleApeart.Handler/eventmodels/EventDemoModelHandler.cs
index a2e722b..bc4c2fc 100644
--- a/example/ExampleApeart.Handler/eventmodels/EventDemoModelHandler.cs
+++ b/example/ExampleApeart.Handler/eventmodels/EventDemoModelHandler.cs
@@ -1,6 +1,5 @@
using ExampleApeart.Application.Contracts.eventmodels;
using Microsoft.Extensions.Logging;
-using PasteApeart;
using PasteApeart.Dependency;
using PasteApeart.Handler;
using PasteApeart.Handler.Extensions;
@@ -32,7 +31,10 @@ namespace ExampleApeart.Handler.eventmodels
_channelHelper = channelHelper;
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ public object Result { get; protected set; }
/// <summary>
///
framework/Directory.Build.props
diff --git a/framework/Directory.Build.props b/framework/Directory.Build.props
index b6669d0..b8f4d75 100644
--- a/framework/Directory.Build.props
+++ b/framework/Directory.Build.props
@@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
- <Version>26.10.02</Version>
- <FileVersion>26.10.02</FileVersion>
- <AssemblyVersion>26.10.02</AssemblyVersion>
+ <Version>26.10.04</Version>
+ <FileVersion>26.10.04</FileVersion>
+ <AssemblyVersion>26.10.04</AssemblyVersion>
</PropertyGroup>
</Project>
\ No newline at end of file
framework/PasteApeart.Dependency/IScopedDependency.cs
diff --git a/framework/PasteApeart.Dependency/IScopedDependency.cs b/framework/PasteApeart.Dependency/IScopedDependency.cs
index 50b06ff..fa9765e 100644
--- a/framework/PasteApeart.Dependency/IScopedDependency.cs
+++ b/framework/PasteApeart.Dependency/IScopedDependency.cs
@@ -1,8 +1,14 @@
namespace PasteApeart.Dependency
{
+ /// <summary>
+ /// 会话模式
+ /// </summary>
public interface IScopedDependency
{
}
+ /// <summary>
+ /// 会话模式
+ /// </summary>
public interface IScoped
{
}
framework/PasteApeart.Dependency/ISingletonDependency.cs
diff --git a/framework/PasteApeart.Dependency/ISingletonDependency.cs b/framework/PasteApeart.Dependency/ISingletonDependency.cs
index cb3e1cb..fde0b22 100644
--- a/framework/PasteApeart.Dependency/ISingletonDependency.cs
+++ b/framework/PasteApeart.Dependency/ISingletonDependency.cs
@@ -1,11 +1,17 @@
namespace PasteApeart.Dependency
{
-
+ /// <summary>
+ /// 单例模式
+ /// </summary>
public interface ISingletonDependency
{
}
+
+ /// <summary>
+ /// 单例模式
+ /// </summary>
public interface ISingleton
{
framework/PasteApeart.Dependency/ITransientDependency.cs
diff --git a/framework/PasteApeart.Dependency/ITransientDependency.cs b/framework/PasteApeart.Dependency/ITransientDependency.cs
index 3d754c8..f095ef2 100644
--- a/framework/PasteApeart.Dependency/ITransientDependency.cs
+++ b/framework/PasteApeart.Dependency/ITransientDependency.cs
@@ -1,11 +1,17 @@
namespace PasteApeart.Dependency
{
+ /// <summary>
+ /// 瞬时
+ /// </summary>
public interface ITransientDependency
{
}
+ /// <summary>
+ /// 瞬时
+ /// </summary>
public interface ITransient
{
framework/PasteApeart.Dependency/PasteApeart.Dependency.csproj
diff --git a/framework/PasteApeart.Dependency/PasteApeart.Dependency.csproj b/framework/PasteApeart.Dependency/PasteApeart.Dependency.csproj
index d3dc50e..a0c478a 100644
--- a/framework/PasteApeart.Dependency/PasteApeart.Dependency.csproj
+++ b/framework/PasteApeart.Dependency/PasteApeart.Dependency.csproj
@@ -12,6 +12,7 @@
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
+ <DocumentationFile>PasteApeart.Dependency.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<None Include="readme.md" Pack="true" PackagePath="/" Visible="true" />
framework/PasteApeart.Dependency/PasteApeart.Dependency.xm
diff --git a/framework/PasteApeart.Dependency/PasteApeart.Dependency.xm b/framework/PasteApeart.Dependency/PasteApeart.Dependency.xm
new file mode 100644
index 0000000..a4c4204
--- /dev/null
+++ b/framework/PasteApeart.Dependency/PasteApeart.Dependency.xm
@@ -0,0 +1,64 @@
+<?xml version="1.0"?>
+<doc>
+ <assembly>
+ <name>PasteApeart.Dependency</name>
+ </assembly>
+ <members>
+ <member name="T:PasteApeart.Dependency.AutoDependencyExtensions">
+ <summary>
+ 自动执行注入
+ </summary>
+ </member>
+ <member name="M:PasteApeart.Dependency.AutoDependencyExtensions.AddAutoDependency(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Reflection.Assembly)">
+ <summary>
+ 扫描注入 瞬时 作用域 单例等 ITransient ISingleton IScoped
+ </summary>
+ <param name="services"></param>
+ <param name="assembly"></param>
+ <returns></returns>
+ </member>
+ <member name="T:PasteApeart.Dependency.AutoDependencyInjectionExtensions">
+ <summary>
+ 自动执行注入
+ </summary>
+ </member>
+ <member name="M:PasteApeart.Dependency.AutoDependencyInjectionExtensions.AddAutoDependencyInjection(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Reflection.Assembly)">
+ <summary>
+ 扫描注入 瞬时 作用域 单例等
+ </summary>
+ <param name="services"></param>
+ <param name="assembly"></param>
+ <returns></returns>
+ </member>
+ <member name="T:PasteApeart.Dependency.IScopedDependency">
+ <summary>
+ 会话模式
+ </summary>
+ </member>
+ <member name="T:PasteApeart.Dependency.IScoped">
+ <summary>
+ 会话模式
+ </summary>
+ </member>
+ <member name="T:PasteApeart.Dependency.ISingletonDependency">
+ <summary>
+ 单例模式
+ </summary>
+ </member>
+ <member name="T:PasteApeart.Dependency.ISingleton">
+ <summary>
+ 单例模式
+ </summary>
+ </member>
+ <member name="T:PasteApeart.Dependency.ITransientDependency">
+ <summary>
+ 瞬时
+ </summary>
+ </member>
+ <member name="T:PasteApeart.Dependency.ITransient">
+ <summary>
+ 瞬时
+ </summary>
+ </member>
+ </members>
+</doc>
framework/PasteApeart.Dependency/PasteApeart.Dependency.xml
diff --git a/framework/PasteApeart.Dependency/PasteApeart.Dependency.xml b/framework/PasteApeart.Dependency/PasteApeart.Dependency.xml
new file mode 100644
index 0000000..a4c4204
--- /dev/null
+++ b/framework/PasteApeart.Dependency/PasteApeart.Dependency.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0"?>
+<doc>
+ <assembly>
+ <name>PasteApeart.Dependency</name>
+ </assembly>
+ <members>
+ <member name="T:PasteApeart.Dependency.AutoDependencyExtensions">
+ <summary>
+ 自动执行注入
+ </summary>
+ </member>
+ <member name="M:PasteApeart.Dependency.AutoDependencyExtensions.AddAutoDependency(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Reflection.Assembly)">
+ <summary>
+ 扫描注入 瞬时 作用域 单例等 ITransient ISingleton IScoped
+ </summary>
+ <param name="services"></param>
+ <param name="assembly"></param>
+ <returns></returns>
+ </member>
+ <member name="T:PasteApeart.Dependency.AutoDependencyInjectionExtensions">
+ <summary>
+ 自动执行注入
+ </summary>
+ </member>
+ <member name="M:PasteApeart.Dependency.AutoDependencyInjectionExtensions.AddAutoDependencyInjection(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Reflection.Assembly)">
+ <summary>
+ 扫描注入 瞬时 作用域 单例等
+ </summary>
+ <param name="services"></param>
+ <param name="assembly"></param>
+ <returns></returns>
+ </member>
+ <member name="T:PasteApeart.Dependency.IScopedDependency">
+ <summary>
+ 会话模式
+ </summary>
+ </member>
+ <member name="T:PasteApeart.Dependency.IScoped">
+ <summary>
+ 会话模式
+ </summary>
+ </member>
+ <member name="T:PasteApeart.Dependency.ISingletonDependency">
+ <summary>
+ 单例模式
+ </summary>
+ </member>
+ <member name="T:PasteApeart.Dependency.ISingleton">
+ <summary>
+ 单例模式
+ </summary>
+ </member>
+ <member name="T:PasteApeart.Dependency.ITransientDependency">
+ <summary>
+ 瞬时
+ </summary>
+ </member>
+ <member name="T:PasteApeart.Dependency.ITransient">
+ <summary>
+ 瞬时
+ </summary>
+ </member>
+ </members>
+</doc>
framework/PasteApeart.Handler/JsonConfig.cs
diff --git a/framework/PasteApeart.Handler/JsonConfig.cs b/framework/PasteApeart.Handler/JsonConfig.cs
index b9664e5..503c3b9 100644
--- a/framework/PasteApeart.Handler/JsonConfig.cs
+++ b/framework/PasteApeart.Handler/JsonConfig.cs
@@ -1,4 +1,4 @@
-using System.Globalization;
+using System.Globalization;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;
@@ -90,12 +90,21 @@ namespace PasteApeart.Handler
}
}
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="writer"></param>
+ /// <param name="value"></param>
+ /// <param name="options"></param>
public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
{
writer.WriteStringValue(value);
}
}
+ /// <summary>
+ ///
+ /// </summary>
public class SafeDateTimeConverter : JsonConverter<DateTime>
{
// 支持的常见日期时间格式
@@ -132,6 +141,14 @@ namespace PasteApeart.Handler
}
}
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="reader"></param>
+ /// <param name="typeToConvert"></param>
+ /// <param name="options"></param>
+ /// <returns></returns>
+ /// <exception cref="JsonException"></exception>
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.String)
@@ -175,6 +192,12 @@ namespace PasteApeart.Handler
throw new JsonException($"意外的 token 类型: {reader.TokenType},期望字符串或数字");
}
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="writer"></param>
+ /// <param name="value"></param>
+ /// <param name="options"></param>
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
// 输出使用标准格式
framework/PasteApeart.Handler/PasteApeartHandlerModule.cs
diff --git a/framework/PasteApeart.Handler/PasteApeartHandlerModule.cs b/framework/PasteApeart.Handler/PasteApeartHandlerModule.cs
index cbaa66b..76cf440 100644
--- a/framework/PasteApeart.Handler/PasteApeartHandlerModule.cs
+++ b/framework/PasteApeart.Handler/PasteApeartHandlerModule.cs
@@ -6,7 +6,9 @@ using PasteApeart.Handler.rabbit;
namespace PasteApeart.Handler
{
-
+ /// <summary>
+ ///
+ /// </summary>
public static class PasteApeartHandlerModule
{
framework/PasteApeart.Handler/SerilogCustomHandler.cs
diff --git a/framework/PasteApeart.Handler/SerilogCustomHandler.cs b/framework/PasteApeart.Handler/SerilogCustomHandler.cs
index 91f9be3..269bf0d 100644
--- a/framework/PasteApeart.Handler/SerilogCustomHandler.cs
+++ b/framework/PasteApeart.Handler/SerilogCustomHandler.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -9,6 +9,9 @@ using Serilog.Events;
namespace PasteApeart.Handler
{
+ /// <summary>
+ ///
+ /// </summary>
public class SerilogCustomHandler : ILogEventSink
{
/// <summary>
framework/PasteApeart.Handler/aevent/AbsEventModelExtensions.cs
diff --git a/framework/PasteApeart.Handler/aevent/AbsEventModelExtensions.cs b/framework/PasteApeart.Handler/aevent/AbsEventModelExtensions.cs
index 0423f8b..7145389 100644
--- a/framework/PasteApeart.Handler/aevent/AbsEventModelExtensions.cs
+++ b/framework/PasteApeart.Handler/aevent/AbsEventModelExtensions.cs
@@ -122,9 +122,10 @@ namespace PasteApeart.Handler
}
/// <summary>
- /// 设置下一次执行时间 并压入到队列
+ ///
/// </summary>
/// <param name="input"></param>
+ /// <param name="_channelHelper"></param>
/// <returns></returns>
public static async Task<bool> ToAutoExpireAndSendAsync(this AbsEventModel input, IChannelHelper _channelHelper)
{
framework/PasteApeart.Handler/aevent/IEventHandler.cs
diff --git a/framework/PasteApeart.Handler/aevent/IEventHandler.cs b/framework/PasteApeart.Handler/aevent/IEventHandler.cs
index 7d08208..33d907f 100644
--- a/framework/PasteApeart.Handler/aevent/IEventHandler.cs
+++ b/framework/PasteApeart.Handler/aevent/IEventHandler.cs
@@ -1,9 +1,4 @@
using PasteApeart.Application.Contracts;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace PasteApeart.Handler
{
@@ -20,5 +15,11 @@ namespace PasteApeart.Handler
/// <param name="input"></param>
/// <returns></returns>
Task HandleEventAsync(EventModel input);
+
+ /// <summary>
+ /// 处理器执行结果,供主动调用方读取。
+ /// 系统运行时通常为 null。
+ /// </summary>
+ object Result { get; }
}
}
framework/PasteApeart.Handler/basic/ApeartExtensions.cs
diff --git a/framework/PasteApeart.Handler/basic/ApeartExtensions.cs b/framework/PasteApeart.Handler/basic/ApeartExtensions.cs
index 9954c88..3e7879e 100644
--- a/framework/PasteApeart.Handler/basic/ApeartExtensions.cs
+++ b/framework/PasteApeart.Handler/basic/ApeartExtensions.cs
@@ -93,41 +93,44 @@ namespace PasteApeart.Handler
: source;
}
- //
- // 摘要:
- // Used for paging. Can be used as an alternative to Skip(...).Take(...) chaining.
+ /// <summary>
+ ///
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="query"></param>
+ /// <param name="skipCount"></param>
+ /// <param name="maxResultCount"></param>
+ /// <returns></returns>
public static IQueryable<T> PastePageBy<T>(this IQueryable<T> query, int skipCount, int maxResultCount)
{
Check.PasteNotNull(query, "query");
return query.Skip(skipCount).Take(maxResultCount);
}
- //
- // 摘要:
- // Used for paging. Can be used as an alternative to Skip(...).Take(...) chaining.
+ /// <summary>
+ ///
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <typeparam name="TQueryable"></typeparam>
+ /// <param name="query"></param>
+ /// <param name="skipCount"></param>
+ /// <param name="maxResultCount"></param>
+ /// <returns></returns>
public static TQueryable PastePageBy<T, TQueryable>(this TQueryable query, int skipCount, int maxResultCount) where TQueryable : IQueryable<T>
{
Check.PasteNotNull(query, "query");
return (TQueryable)query.Skip(skipCount).Take(maxResultCount);
}
- //
- // 摘要:
- // Filters a System.Linq.IQueryable`1 by given predicate if given condition is true.
- //
- //
- // 参数:
- // query:
- // Queryable to apply filtering
- //
- // condition:
- // A boolean value
- //
- // predicate:
- // Predicate to filter the query
- //
- // 返回结果:
- // Filtered or not filtered query based on condition
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="query"></param>
+ /// <param name="condition"></param>
+ /// <param name="predicate"></param>
+ /// <returns></returns>
public static IQueryable<T> PasteWhereIf<T>(this IQueryable<T> query, bool condition, Expression<Func<T, bool>> predicate)
{
Check.PasteNotNull(query, "query");
@@ -139,23 +142,16 @@ namespace PasteApeart.Handler
return query.Where(predicate);
}
- //
- // 摘要:
- // Filters a System.Linq.IQueryable`1 by given predicate if given condition is true.
- //
- //
- // 参数:
- // query:
- // Queryable to apply filtering
- //
- // condition:
- // A boolean value
- //
- // predicate:
- // Predicate to filter the query
- //
- // 返回结果:
- // Filtered or not filtered query based on condition
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <typeparam name="TQueryable"></typeparam>
+ /// <param name="query"></param>
+ /// <param name="condition"></param>
+ /// <param name="predicate"></param>
+ /// <returns></returns>
public static TQueryable PasteWhereIf<T, TQueryable>(this TQueryable query, bool condition, Expression<Func<T, bool>> predicate) where TQueryable : IQueryable<T>
{
Check.PasteNotNull(query, "query");
@@ -167,23 +163,15 @@ namespace PasteApeart.Handler
return (TQueryable)query.Where(predicate);
}
- //
- // 摘要:
- // Filters a System.Linq.IQueryable`1 by given predicate if given condition is true.
- //
- //
- // 参数:
- // query:
- // Queryable to apply filtering
- //
- // condition:
- // A boolean value
- //
- // predicate:
- // Predicate to filter the query
- //
- // 返回结果:
- // Filtered or not filtered query based on condition
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="query"></param>
+ /// <param name="condition"></param>
+ /// <param name="predicate"></param>
+ /// <returns></returns>
public static IQueryable<T> PasteWhereIf<T>(this IQueryable<T> query, bool condition, Expression<Func<T, int, bool>> predicate)
{
Check.PasteNotNull(query, "query");
@@ -195,23 +183,16 @@ namespace PasteApeart.Handler
return query.Where(predicate);
}
- //
- // 摘要:
- // Filters a System.Linq.IQueryable`1 by given predicate if given condition is true.
- //
- //
- // 参数:
- // query:
- // Queryable to apply filtering
- //
- // condition:
- // A boolean value
- //
- // predicate:
- // Predicate to filter the query
- //
- // 返回结果:
- // Filtered or not filtered query based on condition
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <typeparam name="TQueryable"></typeparam>
+ /// <param name="query"></param>
+ /// <param name="condition"></param>
+ /// <param name="predicate"></param>
+ /// <returns></returns>
public static TQueryable PasteWhereIf<T, TQueryable>(this TQueryable query, bool condition, Expression<Func<T, int, bool>> predicate) where TQueryable : IQueryable<T>
{
Check.PasteNotNull(query, "query");
framework/PasteApeart.Handler/cache/CacheHandler.cs
diff --git a/framework/PasteApeart.Handler/cache/CacheHandler.cs b/framework/PasteApeart.Handler/cache/CacheHandler.cs
index fdd5e3e..a85b569 100644
--- a/framework/PasteApeart.Handler/cache/CacheHandler.cs
+++ b/framework/PasteApeart.Handler/cache/CacheHandler.cs
@@ -17,7 +17,6 @@ namespace PasteApeart.Handler.cache
/// </summary>
/// <param name="serviceProvider"></param>
/// <param name="cache"></param>
- /// <param name="map"></param>
public CacheHandler(DbContext serviceProvider, IAppCache cache)
{
_dbContext = serviceProvider;
framework/PasteApeart.Handler/cache/ICacheHandler.cs
diff --git a/framework/PasteApeart.Handler/cache/ICacheHandler.cs b/framework/PasteApeart.Handler/cache/ICacheHandler.cs
index 388d2b4..f98205e 100644
--- a/framework/PasteApeart.Handler/cache/ICacheHandler.cs
+++ b/framework/PasteApeart.Handler/cache/ICacheHandler.cs
@@ -1,6 +1,9 @@
namespace PasteApeart.Handler.cache
{
+ /// <summary>
+ ///
+ /// </summary>
public interface ICacheHandler
{
/// <summary>
framework/PasteApeart.Handler/common/ChannelHelper.cs
diff --git a/framework/PasteApeart.Handler/common/ChannelHelper.cs b/framework/PasteApeart.Handler/common/ChannelHelper.cs
index 608be0f..62267aa 100644
--- a/framework/PasteApeart.Handler/common/ChannelHelper.cs
+++ b/framework/PasteApeart.Handler/common/ChannelHelper.cs
@@ -139,6 +139,7 @@ namespace PasteApeart.Handler
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="input"></param>
+ /// <param name="id"></param>
/// <returns></returns>
[Obsolete("use WriteAutoQueueAsync before new MutexKey")]
public async Task WriteMutexMQAsync<T>(T input, object id) where T : IEventModel
framework/PasteApeart.Handler/common/EventActionHandler.cs
diff --git a/framework/PasteApeart.Handler/common/EventActionHandler.cs b/framework/PasteApeart.Handler/common/EventActionHandler.cs
index f9782a2..b83a5d4 100644
--- a/framework/PasteApeart.Handler/common/EventActionHandler.cs
+++ b/framework/PasteApeart.Handler/common/EventActionHandler.cs
@@ -25,6 +25,7 @@ namespace PasteApeart.Handler
/// <param name="logger"></param>
/// <param name="serviceProvider"></param>
/// <param name="channelHelper"></param>
+ /// <param name="dtoTypes"></param>
public EventActionHandler(ILogger<EventActionHandler> logger, IServiceProvider serviceProvider, IChannelHelper channelHelper, Type[] dtoTypes = null)
{
_logger = logger;
@@ -59,7 +60,7 @@ namespace PasteApeart.Handler
return;
}
- await ActionAsync(msg, _dtoTypeArray);
+ await ActionReturnResultAsync(msg, _dtoTypeArray);
}
/// <summary>
@@ -74,7 +75,45 @@ namespace PasteApeart.Handler
{
return;
}
- await ActionAsync(msg, types);
+ await ActionReturnResultAsync(msg, types);
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="msg"></param>
+ /// <param name="methodName"></param>
+ /// <returns></returns>
+ public async Task<object> ActionResultAsync(string msg, string methodName = "HandleEventAsync")
+ {
+ if (string.IsNullOrWhiteSpace(msg))
+ {
+ return null;
+ }
+
+ if (_dtoTypeArray?.Any() != true)
+ {
+ _logger.LogError("ActionMessageAsync 的string模式下,构造函数的dtoTypes是必传的,表示EventModel所在程序集的类型集合");
+ return null;
+ }
+
+ return await ActionReturnResultAsync(msg, _dtoTypeArray, methodName);
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="msg"></param>
+ /// <param name="types"></param>
+ /// <param name="methodName"></param>
+ /// <returns></returns>
+ public async Task<object> ActionResultAsync(string msg, Type[] types, string methodName = "HandleEventAsync")
+ {
+ if (string.IsNullOrWhiteSpace(msg))
+ {
+ return null;
+ }
+ return await ActionReturnResultAsync(msg, types, methodName);
}
/// <summary>
@@ -191,6 +230,132 @@ namespace PasteApeart.Handler
}
}
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="msg"></param>
+ /// <param name="types"></param>
+ /// <param name="methodName"></param>
+ /// <returns></returns>
+ private async Task<object> ActionReturnResultAsync(string msg, Type[] types, string methodName = "HandleEventAsync")
+ {
+ object input = null;
+ object handler = null;
+ try
+ {
+ // 1. 只反序列化一次,使用 System.Text.Json 性能更好
+ using var jsonDoc = JsonDocument.Parse(msg);
+ var root = jsonDoc.RootElement;
+ JsonElement eventNameProperty;
+ // 使用不区分大小写的匹配,更健壮
+ if (!root.TryGetProperty("eventName", out eventNameProperty))
+ {
+ root.TryGetProperty("EventName", out eventNameProperty);
+ }
+ // 获取字符串值并验证
+ string eventName = eventNameProperty.GetString();
+ if (string.IsNullOrEmpty(eventName))
+ {
+ _logger.LogError($"EventName 字段值为空: {msg}");
+ return null;
+ }
+ // 2. 获取事件类型(带缓存)
+ var modelType = _eventTypeCache.GetOrAdd(eventName, name =>
+ {
+ return types.FirstOrDefault(x => x.Name == name);
+ });
+ if (modelType == null)
+ {
+ _logger.LogError($"未找到事件类型: {eventName}");
+ return null;
+ }
+ // 3. 反序列化为具体类型
+ input = JsonSerializer.Deserialize(msg, modelType, JsonConfig.Options);
+ if (input == null)
+ {
+ _logger.LogError($"无法将消息反序列化为类型 {eventName}: {msg}");
+ return null;
+ }
+ using var scope = _serviceProvider.CreateScope();
+ if (input is IEventModel tryModel)
+ {
+ if (tryModel.ExpireSecond > 0)
+ {
+ await _channelHelper.WriteAutoQueueAsync(tryModel);
+ return null;
+ }
+ }
+ // 4. 获取处理器信息(带缓存)
+ var (handlerType, handleMethod) = _handlerCache.GetOrAdd(modelType, type =>
+ {
+ var hType = typeof(IEventHandler<>).MakeGenericType(type);
+ var method = hType.GetMethod(methodName);
+ return (hType, method);
+ });
+ if (handleMethod == null)
+ {
+ _logger.LogError($"处理器 {handlerType.Name} 没有 {methodName} 方法");
+ return null;
+ }
+ handler = scope.ServiceProvider.GetRequiredService(handlerType);
+ if (handler == null)
+ {
+ _logger.LogError($"没有找到 {eventName} 的 IEventHandler 实现");
+ return null;
+ }
+ try
+ {
+ // 5. 执行处理
+ var task = handleMethod.Invoke(handler, new[] { input }) as Task;
+ if (task != null)
+ {
+ await task;
+ //var type = task.GetType();
+ //if (type.IsGenericType)
+ //{
+ // return type.GetProperty("Result")?.GetValue(task);
+ //}
+ //return null;
+ // 从 handler 实例上读 Result 属性(而不是从 Task<T> 里读)
+ var resultProp = handlerType.GetProperty("Result");
+ return resultProp?.GetValue(handler);
+ }
+ else
+ {
+ _logger.LogError($"无法调用 {eventName} 的处理方法");
+ }
+ }
+ catch (Exception handlerExl)
+ {
+ _logger.LogException(handlerExl);
+ }
+ finally
+ {
+ try
+ {
+ if (handler is IDisposable disposable)
+ {
+ disposable.Dispose();
+ }
+ if (handler is IAsyncDisposable disposable1)
+ {
+ await disposable1.DisposeAsync();
+ }
+ }
+ catch (Exception exlDisposable)
+ {
+ _logger.LogException(exlDisposable);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogException(ex);
+ }
+ return null;
+ }
+
+
private readonly ConcurrentDictionary<Type, Type> _eventHandlerCache = new();
private readonly ConcurrentDictionary<Type, MethodInfo> _handleMethodCache = new();
framework/PasteApeart.Handler/common/IChannelHelper.cs
diff --git a/framework/PasteApeart.Handler/common/IChannelHelper.cs b/framework/PasteApeart.Handler/common/IChannelHelper.cs
index edcd0c6..c6cab3d 100644
--- a/framework/PasteApeart.Handler/common/IChannelHelper.cs
+++ b/framework/PasteApeart.Handler/common/IChannelHelper.cs
@@ -3,6 +3,9 @@ using System.Threading.Channels;
namespace PasteApeart.Handler
{
+ /// <summary>
+ ///
+ /// </summary>
public interface IChannelHelper
{
/// <summary>
framework/PasteApeart.Handler/common/IEventActionHandler.cs
diff --git a/framework/PasteApeart.Handler/common/IEventActionHandler.cs b/framework/PasteApeart.Handler/common/IEventActionHandler.cs
index 4130c97..46da988 100644
--- a/framework/PasteApeart.Handler/common/IEventActionHandler.cs
+++ b/framework/PasteApeart.Handler/common/IEventActionHandler.cs
@@ -2,6 +2,9 @@ using PasteApeart.Application.Contracts;
namespace PasteApeart.Handler
{
+ /// <summary>
+ ///
+ /// </summary>
public interface IEventActionHandler
{
/// <summary>
@@ -30,16 +33,33 @@ namespace PasteApeart.Handler
/// <summary>
/// 一般用于本地的Channel模式
/// </summary>
- /// <param name="read"></param>
+ /// <param name="msg"></param>
/// <returns></returns>
Task ActionMessageAsync(IEventModel msg);
/// <summary>
///
/// </summary>
- /// <param name="read"></param>
+ /// <param name="msg"></param>
/// <returns></returns>
[Obsolete("use ActionMessageAsync")]
Task HanlderEventMessage(IEventModel msg);
+
+ /// <summary>
+ /// 有返回值的,自定义执行函数 一般用于事件控制台
+ /// </summary>
+ /// <param name="msg"></param>
+ /// <param name="methodName"></param>
+ /// <returns></returns>
+ Task<object> ActionResultAsync(string msg, string methodName = "HandleEventAsync");
+
+ /// <summary>
+ /// 有返回值的,自定义执行函数 一般用于事件控制台
+ /// </summary>
+ /// <param name="msg"></param>
+ /// <param name="types"></param>
+ /// <param name="methodName"></param>
+ /// <returns></returns>
+ Task<object> ActionResultAsync(string msg, Type[] types, string methodName = "HandleEventAsync");
}
}
\ No newline at end of file
framework/PasteApeart.Handler/common/ILevelHandler.cs
diff --git a/framework/PasteApeart.Handler/common/ILevelHandler.cs b/framework/PasteApeart.Handler/common/ILevelHandler.cs
index 07394d1..9da0d24 100644
--- a/framework/PasteApeart.Handler/common/ILevelHandler.cs
+++ b/framework/PasteApeart.Handler/common/ILevelHandler.cs
@@ -2,11 +2,44 @@ using PasteApeart.Domain.Entity;
namespace PasteApeart.Handler.Level
{
+ /// <summary>
+ ///
+ /// </summary>
public interface ILevelHandler
{
+ /// <summary>
+ ///
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <typeparam name="Tkey"></typeparam>
+ /// <param name="info"></param>
+ /// <returns></returns>
Task AfterAddAsync<T, Tkey>(ILevelEntity<Tkey> info) where T : class, ILevelEntity<Tkey>;
+ /// <summary>
+ ///
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <typeparam name="Tkey"></typeparam>
+ /// <param name="info"></param>
+ /// <param name="oldFatherStr"></param>
+ /// <param name="oldLevel"></param>
+ /// <returns></returns>
Task AfterUpdateAsync<T, Tkey>(ILevelEntity<Tkey> info, string oldFatherStr, int oldLevel) where T : class, ILevelEntity<Tkey>;
+ /// <summary>
+ ///
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <typeparam name="Tkey"></typeparam>
+ /// <param name="entities"></param>
void AllResortByFatherIdAndSort<T, Tkey>(List<T> entities) where T : ILevelEntity<Tkey>;
+ /// <summary>
+ ///
+ /// </summary>
+ /// <typeparam name="Tkey"></typeparam>
+ /// <param name="TableName"></param>
+ /// <param name="input"></param>
+ /// <param name="step"></param>
+ /// <returns></returns>
Task AutoSort<Tkey>(string TableName, ILevelEntity<Tkey> input, int step = 10);
}
}
\ No newline at end of file
framework/PasteApeart.Handler/common/LevelHandler.cs
diff --git a/framework/PasteApeart.Handler/common/LevelHandler.cs b/framework/PasteApeart.Handler/common/LevelHandler.cs
index 84c1d90..9bf163d 100644
--- a/framework/PasteApeart.Handler/common/LevelHandler.cs
+++ b/framework/PasteApeart.Handler/common/LevelHandler.cs
@@ -34,9 +34,10 @@ namespace PasteApeart.Handler.Level
/// <summary>
- /// 新增后调用,用于自动处理关系链
+ ///
/// </summary>
/// <typeparam name="T"></typeparam>
+ /// <typeparam name="Tkey"></typeparam>
/// <param name="info"></param>
/// <returns></returns>
public async Task AfterAddAsync<T, Tkey>(ILevelEntity<Tkey> info) where T : class, ILevelEntity<Tkey>
@@ -89,10 +90,12 @@ namespace PasteApeart.Handler.Level
///
/// </summary>
/// <typeparam name="T"></typeparam>
+ /// <typeparam name="Tkey"></typeparam>
/// <param name="info"></param>
/// <param name="oldFatherStr"></param>
/// <param name="oldLevel"></param>
/// <returns></returns>
+ /// <exception cref="Exception"></exception>
public async Task AfterUpdateAsync<T, Tkey>(ILevelEntity<Tkey> info, string oldFatherStr, int oldLevel) where T : class, ILevelEntity<Tkey>
{
//IQueryable<ILevelEntity> dbSet = null;
@@ -161,11 +164,12 @@ namespace PasteApeart.Handler.Level
/// <summary>
- /// 基于FatherId和Sort重新计算Level SortStr FatherStr
+ ///
/// </summary>
/// <typeparam name="T"></typeparam>
+ /// <typeparam name="Tkey"></typeparam>
/// <param name="entities"></param>
- /// <returns></returns>
+ /// <exception cref="Exception"></exception>
public void AllResortByFatherIdAndSort<T, Tkey>(List<T> entities) where T : ILevelEntity<Tkey>
{
if (entities == null || entities.Count == 0) return;
@@ -194,6 +198,7 @@ namespace PasteApeart.Handler.Level
///
/// </summary>
/// <typeparam name="T"></typeparam>
+ /// <typeparam name="Tkey"></typeparam>
/// <param name="node"></param>
/// <param name="entities"></param>
/// <exception cref="Exception"></exception>
framework/PasteApeart.Handler/extensions/ApeartExtensions.cs
diff --git a/framework/PasteApeart.Handler/extensions/ApeartExtensions.cs b/framework/PasteApeart.Handler/extensions/ApeartExtensions.cs
index 97ef783..d19c1af 100644
--- a/framework/PasteApeart.Handler/extensions/ApeartExtensions.cs
+++ b/framework/PasteApeart.Handler/extensions/ApeartExtensions.cs
@@ -90,41 +90,44 @@ namespace PasteApeart.Handler.Extensions
: source;
}
- //
- // 摘要:
- // Used for paging. Can be used as an alternative to Skip(...).Take(...) chaining.
+ /// <summary>
+ ///
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="query"></param>
+ /// <param name="skipCount"></param>
+ /// <param name="maxResultCount"></param>
+ /// <returns></returns>
public static IQueryable<T> PageBy<T>(this IQueryable<T> query, int skipCount, int maxResultCount)
{
Check.NotNull(query, "query");
return query.Skip(skipCount).Take(maxResultCount);
}
- //
- // 摘要:
- // Used for paging. Can be used as an alternative to Skip(...).Take(...) chaining.
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <typeparam name="TQueryable"></typeparam>
+ /// <param name="query"></param>
+ /// <param name="skipCount"></param>
+ /// <param name="maxResultCount"></param>
+ /// <returns></returns>
public static TQueryable PageBy<T, TQueryable>(this TQueryable query, int skipCount, int maxResultCount) where TQueryable : IQueryable<T>
{
Check.NotNull(query, "query");
return (TQueryable)query.Skip(skipCount).Take(maxResultCount);
}
- //
- // 摘要:
- // Filters a System.Linq.IQueryable`1 by given predicate if given condition is true.
- //
- //
- // 参数:
- // query:
- // Queryable to apply filtering
- //
- // condition:
- // A boolean value
- //
- // predicate:
- // Predicate to filter the query
- //
- // 返回结果:
- // Filtered or not filtered query based on condition
+ /// <summary>
+ ///
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="query"></param>
+ /// <param name="condition"></param>
+ /// <param name="predicate"></param>
+ /// <returns></returns>
public static IQueryable<T> WhereIf<T>(this IQueryable<T> query, bool condition, Expression<Func<T, bool>> predicate)
{
Check.NotNull(query, "query");
@@ -136,23 +139,15 @@ namespace PasteApeart.Handler.Extensions
return query.Where(predicate);
}
- //
- // 摘要:
- // Filters a System.Linq.IQueryable`1 by given predicate if given condition is true.
- //
- //
- // 参数:
- // query:
- // Queryable to apply filtering
- //
- // condition:
- // A boolean value
- //
- // predicate:
- // Predicate to filter the query
- //
- // 返回结果:
- // Filtered or not filtered query based on condition
+ /// <summary>
+ ///
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <typeparam name="TQueryable"></typeparam>
+ /// <param name="query"></param>
+ /// <param name="condition"></param>
+ /// <param name="predicate"></param>
+ /// <returns></returns>
public static TQueryable WhereIf<T, TQueryable>(this TQueryable query, bool condition, Expression<Func<T, bool>> predicate) where TQueryable : IQueryable<T>
{
Check.NotNull(query, "query");
@@ -164,23 +159,14 @@ namespace PasteApeart.Handler.Extensions
return (TQueryable)query.Where(predicate);
}
- //
- // 摘要:
- // Filters a System.Linq.IQueryable`1 by given predicate if given condition is true.
- //
- //
- // 参数:
- // query:
- // Queryable to apply filtering
- //
- // condition:
- // A boolean value
- //
- // predicate:
- // Predicate to filter the query
- //
- // 返回结果:
- // Filtered or not filtered query based on condition
+ /// <summary>
+ ///
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="query"></param>
+ /// <param name="condition"></param>
+ /// <param name="predicate"></param>
+ /// <returns></returns>
public static IQueryable<T> WhereIf<T>(this IQueryable<T> query, bool condition, Expression<Func<T, int, bool>> predicate)
{
Check.NotNull(query, "query");
@@ -192,23 +178,15 @@ namespace PasteApeart.Handler.Extensions
return query.Where(predicate);
}
- //
- // 摘要:
- // Filters a System.Linq.IQueryable`1 by given predicate if given condition is true.
- //
- //
- // 参数:
- // query:
- // Queryable to apply filtering
- //
- // condition:
- // A boolean value
- //
- // predicate:
- // Predicate to filter the query
- //
- // 返回结果:
- // Filtered or not filtered query based on condition
+ /// <summary>
+ ///
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <typeparam name="TQueryable"></typeparam>
+ /// <param name="query"></param>
+ /// <param name="condition"></param>
+ /// <param name="predicate"></param>
+ /// <returns></returns>
public static TQueryable WhereIf<T, TQueryable>(this TQueryable query, bool condition, Expression<Func<T, int, bool>> predicate) where TQueryable : IQueryable<T>
{
Check.NotNull(query, "query");
framework/PasteApeart.Handler/rabbit/IRabbitMQProducer.cs
diff --git a/framework/PasteApeart.Handler/rabbit/IRabbitMQProducer.cs b/framework/PasteApeart.Handler/rabbit/IRabbitMQProducer.cs
index e40b83d..e4b63a8 100644
--- a/framework/PasteApeart.Handler/rabbit/IRabbitMQProducer.cs
+++ b/framework/PasteApeart.Handler/rabbit/IRabbitMQProducer.cs
@@ -1,10 +1,32 @@
namespace PasteApeart.Handler.rabbit
{
+ /// <summary>
+ ///
+ /// </summary>
public interface IRabbitMQProducer
{
+ /// <summary>
+ ///
+ /// </summary>
void Close();
+ /// <summary>
+ ///
+ /// </summary>
void Dispose();
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="exchange"></param>
+ /// <param name="message"></param>
+ /// <param name="routingkey"></param>
+ /// <param name="maxRetries"></param>
+ /// <returns></returns>
Task<bool> SendWithRetryAsync(string exchange, string message, string routingkey, int maxRetries = 3);
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="message"></param>
+ /// <returns></returns>
Task WriteSubscribeAsync(string message);
}
}
\ No newline at end of file
framework/PasteApeart.Handler/rabbit/IRabbitMultiConsumerHandler.cs
diff --git a/framework/PasteApeart.Handler/rabbit/IRabbitMultiConsumerHandler.cs b/framework/PasteApeart.Handler/rabbit/IRabbitMultiConsumerHandler.cs
index 7b53e44..2dca042 100644
--- a/framework/PasteApeart.Handler/rabbit/IRabbitMultiConsumerHandler.cs
+++ b/framework/PasteApeart.Handler/rabbit/IRabbitMultiConsumerHandler.cs
@@ -1,9 +1,24 @@
namespace PasteApeart.Handler.rabbit
{
+ /// <summary>
+ ///
+ /// </summary>
public interface IRabbitMultiConsumerHandler
{
+ /// <summary>
+ ///
+ /// </summary>
+ /// <returns></returns>
ValueTask DisposeAsync();
+ /// <summary>
+ ///
+ /// </summary>
+ /// <returns></returns>
Task InitAsync();
+ /// <summary>
+ ///
+ /// </summary>
+ /// <returns></returns>
Task ShutdownAsync();
}
}
\ No newline at end of file
framework/PasteApeart.Handler/rabbit/RabbitMQProducer.cs
diff --git a/framework/PasteApeart.Handler/rabbit/RabbitMQProducer.cs b/framework/PasteApeart.Handler/rabbit/RabbitMQProducer.cs
index 486d656..deb18c1 100644
--- a/framework/PasteApeart.Handler/rabbit/RabbitMQProducer.cs
+++ b/framework/PasteApeart.Handler/rabbit/RabbitMQProducer.cs
@@ -37,9 +37,10 @@ namespace PasteApeart.Handler.rabbit
private readonly ILogger<RabbitMQProducer> _logger;
/// <summary>
- /// Constructor for RabbitMqClient
+ ///
/// </summary>
- /// <param name="config">mandatory</param>
+ /// <param name="config"></param>
+ /// <param name="logger"></param>
public RabbitMQProducer(IOptions<RabbitConfig> config, ILogger<RabbitMQProducer> logger)
{
_logger = logger;
framework/PasteApeart.Handler/redis/HashKeyValue.cs
diff --git a/framework/PasteApeart.Handler/redis/HashKeyValue.cs b/framework/PasteApeart.Handler/redis/HashKeyValue.cs
index 93beaee..0c3540d 100644
--- a/framework/PasteApeart.Handler/redis/HashKeyValue.cs
+++ b/framework/PasteApeart.Handler/redis/HashKeyValue.cs
@@ -1,8 +1,18 @@
namespace PasteApeart.Handler.redis
{
+ /// <summary>
+ ///
+ /// </summary>
public class HashKeyValue
{
+ /// <summary>
+ ///
+ /// </summary>
public string Key { get; set; }
+
+ /// <summary>
+ ///
+ /// </summary>
public string Value { get; set; }
}
}
framework/PasteApeart.Handler/redis/IAppCache.cs
diff --git a/framework/PasteApeart.Handler/redis/IAppCache.cs b/framework/PasteApeart.Handler/redis/IAppCache.cs
index 8942cb7..a58452b 100644
--- a/framework/PasteApeart.Handler/redis/IAppCache.cs
+++ b/framework/PasteApeart.Handler/redis/IAppCache.cs
@@ -139,7 +139,10 @@ namespace PasteApeart.Handler.redis
///
/// </summary>
/// <param name="key"></param>
- /// <param name="vals"></param>
+ /// <param name="field"></param>
+ /// <param name="value"></param>
+ /// <param name="isnum"></param>
+ /// <returns></returns>
Task HashSetAsync(string key, string field, RedisValue value, bool isnum = false);
/// <summary>
@@ -148,28 +151,29 @@ namespace PasteApeart.Handler.redis
/// <returns></returns>
string Print();
- /// <summary>
- ///
- /// </summary>
- /// <param name="key"></param>
- /// <param name="field"></param>
- /// <param name="num"></param>
- /// <returns></returns>
- Task<long> HashIncrementAsync(string key, string field, long num = 1);
+ ///// <summary>
+ /////
+ ///// </summary>
+ ///// <param name="key"></param>
+ ///// <param name="field"></param>
+ ///// <param name="num"></param>
+ ///// <returns></returns>
+ //Task<long> HashIncrementAsync(string key, string field, long num = 1);
- /// <summary>
- ///
- /// </summary>
- /// <param name="key"></param>
- /// <param name="field"></param>
- /// <returns></returns>
- Task<long> HashDecrementAsync(string key, string field);
+ ///// <summary>
+ /////
+ ///// </summary>
+ ///// <param name="key"></param>
+ ///// <param name="field"></param>
+ ///// <returns></returns>
+ //Task<long> HashDecrementAsync(string key, string field);
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <param name="field"></param>
+ /// <param name="isNum"></param>
/// <returns></returns>
Task<int> HashGetIntFieldAsync(string key, string field, bool isNum = false);
@@ -178,6 +182,7 @@ namespace PasteApeart.Handler.redis
/// </summary>
/// <param name="key"></param>
/// <param name="field"></param>
+ /// <param name="isNum"></param>
/// <returns></returns>
Task<long> HashGetLongFieldAsync(string key, string field, bool isNum = false);
@@ -223,6 +228,7 @@ namespace PasteApeart.Handler.redis
/// <param name="pattern"></param>
/// <param name="page"></param>
/// <param name="size"></param>
+ /// <param name="isincom"></param>
/// <returns></returns>
Task<List<HashEntry>> HashScanAsync(string key, string pattern, int page, int size, bool isincom = false);
@@ -231,6 +237,7 @@ namespace PasteApeart.Handler.redis
/// </summary>
/// <param name="key"></param>
/// <param name="sunkey"></param>
+ /// <param name="isnum"></param>
/// <returns></returns>
Task<string> HashGetAsync(string key, string sunkey, bool isnum = false);
@@ -239,6 +246,7 @@ namespace PasteApeart.Handler.redis
/// </summary>
/// <param name="key"></param>
/// <param name="fields"></param>
+ /// <param name="isinnum"></param>
/// <returns></returns>
Task<RedisValue[]> HashGetAsync(string key, RedisValue[] fields, bool isinnum = false);
@@ -292,7 +300,6 @@ namespace PasteApeart.Handler.redis
/// </summary>
/// <param name="key"></param>
/// <param name="field"></param>
- /// <param name="value"></param>
/// <returns></returns>
Task<bool> SortedSetRemoveAsync(string key, string field);
@@ -547,6 +554,21 @@ namespace PasteApeart.Handler.redis
/// <param name="key"></param>
/// <returns></returns>
List<HashKeyValue> HashGetAll(string key);
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <returns></returns>
+ HashEntry[] HashGetAllEntry(string key);
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <returns></returns>
+ Task<HashEntry[]> HashGetAllEntryAsync(string key);
+
///// <summary>
/////
///// </summary>
@@ -627,13 +649,13 @@ namespace PasteApeart.Handler.redis
/// <returns></returns>
string HashGet(string key, string sunkey);
- /// <summary>
- ///
- /// </summary>
- /// <param name="key"></param>
- /// <param name="sunkey"></param>
- /// <returns></returns>
- Task<string> HashGetAsync(string key, string sunkey);
+ ///// <summary>
+ /////
+ ///// </summary>
+ ///// <param name="key"></param>
+ ///// <param name="sunkey"></param>
+ ///// <returns></returns>
+ //Task<string> HashGetAsync(string key, string sunkey);
/// <summary>
/// 随机从Hash中获取一个
@@ -649,13 +671,13 @@ namespace PasteApeart.Handler.redis
- /// <summary>
- /// 添加某一个数据
- /// </summary>
- /// <param name="key"></param>
- /// <param name="felid"></param>
- /// <param name="num"></param>
- Task HashIncrementAsync(string key, string felid, int num = 1);
+ ///// <summary>
+ ///// 添加某一个数据
+ ///// </summary>
+ ///// <param name="key"></param>
+ ///// <param name="felid"></param>
+ ///// <param name="num"></param>
+ //Task HashIncrementAsync(string key, string felid, int num = 1);
/// <summary>
///
framework/PasteApeart.Handler/redis/MemoryClient.bakup.cs
diff --git a/framework/PasteApeart.Handler/redis/MemoryClient.bakup.cs b/framework/PasteApeart.Handler/redis/MemoryClient.bakup.cs
new file mode 100644
index 0000000..c57bdf3
--- /dev/null
+++ b/framework/PasteApeart.Handler/redis/MemoryClient.bakup.cs
@@ -0,0 +1,1620 @@
+//using Microsoft.Extensions.Caching.Memory;
+//using StackExchange.Redis;
+//using System.Collections.Concurrent;
+//using System.Text;
+//using System.Text.Json;
+
+//namespace PasteApeart.Handler.redis
+//{
+// /// <summary>
+// /// 本地缓存
+// /// </summary>
+// public class MemoryClient : IAppCache
+// {
+// private readonly IMemoryCache _memoryCache;
+
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="memoryCache"></param>
+// public MemoryClient(IMemoryCache memoryCache)
+// {
+// _memoryCache = memoryCache;
+// key_hash_set = new ConcurrentDictionary<string, ConcurrentDictionary<string, string>>();
+// key_hash_num = new ConcurrentDictionary<string, ConcurrentDictionary<string, long>>();
+// }
+
+// ///// <summary>
+// /////
+// ///// </summary>
+// //private ConcurrentDictionary<string, string> key_val;
+
+// ///// <summary>
+// /////
+// ///// </summary>
+// //private ConcurrentDictionary<string, List<SortScore>> key_sort_set;
+
+// /// <summary>
+// ///
+// /// </summary>
+// private ConcurrentDictionary<string, ConcurrentDictionary<string, string>> key_hash_set;
+
+// /// <summary>
+// ///
+// /// </summary>
+// private ConcurrentDictionary<string, ConcurrentDictionary<string, long>> key_hash_num;
+
+// public bool IsRedis { get => false; }
+
+// public bool Delete(string key)
+// {
+// _memoryCache.Remove(key);
+// return true;
+// }
+
+// /// <summary>
+// /// error
+// /// </summary>
+// /// <param name="key"></param>
+// /// <returns></returns>
+// public Task<bool> DeleteAsync(string key)
+// {
+// return Task.Run<bool>(() =>
+// {
+// return Delete(key);
+// });
+// }
+
+// public bool Exists(string key)
+// {
+// return _memoryCache.TryGetValue(key, out var val);
+// //throw new NotImplementedException();
+// }
+
+// public T GetObject<T>(string key)
+// {
+// if (_memoryCache.TryGetValue(key, out string val))
+// {
+// return JsonSerializer.Deserialize<T>(val, JsonConfig.Options);// JsonConvert.DeserializeObject<T>(val);
+// }
+// return default(T);
+// }
+
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="key"></param>
+// /// <returns></returns>
+// public string Get(string key)
+// {
+// if (_memoryCache.TryGetValue(key, out string val))
+// {
+// return val;
+// }
+// return "";
+// // throw new NotImplementedException();
+// }
+
+// public Task<T> GetObjectAsync<T>(string key)
+// {
+// return Task.Run<T>(() =>
+// {
+// return GetObject<T>(key);
+// });
+// }
+
+// public Task<string> GetAsync(string key)
+// {
+// return Task.Run<string>(() =>
+// {
+// return Get(key);
+// });
+// }
+
+// public string GetStringValue(string key)
+// {
+// return Get(key);
+// }
+
+// public string HashGet(string key, string sunkey)
+// {
+// throw new NotImplementedException();
+// }
+
+// public HashEntry[] HashGetAll(string key)
+// {
+// throw new NotImplementedException();
+// }
+
+// //public Task<HashEntry[]> HashGetAllAsync(string key)
+// //{
+// // throw new NotImplementedException();
+// //}
+
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="key"></param>
+// /// <param name="sunkey"></param>
+// /// <returns></returns>
+// public Task<string> HashGetAsync(string key, string sunkey, bool isnum = false)
+// {
+// if (key_hash_set.TryGetValue(key, out var val))
+// {
+// if (val != null && val != default)
+// {
+// if (val.TryGetValue(sunkey, out var _val))
+// {
+// return Task.FromResult(_val);
+// }
+// }
+// }
+// return Task.FromResult(String.Empty);
+// }
+
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="key"></param>
+// /// <param name="field"></param>
+// /// <returns></returns>
+// public async Task<int> HashGetIntFieldAsync(string key, string field, bool isNum = false)
+// {
+// var read = await this.HashGetAsync(key, field, isNum);
+// if (!string.IsNullOrEmpty(read))
+// {
+// int.TryParse(read, out var ival);
+// return ival;
+// }
+// return default(int);
+// }
+
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="key"></param>
+// /// <param name="field"></param>
+// /// <returns></returns>
+// public async Task<long> HashGetLongFieldAsync(string key, string field, bool isNum = false)
+// {
+// var read = await this.HashGetAsync(key, field, isNum);
+// if (!string.IsNullOrEmpty(read))
+// {
+// long.TryParse(read, out var ival);
+// return ival;
+// }
+// return default(long);
+// }
+
+// public void HashSet(string key, HashEntry[] vals)
+// {
+// throw new NotImplementedException();
+// }
+
+// //public void HashSetAsync(string key, HashEntry[] vals)
+// //{
+// // throw new NotImplementedException();
+// //}
+
+// public bool Lock(string key, int seconds)
+// {
+// return false;
+// }
+
+// public Task<bool> LockAsync(string key, int seconds)
+// {
+// //return Task.Run<bool>(() =>
+// //{
+// // return Lock(key, seconds);
+// //});
+// return Task.FromResult(true);
+// }
+
+// public bool Set(string key, string value, TimeSpan? expiry = null)
+// {
+// using (var wcache = _memoryCache.CreateEntry(key))
+// {
+// wcache.Value = value;
+// if (expiry == null)
+// {
+// wcache.AbsoluteExpiration = System.DateTimeOffset.Now.AddSeconds(30);
+// }
+// else
+// {
+// wcache.AbsoluteExpiration = DateTimeOffset.Now.Add((TimeSpan)expiry);
+// }
+// }
+
+// return true;
+// }
+
+// public bool Set(string key, string value, int seconds)
+// {
+// using (var wcache = _memoryCache.CreateEntry(key))
+// {
+// wcache.Value = value;
+
+// wcache.AbsoluteExpiration = System.DateTimeOffset.Now.AddSeconds(seconds);
+
+// }
+
+// return true;
+// }
+
+// public bool Set(string key, string value)
+// {
+// using (var wcache = _memoryCache.CreateEntry(key))
+// {
+// wcache.Value = value;
+// }
+// return true;
+// }
+
+// public bool SetObject<T>(string key, T value, TimeSpan? expiry = null)
+// {
+
+// return Set(key, JsonSerializer.Serialize<T>(value, JsonConfig.Options), expiry);
+// }
+
+// public bool SetObject<T>(string key, T value, int seconds)
+// {
+// return Set(key, JsonSerializer.Serialize<T>(value, JsonConfig.Options), seconds);
+// }
+
+// public Task<bool> SetAsync(string key, string value, TimeSpan? expiry = null)
+// {
+// return Task.Run<bool>(() =>
+// {
+// return Set(key, value, expiry);
+// });
+// }
+
+// public Task<bool> SetAsync(string key, string value, int seconds)
+// {
+// return Task.Run<bool>(() =>
+// {
+// return Set(key, value, seconds);
+// });
+// }
+
+// public Task<bool> SetObjectAsync<T>(string key, T value, int second)
+// {
+// return Task.Run<bool>(() =>
+// {
+// return SetObject(key, value, second);
+// });
+// }
+
+// public bool SetExpire(string key, TimeSpan? expiry)
+// {
+// if (_memoryCache.TryGetValue(key, out string sval))
+// {
+
+// return Set(key, sval, expiry);
+// }
+// return false;
+// }
+
+// public bool SetExpire(string key, int seconds)
+// {
+// if (_memoryCache.TryGetValue(key, out string sval))
+// {
+// return Set(key, sval, seconds);
+// }
+// return false;
+// }
+
+// public Task<bool> SetExpireAsync(string key, int seconds)
+// {
+// return Task.Run<bool>(() =>
+// {
+// return SetExpire(key, seconds);
+// });
+// }
+
+// public Task<bool> SetExpireAsync(string key, TimeSpan? expiry)
+// {
+// return Task.Run<bool>(() =>
+// {
+// return SetExpire(key, expiry);
+// });
+// }
+
+// public bool SetValue(string key, string val, int second)
+// {
+// return Set(key, val, second);
+// }
+
+// public bool SetValue(string key, string val)
+// {
+// return Set(key, val);
+// }
+
+// public bool UnLock(string key)
+// {
+// return false;
+// }
+
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="key"></param>
+// /// <returns></returns>
+// public Task<bool> UnLockAsync(string key)
+// {
+// //return Task.Run<bool>(() =>
+// //{
+// // return UnLock(key);
+// //});
+// return Task.FromResult(true);
+// }
+
+// ///// <summary>
+// /////
+// ///// </summary>
+// ///// <param name="key"></param>
+// ///// <param name="vals"></param>
+// ///// <returns></returns>
+// //public async Task HashSetAsync(string key, HashEntry[] vals, bool isnum = false)
+// //{
+// // await Task.Run(() =>
+// // {
+// // if (isnum)
+// // {
+// // if(key_hash_num.TryGetValue(key, out var _hash))
+// // {
+// // foreach (var entry in vals)
+// // {
+// // _hash.AddOrUpdate(entry.Name.ToString(), long.Parse(entry.Value.ToString()), (k, oldValue) => long.Parse(entry.Value.ToString()));
+// // }
+// // }
+// // else
+// // {
+// // _hash = new ConcurrentDictionary<string, long>();
+
+// // foreach (var entry in vals)
+// // {
+// // _hash.AddOrUpdate(entry.Name.ToString(), long.Parse(entry.Value.ToString()), (k, oldValue) => long.Parse(entry.Value.ToString()));
+// // }
+// // key_hash_num.TryAdd(key, _hash);
+// // }
+// // }
+// // else
+// // {
+// // key_hash_set.TryGetValue(key, out var _hash);
+// // if (_hash == null || _hash == default)
+// // {
+// // _hash = new ConcurrentDictionary<string, string>();
+// // }
+// // foreach (var entry in vals)
+// // {
+// // _hash.AddOrUpdate(entry.Name.ToString(), entry.Value.ToString(), (k, oldValue) => entry.Value.ToString());
+// // }
+// // key_hash_set.AddOrUpdate(key, _hash, (k, oldvalue) => _hash);
+// // }
+
+
+// // });
+// //}
+
+// //public List<HashKeyValue> HashGetAll(string key)
+// //{
+// // throw new NotImplementedException();
+// //}
+
+// //public Task<List<HashKeyValue>> HashGetAllAsync(string key)
+// //{
+// // throw new NotImplementedException();
+// //}
+
+// public void HashSet(string key, List<HashKeyValue> vals)
+// {
+// throw new NotImplementedException();
+// }
+
+// ///// <summary>
+// /////
+// ///// </summary>
+// ///// <param name="key"></param>
+// ///// <param name="vals"></param>
+// ///// <returns></returns>
+// //public async Task HashSetAsync(string key, List<HashKeyValue> vals, bool isnum = false)
+// //{
+// // await Task.Run(() =>
+// // {
+// // if (isnum)
+// // {
+// // if(key_hash_num.TryGetValue(key, out var _hash))
+// // {
+// // foreach (var entry in vals)
+// // {
+// // _hash.AddOrUpdate(entry.Key, long.Parse(entry.Value), (k, oldValue) => long.Parse(entry.Value));
+// // }
+// // }
+// // else
+// // {
+// // _hash = new ConcurrentDictionary<string, long>();
+// // foreach (var entry in vals)
+// // {
+// // _hash.AddOrUpdate(entry.Key, long.Parse(entry.Value), (k, oldValue) => long.Parse(entry.Value));
+// // }
+// // key_hash_num.TryAdd(key, _hash);
+// // }
+// // }
+// // else
+// // {
+// // key_hash_set.TryGetValue(key, out var _hash);
+// // if (_hash == null || _hash == default)
+// // {
+// // _hash = new ConcurrentDictionary<string, string>();
+// // }
+// // foreach (var entry in vals)
+// // {
+// // _hash.AddOrUpdate(entry.Key, entry.Value, (k, oldValue) => entry.Value);
+// // }
+// // key_hash_set.AddOrUpdate(key, _hash, (k, oldvalue) => _hash);
+// // }
+// // });
+// //}
+
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="key"></param>
+// /// <param name="field"></param>
+// /// <param name="num"></param>
+// /// <returns></returns>
+// public Task<long> HashIncrementAsync(string key, string field, long num = 1)
+// {
+// var _result = num;
+// key_hash_num.TryGetValue(key, out var _hash);
+// if (_hash == null || _hash == default)
+// {
+// _hash = new ConcurrentDictionary<string, long>() { };
+// _hash.TryAdd(field, num);
+// key_hash_num.TryAdd(key, _hash);
+// }
+// else
+// {
+// if (_hash.ContainsKey(field))
+// {
+// _hash[field] = _hash[field] + num;
+// _result = _hash[field];
+// }
+// else
+// {
+// _hash.TryAdd(field, num);
+// }
+// }
+// return Task.FromResult(_result);
+// }
+
+// ///// <summary>
+// /////
+// ///// </summary>
+// ///// <param name="key"></param>
+// ///// <param name="start"></param>
+// ///// <param name="stop"></param>
+// ///// <returns></returns>
+// //public Task<SortedSetEntry[]> SortedSetRangeByRankWithScoresAsync(string key, int start = 0, int stop = 1)
+// //{
+// // if (key_hash_num.TryGetValue(key, out var _hash))
+// // {
+// // var list = new List<SortedSetEntry>();
+// // var hits = _hash.Where(x => x.Value >= start && x.Value < stop).ToList();
+// // foreach (var item in hits)
+// // {
+// // list.Add(new SortedSetEntry(item.Key, item.Value));
+// // }
+// // return Task.FromResult(list.ToArray());
+// // }
+// // return Task.FromResult(new SortedSetEntry[] { });
+// //}
+
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="key"></param>
+// /// <param name="start"></param>
+// /// <param name="stop"></param>
+// /// <returns></returns>
+// /// <exception cref="NotImplementedException"></exception>
+// public Task<RedisValue[]> SortedSetRangeByScoreAsync(string key, long start = 0, long stop = 1)
+// {
+// if (key_hash_num.TryGetValue(key, out var _hash))
+// {
+// var list = new List<RedisValue>();
+// var hits = _hash
+// .PasteWhereIf(start < stop, x => start <= x.Value && x.Value < stop)
+// .PasteWhereIf(start > stop, x => stop <= x.Value && x.Value < start)
+// .ToList();
+// foreach (var item in hits)
+// {
+// list.Add(new RedisValue(item.Key));
+// }
+// return Task.FromResult(list.ToArray());
+// }
+// return Task.FromResult(new RedisValue[] { });
+// }
+
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="key"></param>
+// /// <param name="field"></param>
+// /// <param name="num"></param>
+// /// <returns></returns>
+// public Task<long> SortedSetIncrementAsync(string key, string field, long num = 1)
+// {
+// var _result = num;
+// key_hash_num.TryGetValue(key, out var _hash);
+// if (_hash == null || _hash == default)
+// {
+// _hash = new ConcurrentDictionary<string, long>() { };
+// _hash.TryAdd(field, num);
+// key_hash_num.TryAdd(key, _hash);
+// }
+// else
+// {
+// if (_hash.ContainsKey(field))
+// {
+// _hash[field] = _hash[field] + num;
+// _result = _hash[field];
+// }
+// else
+// {
+// _hash.TryAdd(field, num);
+// }
+// }
+// return Task.FromResult(_result);
+// }
+
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="key"></param>
+// /// <param name="field"></param>
+// /// <param name="num"></param>
+// /// <returns></returns>
+// public Task<long> SortedSetDecrementAsync(string key, string field, long num)
+// {
+// var _result = num;
+// key_hash_num.TryGetValue(key, out var _hash);
+// if (_hash == null || _hash == default)
+// {
+// _hash = new ConcurrentDictionary<string, long>() { };
+// _hash.TryAdd(field, num);
+// key_hash_num.TryAdd(key, _hash);
+// }
+// else
+// {
+// if (_hash.ContainsKey(field))
+// {
+// _hash[field] = _hash[field] - num;
+// _result = _hash[field];
+// }
+// else
+// {
+// _hash.TryAdd(field, num);
+// }
+// }
+// return Task.FromResult(_result);
+// }
+
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="key"></param>
+// /// <param name="field"></param>
+// /// <returns></returns>
+// public Task<bool> SortedSetRemoveAsync(string key, string field)
+// {
+// var _result = false;
+// if (key_hash_num.TryGetValue(key, out var _hash))
+// {
+// if (_hash.ContainsKey(field))
+// {
+// _hash.Remove(field, out _);
+// _result = true;
+// }
+// }
+// return Task.FromResult(_result);
+// }
+
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="key"></param>
+// /// <param name="field"></param>
+// /// <param name="num"></param>
+// /// <returns></returns>
+// public Task<bool> SortedSetAddAsync(string key, string field, long num)
+// {
+// if (key_hash_num.TryGetValue(key, out var _hash))
+// {
+// if (_hash.ContainsKey(field))
+// {
+// _hash[field] = num;
+// }
+// else
+// {
+// _hash.TryAdd(field, num);
+// }
+// }
+// else
+// {
+// _hash = new ConcurrentDictionary<string, long>() { };
+// _hash.TryAdd(field, num);
+// key_hash_num.TryAdd(key, _hash);
+// }
+// return Task.FromResult(true);
+// }
+
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="key"></param>
+// /// <returns></returns>
+// /// <exception cref="NotImplementedException"></exception>
+// public Task<bool> ExistsAsync(string key)
+// {
+// var _result = _memoryCache.TryGetValue(key, out var val);
+// return Task.FromResult(_result);
+// }
+
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="key"></param>
+// /// <returns></returns>
+// /// <exception cref="NotImplementedException"></exception>
+// public Task<List<HashKeyValue>> HashGetAllAsync(string key)
+// {
+// if (key_hash_set.TryGetValue(key, out var _hash))
+// {
+// var finds = new List<HashKeyValue>();
+// foreach (var item in _hash)
+// {
+// finds.Add(new HashKeyValue { Key = item.Key, Value = item.Value });
+// }
+// return Task.FromResult(finds);
+// }
+// if (key_hash_num.TryGetValue(key, out var _hash_num))
+// {
+// var finds = new List<HashKeyValue>();
+// foreach (var item in _hash_num)
+// {
+// finds.Add(new HashKeyValue { Key = item.Key, Value = item.ToString() });
+// }
+// return Task.FromResult(finds);
+// }
+// return Task.FromResult(new List<HashKeyValue> { });
+// }
+
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="key"></param>
+// /// <param name="field"></param>
+// /// <returns></returns>
+// public Task<long> HashDecrementAsync(string key, string field)
+// {
+// var num = 1;
+// long _result = num;
+// key_hash_num.TryGetValue(key, out var _hash);
+// if (_hash == null || _hash == default)
+// {
+// _hash = new ConcurrentDictionary<string, long>() { };
+// _hash.TryAdd(field, 0 - num);
+// key_hash_num.TryAdd(key, _hash);
+// }
+// else
+// {
+// if (_hash.ContainsKey(field))
+// {
+// _hash[field] = _hash[field] - num;
+// _result = _hash[field];
+// }
+// else
+// {
+// _hash.TryAdd(field, num);
+// }
+// }
+// return Task.FromResult(_result);
+// }
+
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="key"></param>
+// /// <param name="filed"></param>
+// /// <returns></returns>
+// public Task<bool> HashExistsAsync(string key, string filed)
+// {
+// var _result = false;
+
+// if (key_hash_num.TryGetValue(key, out var _hash))
+// {
+// if (_hash.ContainsKey(filed))
+// {
+// _result = true;
+// }
+// }
+// if (!_result)
+// {
+// if (key_hash_set.TryGetValue(key, out var hash_key))
+// {
+// if (hash_key.ContainsKey(filed))
+// {
+// _result = true;
+// }
+// }
+// }
+// return Task.FromResult(true);
+// }
+
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="key"></param>
+// /// <param name="field"></param>
+// /// <param name="value"></param>
+// /// <returns></returns>
+// public async Task HashSetAsync(string key, string field, RedisValue value, bool isnum = false)
+// {
+// await Task.Run(() =>
+// {
+// if (isnum)
+// {
+// if (key_hash_num.TryGetValue(key, out var hash_key))
+// {
+// hash_key.AddOrUpdate(field, long.Parse(value.ToString()), (n, o) => long.Parse(value.ToString()));
+// }
+// else
+// {
+// var find = new ConcurrentDictionary<string, long>();
+// find.TryAdd(field, long.Parse(value.ToString()));
+// key_hash_num.TryAdd(key, find);
+// }
+// }
+// else
+// {
+// if (key_hash_set.TryGetValue(key, out var hash_key))
+// {
+// hash_key.AddOrUpdate(field, value.ToString(), (n, o) => value.ToString());
+// }
+// else
+// {
+// var find = new ConcurrentDictionary<string, string>();
+// find.TryAdd(field, value.ToString());
+// key_hash_set.TryAdd(key, find);
+// }
+// }
+// });
+// }
+
+// /// <summary>
+// ///
+// /// </summary>
+// /// <typeparam name="T"></typeparam>
+// /// <param name="key"></param>
+// /// <param name="field"></param>
+// /// <returns></returns>
+// public Task<T> HashGetObjectAsync<T>(string key, string field)
+// {
+// if (key_hash_set.TryGetValue(key, out var hash_key))
+// {
+// if (hash_key.TryGetValue(field, out var _value))
+// {
+// if (!String.IsNullOrEmpty(_value))
+// {
+// var t = JsonSerializer.Deserialize<T>(_value, JsonConfig.Options);// Newtonsoft.Json.JsonConvert.DeserializeObject<T>(_value);
+// return Task.FromResult(t);
+// }
+// }
+// }
+// return Task.FromResult(default(T));
+// }
+
+// /// <summary>
+// ///
+// /// </summary>
+// /// <typeparam name="T"></typeparam>
+// /// <param name="key"></param>
+// /// <param name="field"></param>
+// /// <param name="entity"></param>
+// /// <returns></returns>
+// public Task<bool> HashSetObjectAsync<T>(string key, string field, T entity)
+// {
+// var value = JsonSerializer.Serialize<T>(entity, JsonConfig.Options);
+// //Newtonsoft.Json.JsonConvert.SerializeObject(entity);
+// if (key_hash_set.TryGetValue(key, out var hash_key))
+// {
+
+// hash_key.AddOrUpdate(field, value, (n, o) => value);
+
+// }
+// else
+// {
+// var find = new ConcurrentDictionary<string, string>();
+// find.TryAdd(field, value);
+// key_hash_set.TryAdd(key, find);
+// }
+// return Task.FromResult(true);
+// }
+
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="key"></param>
+// /// <param name="pattern"></param>
+// /// <param name="page"></param>
+// /// <param name="size"></param>
+// /// <returns></returns>
+// public Task<List<HashEntry>> HashScanAsync(string key, string pattern, int page, int size, bool isincom = false)
+// {
+// if (isincom)
+// {
+// if (key_hash_num.TryGetValue(key, out var hash_key))
+// {
+// var position = 3;//1left 2right 3like
+// if (pattern.StartsWith("*"))
+// {
+// position = 1;
+// }
+// if (pattern.EndsWith("*"))
+// {
+// if (position == 1)
+// {
+// position = 3;
+// }
+// else
+// {
+// position = 2;
+// }
+// }
+// pattern = pattern.Replace("*", "");
+// var vals = hash_key
+// .PasteWhereIf(position == 1, x => x.Key.EndsWith(pattern))
+// .PasteWhereIf(position == 2, x => x.Key.StartsWith(pattern))
+// .PasteWhereIf(position == 3, x => x.Key.Contains(pattern))
+// .OrderBy(x => x.Key)
+// .ToList();
+// var start = (page - 1) * size;
+// var end = page * size;
+// var list = new List<HashEntry>();
+// for (var k = 0; k < vals.Count; k++)
+// {
+// if (k >= start && k < end)
+// {
+// var item = vals[k];
+// list.Add(new HashEntry(item.Key, item.Value));
+// }
+// if (k > end)
+// {
+// break;
+// }
+// }
+// return Task.FromResult(list);
+// }
+// }
+// else
+// {
+// if (key_hash_set.TryGetValue(key, out var hash_key))
+// {
+// var position = 3;//1left 2right 3like
+// if (pattern.StartsWith("*"))
+// {
+// position = 1;
+// }
+// if (pattern.EndsWith("*"))
+// {
+// if (position == 1)
+// {
+// position = 3;
+// }
+// else
+// {
+// position = 2;
+// }
+// }
+// pattern = pattern.Replace("*", "");
+// var vals = hash_key
+// .PasteWhereIf(position == 1, x => x.Key.StartsWith(pattern))
+// .PasteWhereIf(position == 2, x => x.Key.EndsWith(pattern))
+// .PasteWhereIf(position == 3, x => x.Key.Contains(pattern))
+// .OrderBy(x => x.Key)
+// .ToList();
+// var start = (page - 1) * size;
+// var end = page * size;
+// var list = new List<HashEntry>();
+// for (var k = 0; k < vals.Count; k++)
+// {
+// if (k >= start && k < end)
+// {
+// var item = vals[k];
+// list.Add(new HashEntry(item.Key, item.Value));
+// }
+// if (k > end)
+// {
+// break;
+// }
+// }
+// return Task.FromResult(list);
+// }
+// }
+// return Task.FromResult(new List<HashEntry> { });
+// }
+
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="key"></param>
+// /// <param name="fields"></param>
+// /// <returns></returns>
+// public Task<RedisValue[]> HashGetAsync(string key, RedisValue[] fields, bool isnum = false)
+// {
+// var fis = fields.Select(x => x.ToString()).ToArray();
+// if (!isnum)
+// {
+// if (key_hash_set.TryGetValue(key, out var hash_key))
+// {
+// var haves = hash_key.Where(x => fis.Contains(x.Key)).ToList();
+// var reds = new List<RedisValue>();
+// foreach (var kv in haves)
+// {
+// reds.Add(kv.Value);
+// }
+// return Task.FromResult(reds.ToArray());
+// }
+// }
+// else
+// {
+// if (key_hash_num.TryGetValue(key, out var hash_key))
+// {
+// var haves = hash_key.Where(x => fis.Contains(x.Key)).ToList();
+// var reds = new List<RedisValue>();
+// foreach (var kv in haves)
+// {
+// reds.Add(kv.Value);
+// }
+// return Task.FromResult(reds.ToArray());
+// }
+// }
+// return Task.FromResult(new RedisValue[] { });
+// }
+
+
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="key"></param>
+// /// <param name="field"></param>
+// /// <returns></returns>
+// public async Task<bool> HashDeleteAsync(string key, string field)
+// {
+// await Task.Run(() =>
+// {
+// var _result = false;
+// if (key_hash_set.TryGetValue(key, out var hash_key))
+// {
+// if (hash_key.ContainsKey(field))
+// {
+// _result = true;
+// }
+// hash_key.Remove(field, out var abc);
+// }
+// if (!_result)
+// {
+// if (key_hash_num.TryGetValue(key, out var _hash))
+// {
+// if (_hash.ContainsKey(field))
+// {
+// _result = true;
+// }
+// _hash.Remove(field, out var abc);
+// }
+// }
+// return _result;
+// });
+// return false;
+// }
+
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="key"></param>
+// /// <param name="fields"></param>
+// /// <returns></returns>
+// /// <exception cref="NotImplementedException"></exception>
+// public Task<bool> HashDeleteAsync(string key, RedisValue[] fields)
+// {
+// var fis = fields.Select(x => x.ToString()).ToArray();
+// if (key_hash_set.TryGetValue(key, out var hash_key))
+// {
+// foreach (var kv in fis)
+// {
+// hash_key.Remove(kv, out var va);
+// }
+// var haves = hash_key.Where(x => fis.Contains(x.Key)).ToList();
+// var reds = new List<RedisValue>();
+// foreach (var kv in haves)
+// {
+// reds.Add(kv.Value);
+// }
+// return Task.FromResult(true);
+// }
+// return Task.FromResult(false);
+// }
+
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="key"></param>
+// /// <returns></returns>
+// /// <exception cref="NotImplementedException"></exception>
+// public Task<long> HashLengthAsync(string key)
+// {
+// if (key_hash_set.TryGetValue(key, out var hash_key))
+// {
+// return Task.FromResult((long)hash_key.Keys.Count);
+// }
+// return Task.FromResult((long)0);
+// }
+
+// /// <summary>
+// /// 打印
+// /// </summary>
+// /// <returns></returns>
+// public string Print()
+// {
+// var sb = new StringBuilder();
+
+// if (key_hash_set != null && key_hash_set.Any())
+// {
+// //sb.AppendLine(Newtonsoft.Json.JsonConvert.SerializeObject(key_hash_set));
+// sb.AppendLine(JsonSerializer.Serialize(key_hash_set, JsonConfig.Options));
+// }
+
+// if (key_hash_num != null && key_hash_num.Any())
+// {
+// //sb.AppendLine(Newtonsoft.Json.JsonConvert.SerializeObject(key_hash_num));
+// sb.AppendLine(JsonSerializer.Serialize(key_hash_set, JsonConfig.Options));
+// }
+
+// return sb.ToString();
+// }
+
+
+// //------------------------------------------------
+
+
+// //private readonly IMemoryCache _memoryCache;
+// private static readonly Random _random = new();
+
+// //public MemoryClient(IMemoryCache memoryCache)
+// //{
+// // _memoryCache = memoryCache;
+// //}
+
+// //public bool IsRedis => false;
+
+// #region 同步方法
+
+// //public bool Delete(string key)
+// //{
+// // _memoryCache.Remove(key);
+// // return true;
+// //}
+
+// //public bool Exists(string key)
+// //{
+// // return _memoryCache.TryGetValue(key, out _);
+// //}
+
+// //public string Get(string key)
+// //{
+// // return _memoryCache.TryGetValue(key, out string? val) ? val ?? string.Empty : string.Empty;
+// //}
+
+// //public T GetObject<T>(string key)
+// //{
+// // if (_memoryCache.TryGetValue(key, out string? val) && !string.IsNullOrEmpty(val))
+// // {
+// // return JsonConvert.DeserializeObject<T>(val);
+// // }
+// // return default;
+// //}
+
+// //public string GetStringValue(string key)
+// //{
+// // return Get(key);
+// //}
+
+// public object TryGetValue(string key)
+// {
+// return _memoryCache.TryGetValue(key, out var val) ? val : null;
+// }
+
+// public T GetOrCreate<T>(string key, Func<ICacheEntry, T> factory, TimeSpan? expiration = null)
+// {
+// return _memoryCache.GetOrCreate(key, entry =>
+// {
+// SetCacheEntryOptions(entry, expiration);
+// return factory(entry);
+// });
+// }
+
+// //public bool Set(string key, string value, TimeSpan? expiry = null)
+// //{
+// // using var entry = _memoryCache.CreateEntry(key);
+// // entry.Value = value;
+// // SetCacheEntryOptions(entry, expiry);
+// // return true;
+// //}
+
+// //public bool Set(string key, string value, int seconds)
+// //{
+// // return Set(key, value, TimeSpan.FromSeconds(seconds));
+// //}
+
+// //public bool Set(string key, string value)
+// //{
+// // using var entry = _memoryCache.CreateEntry(key);
+// // entry.Value = value;
+// // return true;
+// //}
+
+// //public bool SetObject<T>(string key, T value, TimeSpan? expiry = null)
+// //{
+// // return Set(key, JsonConvert.SerializeObject(value), expiry);
+// //}
+
+// //public bool SetObject<T>(string key, T value, int seconds)
+// //{
+// // return Set(key, JsonConvert.SerializeObject(value), TimeSpan.FromSeconds(seconds));
+// //}
+
+// public bool CreateEntry(string key, object value, TimeSpan? expiry = null)
+// {
+// using var entry = _memoryCache.CreateEntry(key);
+// entry.Value = value;
+// SetCacheEntryOptions(entry, expiry);
+// return true;
+// }
+
+// //public bool SetValue(string key, string val, int second)
+// //{
+// // return Set(key, val, second);
+// //}
+
+// //public bool SetValue(string key, string val)
+// //{
+// // return Set(key, val);
+// //}
+
+// //public bool SetExpire(string key, TimeSpan? expiry)
+// //{
+// // if (_memoryCache.TryGetValue(key, out string? val))
+// // {
+// // return Set(key, val ?? string.Empty, expiry);
+// // }
+// // return false;
+// //}
+
+// //public bool SetExpire(string key, int seconds)
+// //{
+// // return SetExpire(key, TimeSpan.FromSeconds(seconds));
+// //}
+
+// //public bool Lock(string key, int seconds)
+// //{
+// // // MemoryCache 不支持分布式锁,直接返回 true
+// // return true;
+// //}
+
+// //public bool UnLock(string key)
+// //{
+// // return true;
+// //}
+
+// #endregion
+
+// #region 异步方法(同步包装,返回 Task)
+
+// //public Task<bool> DeleteAsync(string key)
+// //{
+// // Delete(key);
+// // return Task.FromResult(true);
+// //}
+
+// public Task BatchRemoveAsync(string[] keys)
+// {
+// if (keys != null)
+// {
+// foreach (var key in keys)
+// {
+// if (!string.IsNullOrEmpty(key))
+// {
+// _memoryCache.Remove(key);
+// }
+// }
+// }
+// return Task.CompletedTask;
+// }
+
+// //public Task<bool> ExistsAsync(string key)
+// //{
+// // return Task.FromResult(Exists(key));
+// //}
+
+// //public Task<string> GetAsync(string key)
+// //{
+// // return Task.FromResult(Get(key));
+// //}
+
+// //public Task<T?> GetObjectAsync<T>(string key)
+// //{
+// // return Task.FromResult(GetObject<T>(key));
+// //}
+
+// public Task<T> GetOrCreateAsync<T>(string key, Func<ICacheEntry, Task<T>> factory, TimeSpan? expiration = null)
+// {
+// return _memoryCache.GetOrCreateAsync(key, async entry =>
+// {
+// SetCacheEntryOptions(entry, expiration);
+// return await factory(entry);
+// });
+// }
+
+// //public Task<bool> SetAsync(string key, string value, TimeSpan? expiry = null)
+// //{
+// // return Task.FromResult(Set(key, value, expiry));
+// //}
+
+// //public Task<bool> SetAsync(string key, string value, int seconds)
+// //{
+// // return Task.FromResult(Set(key, value, seconds));
+// //}
+
+// //public Task<bool> SetObjectAsync<T>(string key, T value, int second)
+// //{
+// // return Task.FromResult(SetObject(key, value, second));
+// //}
+
+// //public Task<bool> SetExpireAsync(string key, int seconds)
+// //{
+// // return Task.FromResult(SetExpire(key, seconds));
+// //}
+
+// //public Task<bool> SetExpireAsync(string key, TimeSpan? expiry)
+// //{
+// // return Task.FromResult(SetExpire(key, expiry));
+// //}
+
+// //public Task<bool> LockAsync(string key, int seconds)
+// //{
+// // return Task.FromResult(Lock(key, seconds));
+// //}
+
+// //public Task<bool> UnLockAsync(string key)
+// //{
+// // return Task.FromResult(UnLock(key));
+// //}
+
+// #endregion
+
+// #region Hash 操作
+
+// //public string HashGet(string key, string subKey)
+// //{
+// // if (_memoryCache.TryGetValue(key, out var obj) && obj is Dictionary<string, string> dict)
+// // {
+// // return dict.TryGetValue(subKey, out var val) ? val : string.Empty;
+// // }
+// // return string.Empty;
+// //}
+
+// //public HashEntry[] HashGetAll(string key)
+// //{
+// // if (_memoryCache.TryGetValue(key, out var obj) && obj is Dictionary<string, string> dict)
+// // {
+// // return dict.Select(x => new HashEntry(x.Key, x.Value)).ToArray();
+// // }
+// // return Array.Empty<HashEntry>();
+// //}
+
+// //public void HashSet(string key, HashEntry[] vals)
+// //{
+// // var dict = _memoryCache.TryGetValue(key, out var obj) && obj is Dictionary<string, string> existing
+// // ? existing
+// // : new Dictionary<string, string>();
+
+// // foreach (var entry in vals)
+// // {
+// // dict[entry.Name.ToString()] = entry.Value.ToString();
+// // }
+
+// // _memoryCache.Set(key, dict);
+// //}
+
+// public Task<string> HashGetAsync(string key, string subKey)
+// {
+// return Task.FromResult(HashGet(key, subKey));
+// }
+
+// //public Task<HashEntry[]> HashGetAllAsync(string key)
+// //{
+// // return Task.FromResult(HashGetAll(key));
+// //}
+
+// public Task HashSetAsync(string key, HashEntry[] vals)
+// {
+// HashSet(key, vals);
+// return Task.CompletedTask;
+// }
+
+// ///// <summary>
+// /////
+// ///// </summary>
+// ///// <param name="key"></param>
+// ///// <param name="field"></param>
+// ///// <returns></returns>
+// //public Task<bool> HashDeleteAsync(string key, string field)
+// //{
+// // if (_memoryCache.TryGetValue(key, out var obj) && obj is Dictionary<string, string> dict)
+// // {
+// // if (dict.ContainsKey(field))
+// // {
+// // dict.Remove(field);
+// // }
+// // }
+// // return Task.FromResult(true);
+// //}
+
+// public Task<HashEntry> HashRandomFieldsWithValuesAsync(string key)
+// {
+// if (_memoryCache.TryGetValue(key, out var obj) && obj is Dictionary<string, string> dict && dict.Count > 0)
+// {
+// var keys = dict.Keys.ToArray();
+// var randomKey = keys[_random.Next(keys.Length)];
+// return Task.FromResult(new HashEntry(randomKey, dict[randomKey]));
+// }
+// return Task.FromResult(new HashEntry(string.Empty, string.Empty));
+// }
+
+// public Task<long> HashIncrementAsync(string key, RedisValue field, long num = 1)
+// {
+// // MemoryCache 不支持原子增减,简单实现
+// var current = HashGet(key, field.ToString());
+// if (long.TryParse(current, out var value))
+// {
+// var newValue = value + num;
+// HashSet(key, new[] { new HashEntry(field, newValue.ToString()) });
+// return Task.FromResult(newValue);
+// }
+// HashSet(key, new[] { new HashEntry(field, num.ToString()) });
+// return Task.FromResult(num);
+// }
+
+// public Task<long> HashDecrementAsync(string key, RedisValue field, long num = 1)
+// {
+// return HashIncrementAsync(key, field, -num);
+// }
+
+// #endregion
+
+// #region 未实现的方法(抛出明确异常)
+
+// //public void HashSet(string key, List<HashKeyValue> vals)
+// //{
+// // throw new NotImplementedException("MemoryCache 不支持此操作");
+// //}
+
+// public Task HashSetAsync(string key, List<HashKeyValue> vals)
+// {
+// throw new NotImplementedException("MemoryCache 不支持此操作");
+// }
+
+// List<HashKeyValue> IAppCache.HashGetAll(string key)
+// {
+// throw new NotImplementedException("MemoryCache 不支持此操作");
+// }
+
+// Task<List<HashKeyValue>> IAppCache.HashGetAllAsync(string key)
+// {
+// throw new NotImplementedException("MemoryCache 不支持此操作");
+// }
+
+// public Task<HashEntry[]> HashScanAsync(string key, string pattern, int size = 1, int cursor = 0, int offset = 0)
+// {
+// throw new NotImplementedException("MemoryCache 不支持 HashScan");
+// }
+
+// #endregion
+
+// #region 私有辅助方法
+
+// private static void SetCacheEntryOptions(ICacheEntry entry, TimeSpan? expiration)
+// {
+// if (expiration.HasValue)
+// {
+// entry.AbsoluteExpirationRelativeToNow = expiration;
+// }
+// else
+// {
+// entry.SlidingExpiration = TimeSpan.FromMinutes(5);
+// }
+// }
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="key"></param>
+// /// <param name="felid"></param>
+// /// <param name="num"></param>
+// /// <returns></returns>
+// /// <exception cref="NotImplementedException"></exception>
+// public Task HashIncrementAsync(string key, string felid, int num = 1)
+// {
+// throw new NotImplementedException();
+// }
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="key"></param>
+// /// <returns></returns>
+// /// <exception cref="NotImplementedException"></exception>
+// public Task<string> ReadStringAsync(string key)
+// {
+// throw new NotImplementedException();
+// }
+// /// <summary>
+// ///
+// /// </summary>
+// /// <typeparam name="T"></typeparam>
+// /// <param name="key"></param>
+// /// <returns></returns>
+// /// <exception cref="NotImplementedException"></exception>
+// public Task<T> ReadObjectAsync<T>(string key)
+// {
+// throw new NotImplementedException();
+// }
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="skey"></param>
+// /// <param name="val"></param>
+// /// <returns></returns>
+// /// <exception cref="NotImplementedException"></exception>
+// public Task<bool> SetAddAsync(string skey, int val)
+// {
+// throw new NotImplementedException();
+// }
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="skey"></param>
+// /// <param name="filed"></param>
+// /// <returns></returns>
+// /// <exception cref="NotImplementedException"></exception>
+// public Task<bool> SetContainsAsync(string skey, int filed)
+// {
+// throw new NotImplementedException();
+// }
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="skey"></param>
+// /// <param name="filed"></param>
+// /// <returns></returns>
+// /// <exception cref="NotImplementedException"></exception>
+// public Task<bool> SetRemoveAsync(string skey, int filed)
+// {
+// throw new NotImplementedException();
+// }
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="skey"></param>
+// /// <returns></returns>
+// /// <exception cref="NotImplementedException"></exception>
+// public Task<long> SetRandomMemberAsync(string skey)
+// {
+// throw new NotImplementedException();
+// }
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="skey"></param>
+// /// <returns></returns>
+// /// <exception cref="NotImplementedException"></exception>
+// public Task<long> SetLengthAsync(string skey)
+// {
+// throw new NotImplementedException();
+// }
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="skey"></param>
+// /// <param name="sval"></param>
+// /// <returns></returns>
+// /// <exception cref="NotImplementedException"></exception>
+// public Task<long> ListRightPushAsync(string skey, string sval)
+// {
+// throw new NotImplementedException();
+// }
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="skey"></param>
+// /// <param name="score"></param>
+// /// <returns></returns>
+// /// <exception cref="NotImplementedException"></exception>
+// public Task<string> SortedSetRangeByScoreAsync(string skey, long score)
+// {
+// throw new NotImplementedException();
+// }
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="skey"></param>
+// /// <returns></returns>
+// /// <exception cref="NotImplementedException"></exception>
+// public Task<long> SortedSetRangeByRankWithScoresAsync(string skey)
+// {
+// throw new NotImplementedException();
+// }
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="skey"></param>
+// /// <returns></returns>
+// /// <exception cref="NotImplementedException"></exception>
+// public Task<long> ListLengthAsync(string skey)
+// {
+// throw new NotImplementedException();
+// }
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="skey"></param>
+// /// <returns></returns>
+// /// <exception cref="NotImplementedException"></exception>
+// public Task<string> ListLeftPopAsync(string skey)
+// {
+// throw new NotImplementedException();
+// }
+
+// /// <summary>
+// ///
+// /// </summary>
+// /// <param name="skey"></param>
+// /// <param name="start"></param>
+// /// <param name="stop"></param>
+// /// <returns></returns>
+// /// <exception cref="NotImplementedException"></exception>
+// public Task<List<string>> ListRangeAsync(string skey, int start = 0, int stop = 30)
+// {
+// throw new NotImplementedException();
+// }
+
+// /// <summary>
+// ///
+// /// </summary>
+// /// <typeparam name="T"></typeparam>
+// /// <param name="skey"></param>
+// /// <param name="start"></param>
+// /// <param name="stop"></param>
+// /// <returns></returns>
+// /// <exception cref="NotImplementedException"></exception>
+// public Task<List<T>> ListRangeAsync<T>(string skey, int start = 0, int stop = 30)
+// {
+// throw new NotImplementedException();
+// }
+
+// #endregion
+
+
+// }
+
+//}
framework/PasteApeart.Handler/redis/MemoryClient.cs
diff --git a/framework/PasteApeart.Handler/redis/MemoryClient.cs b/framework/PasteApeart.Handler/redis/MemoryClient.cs
index 229d2a2..c6cd5d3 100644
--- a/framework/PasteApeart.Handler/redis/MemoryClient.cs
+++ b/framework/PasteApeart.Handler/redis/MemoryClient.cs
@@ -22,64 +22,82 @@ namespace PasteApeart.Handler.redis
_memoryCache = memoryCache;
key_hash_set = new ConcurrentDictionary<string, ConcurrentDictionary<string, string>>();
key_hash_num = new ConcurrentDictionary<string, ConcurrentDictionary<string, long>>();
+ key_set = new ConcurrentDictionary<string, ConcurrentDictionary<int, byte>>();
+ key_list = new ConcurrentDictionary<string, List<string>>();
}
- ///// <summary>
- /////
- ///// </summary>
- //private ConcurrentDictionary<string, string> key_val;
+ private ConcurrentDictionary<string, ConcurrentDictionary<string, string>> key_hash_set;
+ private ConcurrentDictionary<string, ConcurrentDictionary<string, long>> key_hash_num;
- ///// <summary>
- /////
- ///// </summary>
- //private ConcurrentDictionary<string, List<SortScore>> key_sort_set;
+ /// <summary>
+ /// Set(整数集合) 支持
+ /// </summary>
+ private ConcurrentDictionary<string, ConcurrentDictionary<int, byte>> key_set;
/// <summary>
- ///
+ /// List 支持
/// </summary>
- private ConcurrentDictionary<string, ConcurrentDictionary<string, string>> key_hash_set;
+ private ConcurrentDictionary<string, List<string>> key_list;
/// <summary>
+ /// List 操作锁
+ /// </summary>
+ private readonly object _listLock = new object();
+ /// <summary>
///
/// </summary>
- private ConcurrentDictionary<string, ConcurrentDictionary<string, long>> key_hash_num;
-
public bool IsRedis { get => false; }
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <returns></returns>
public bool Delete(string key)
{
_memoryCache.Remove(key);
+ key_hash_set.TryRemove(key, out _);
+ key_hash_num.TryRemove(key, out _);
+ key_set.TryRemove(key, out _);
+ key_list.TryRemove(key, out _);
return true;
}
-
/// <summary>
- /// error
+ ///
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public Task<bool> DeleteAsync(string key)
{
- return Task.Run<bool>(() =>
- {
- return Delete(key);
- });
+ return Task.FromResult(Delete(key));
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <returns></returns>
public bool Exists(string key)
{
- return _memoryCache.TryGetValue(key, out var val);
- //throw new NotImplementedException();
+ if (_memoryCache.TryGetValue(key, out var _)) return true;
+ if (key_hash_set.ContainsKey(key)) return true;
+ if (key_hash_num.ContainsKey(key)) return true;
+ if (key_set.ContainsKey(key)) return true;
+ if (key_list.ContainsKey(key)) return true;
+ return false;
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="key"></param>
+ /// <returns></returns>
public T GetObject<T>(string key)
{
if (_memoryCache.TryGetValue(key, out string val))
{
- return JsonSerializer.Deserialize<T>(val, JsonConfig.Options);// JsonConvert.DeserializeObject<T>(val);
+ return JsonSerializer.Deserialize<T>(val, JsonConfig.Options);
}
return default(T);
}
-
/// <summary>
///
/// </summary>
@@ -92,71 +110,100 @@ namespace PasteApeart.Handler.redis
return val;
}
return "";
- // throw new NotImplementedException();
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="key"></param>
+ /// <returns></returns>
public Task<T> GetObjectAsync<T>(string key)
{
- return Task.Run<T>(() =>
- {
- return GetObject<T>(key);
- });
+ return Task.FromResult(GetObject<T>(key));
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <returns></returns>
public Task<string> GetAsync(string key)
{
- return Task.Run<string>(() =>
- {
- return Get(key);
- });
+ return Task.FromResult(Get(key));
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <returns></returns>
public string GetStringValue(string key)
{
return Get(key);
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="sunkey"></param>
+ /// <returns></returns>
public string HashGet(string key, string sunkey)
{
- throw new NotImplementedException();
+ if (key_hash_set.TryGetValue(key, out var val) && val.TryGetValue(sunkey, out var _val))
+ {
+ return _val;
+ }
+ if (key_hash_num.TryGetValue(key, out var numVal) && numVal.TryGetValue(sunkey, out var _numVal))
+ {
+ return _numVal.ToString();
+ }
+ return string.Empty;
}
- public HashEntry[] HashGetAll(string key)
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <returns></returns>
+ public HashEntry[] HashGetAllEntry(string key)
{
- throw new NotImplementedException();
+ if (key_hash_set.TryGetValue(key, out var val))
+ {
+ return val.Select(x => new HashEntry(x.Key, x.Value)).ToArray();
+ }
+ if (key_hash_num.TryGetValue(key, out var numVal))
+ {
+ return numVal.Select(x => new HashEntry(x.Key, x.Value)).ToArray();
+ }
+ return Array.Empty<HashEntry>();
}
- //public Task<HashEntry[]> HashGetAllAsync(string key)
- //{
- // throw new NotImplementedException();
- //}
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <returns></returns>
+ public async Task<HashEntry[]> HashGetAllEntryAsync(string key)
+ {
+ var result = HashGetAllEntry(key);
+ return await Task.FromResult(result);
+ }
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <param name="sunkey"></param>
+ /// <param name="isnum"></param>
/// <returns></returns>
public Task<string> HashGetAsync(string key, string sunkey, bool isnum = false)
{
- if (key_hash_set.TryGetValue(key, out var val))
- {
- if (val != null && val != default)
- {
- if (val.TryGetValue(sunkey, out var _val))
- {
- return Task.FromResult(_val);
- }
- }
- }
- return Task.FromResult(String.Empty);
+ return Task.FromResult(HashGet(key, sunkey));
}
-
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <param name="field"></param>
+ /// <param name="isNum"></param>
/// <returns></returns>
public async Task<int> HashGetIntFieldAsync(string key, string field, bool isNum = false)
{
@@ -168,12 +215,12 @@ namespace PasteApeart.Handler.redis
}
return default(int);
}
-
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <param name="field"></param>
+ /// <param name="isNum"></param>
/// <returns></returns>
public async Task<long> HashGetLongFieldAsync(string key, string field, bool isNum = false)
{
@@ -185,31 +232,53 @@ namespace PasteApeart.Handler.redis
}
return default(long);
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="vals"></param>
public void HashSet(string key, HashEntry[] vals)
{
- throw new NotImplementedException();
+ var dict = key_hash_set.GetOrAdd(key, _ => new ConcurrentDictionary<string, string>());
+ foreach (var entry in vals)
+ {
+ dict[entry.Name.ToString()] = entry.Value.ToString();
+ }
}
-
- //public void HashSetAsync(string key, HashEntry[] vals)
- //{
- // throw new NotImplementedException();
- //}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="seconds"></param>
+ /// <returns></returns>
public bool Lock(string key, int seconds)
{
- return false;
+ // 本地缓存模拟锁:若不存在则创建,存在则失败
+ var lockKey = "__lock__" + key;
+ if (_memoryCache.TryGetValue(lockKey, out _))
+ {
+ return false;
+ }
+ Set(lockKey, "1", seconds);
+ return true;
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="seconds"></param>
+ /// <returns></returns>
public Task<bool> LockAsync(string key, int seconds)
{
- //return Task.Run<bool>(() =>
- //{
- // return Lock(key, seconds);
- //});
- return Task.FromResult(true);
+ return Task.FromResult(Lock(key, seconds));
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="value"></param>
+ /// <param name="expiry"></param>
+ /// <returns></returns>
public bool Set(string key, string value, TimeSpan? expiry = null)
{
using (var wcache = _memoryCache.CreateEntry(key))
@@ -217,30 +286,37 @@ namespace PasteApeart.Handler.redis
wcache.Value = value;
if (expiry == null)
{
- wcache.AbsoluteExpiration = System.DateTimeOffset.Now.AddSeconds(30);
+ wcache.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(30);
}
else
{
wcache.AbsoluteExpiration = DateTimeOffset.Now.Add((TimeSpan)expiry);
}
}
-
return true;
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="value"></param>
+ /// <param name="seconds"></param>
+ /// <returns></returns>
public bool Set(string key, string value, int seconds)
{
using (var wcache = _memoryCache.CreateEntry(key))
{
wcache.Value = value;
-
- wcache.AbsoluteExpiration = System.DateTimeOffset.Now.AddSeconds(seconds);
-
+ wcache.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(seconds);
}
-
return true;
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="value"></param>
+ /// <returns></returns>
public bool Set(string key, string value)
{
using (var wcache = _memoryCache.CreateEntry(key))
@@ -249,52 +325,84 @@ namespace PasteApeart.Handler.redis
}
return true;
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="key"></param>
+ /// <param name="value"></param>
+ /// <param name="expiry"></param>
+ /// <returns></returns>
public bool SetObject<T>(string key, T value, TimeSpan? expiry = null)
{
-
return Set(key, JsonSerializer.Serialize<T>(value, JsonConfig.Options), expiry);
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="key"></param>
+ /// <param name="value"></param>
+ /// <param name="seconds"></param>
+ /// <returns></returns>
public bool SetObject<T>(string key, T value, int seconds)
{
return Set(key, JsonSerializer.Serialize<T>(value, JsonConfig.Options), seconds);
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="value"></param>
+ /// <param name="expiry"></param>
+ /// <returns></returns>
public Task<bool> SetAsync(string key, string value, TimeSpan? expiry = null)
{
- return Task.Run<bool>(() =>
- {
- return Set(key, value, expiry);
- });
+ return Task.FromResult(Set(key, value, expiry));
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="value"></param>
+ /// <param name="seconds"></param>
+ /// <returns></returns>
public Task<bool> SetAsync(string key, string value, int seconds)
{
- return Task.Run<bool>(() =>
- {
- return Set(key, value, seconds);
- });
+ return Task.FromResult(Set(key, value, seconds));
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="key"></param>
+ /// <param name="value"></param>
+ /// <param name="second"></param>
+ /// <returns></returns>
public Task<bool> SetObjectAsync<T>(string key, T value, int second)
{
- return Task.Run<bool>(() =>
- {
- return SetObject(key, value, second);
- });
+ return Task.FromResult(SetObject(key, value, second));
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="expiry"></param>
+ /// <returns></returns>
public bool SetExpire(string key, TimeSpan? expiry)
{
if (_memoryCache.TryGetValue(key, out string sval))
{
-
return Set(key, sval, expiry);
}
return false;
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="seconds"></param>
+ /// <returns></returns>
public bool SetExpire(string key, int seconds)
{
if (_memoryCache.TryGetValue(key, out string sval))
@@ -303,38 +411,57 @@ namespace PasteApeart.Handler.redis
}
return false;
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="seconds"></param>
+ /// <returns></returns>
public Task<bool> SetExpireAsync(string key, int seconds)
{
- return Task.Run<bool>(() =>
- {
- return SetExpire(key, seconds);
- });
+ return Task.FromResult(SetExpire(key, seconds));
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="expiry"></param>
+ /// <returns></returns>
public Task<bool> SetExpireAsync(string key, TimeSpan? expiry)
{
- return Task.Run<bool>(() =>
- {
- return SetExpire(key, expiry);
- });
+ return Task.FromResult(SetExpire(key, expiry));
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="val"></param>
+ /// <param name="second"></param>
+ /// <returns></returns>
public bool SetValue(string key, string val, int second)
{
return Set(key, val, second);
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="val"></param>
+ /// <returns></returns>
public bool SetValue(string key, string val)
{
return Set(key, val);
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <returns></returns>
public bool UnLock(string key)
{
- return false;
+ _memoryCache.Remove("__lock__" + key);
+ return true;
}
-
/// <summary>
///
/// </summary>
@@ -342,121 +469,21 @@ namespace PasteApeart.Handler.redis
/// <returns></returns>
public Task<bool> UnLockAsync(string key)
{
- //return Task.Run<bool>(() =>
- //{
- // return UnLock(key);
- //});
- return Task.FromResult(true);
+ return Task.FromResult(UnLock(key));
}
-
- ///// <summary>
- /////
- ///// </summary>
- ///// <param name="key"></param>
- ///// <param name="vals"></param>
- ///// <returns></returns>
- //public async Task HashSetAsync(string key, HashEntry[] vals, bool isnum = false)
- //{
- // await Task.Run(() =>
- // {
- // if (isnum)
- // {
- // if(key_hash_num.TryGetValue(key, out var _hash))
- // {
- // foreach (var entry in vals)
- // {
- // _hash.AddOrUpdate(entry.Name.ToString(), long.Parse(entry.Value.ToString()), (k, oldValue) => long.Parse(entry.Value.ToString()));
- // }
- // }
- // else
- // {
- // _hash = new ConcurrentDictionary<string, long>();
-
- // foreach (var entry in vals)
- // {
- // _hash.AddOrUpdate(entry.Name.ToString(), long.Parse(entry.Value.ToString()), (k, oldValue) => long.Parse(entry.Value.ToString()));
- // }
- // key_hash_num.TryAdd(key, _hash);
- // }
- // }
- // else
- // {
- // key_hash_set.TryGetValue(key, out var _hash);
- // if (_hash == null || _hash == default)
- // {
- // _hash = new ConcurrentDictionary<string, string>();
- // }
- // foreach (var entry in vals)
- // {
- // _hash.AddOrUpdate(entry.Name.ToString(), entry.Value.ToString(), (k, oldValue) => entry.Value.ToString());
- // }
- // key_hash_set.AddOrUpdate(key, _hash, (k, oldvalue) => _hash);
- // }
-
-
- // });
- //}
-
- //public List<HashKeyValue> HashGetAll(string key)
- //{
- // throw new NotImplementedException();
- //}
-
- //public Task<List<HashKeyValue>> HashGetAllAsync(string key)
- //{
- // throw new NotImplementedException();
- //}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="vals"></param>
public void HashSet(string key, List<HashKeyValue> vals)
{
- throw new NotImplementedException();
+ var dict = key_hash_set.GetOrAdd(key, _ => new ConcurrentDictionary<string, string>());
+ foreach (var entry in vals)
+ {
+ dict[entry.Key] = entry.Value;
+ }
}
-
- ///// <summary>
- /////
- ///// </summary>
- ///// <param name="key"></param>
- ///// <param name="vals"></param>
- ///// <returns></returns>
- //public async Task HashSetAsync(string key, List<HashKeyValue> vals, bool isnum = false)
- //{
- // await Task.Run(() =>
- // {
- // if (isnum)
- // {
- // if(key_hash_num.TryGetValue(key, out var _hash))
- // {
- // foreach (var entry in vals)
- // {
- // _hash.AddOrUpdate(entry.Key, long.Parse(entry.Value), (k, oldValue) => long.Parse(entry.Value));
- // }
- // }
- // else
- // {
- // _hash = new ConcurrentDictionary<string, long>();
- // foreach (var entry in vals)
- // {
- // _hash.AddOrUpdate(entry.Key, long.Parse(entry.Value), (k, oldValue) => long.Parse(entry.Value));
- // }
- // key_hash_num.TryAdd(key, _hash);
- // }
- // }
- // else
- // {
- // key_hash_set.TryGetValue(key, out var _hash);
- // if (_hash == null || _hash == default)
- // {
- // _hash = new ConcurrentDictionary<string, string>();
- // }
- // foreach (var entry in vals)
- // {
- // _hash.AddOrUpdate(entry.Key, entry.Value, (k, oldValue) => entry.Value);
- // }
- // key_hash_set.AddOrUpdate(key, _hash, (k, oldvalue) => _hash);
- // }
- // });
- //}
-
/// <summary>
///
/// </summary>
@@ -466,51 +493,10 @@ namespace PasteApeart.Handler.redis
/// <returns></returns>
public Task<long> HashIncrementAsync(string key, string field, long num = 1)
{
- var _result = num;
- key_hash_num.TryGetValue(key, out var _hash);
- if (_hash == null || _hash == default)
- {
- _hash = new ConcurrentDictionary<string, long>() { };
- _hash.TryAdd(field, num);
- key_hash_num.TryAdd(key, _hash);
- }
- else
- {
- if (_hash.ContainsKey(field))
- {
- _hash[field] = _hash[field] + num;
- _result = _hash[field];
- }
- else
- {
- _hash.TryAdd(field, num);
- }
- }
- return Task.FromResult(_result);
+ var dict = key_hash_num.GetOrAdd(key, _ => new ConcurrentDictionary<string, long>());
+ var result = dict.AddOrUpdate(field, num, (k, old) => old + num);
+ return Task.FromResult(result);
}
-
- ///// <summary>
- /////
- ///// </summary>
- ///// <param name="key"></param>
- ///// <param name="start"></param>
- ///// <param name="stop"></param>
- ///// <returns></returns>
- //public Task<SortedSetEntry[]> SortedSetRangeByRankWithScoresAsync(string key, int start = 0, int stop = 1)
- //{
- // if (key_hash_num.TryGetValue(key, out var _hash))
- // {
- // var list = new List<SortedSetEntry>();
- // var hits = _hash.Where(x => x.Value >= start && x.Value < stop).ToList();
- // foreach (var item in hits)
- // {
- // list.Add(new SortedSetEntry(item.Key, item.Value));
- // }
- // return Task.FromResult(list.ToArray());
- // }
- // return Task.FromResult(new SortedSetEntry[] { });
- //}
-
/// <summary>
///
/// </summary>
@@ -518,7 +504,6 @@ namespace PasteApeart.Handler.redis
/// <param name="start"></param>
/// <param name="stop"></param>
/// <returns></returns>
- /// <exception cref="NotImplementedException"></exception>
public Task<RedisValue[]> SortedSetRangeByScoreAsync(string key, long start = 0, long stop = 1)
{
if (key_hash_num.TryGetValue(key, out var _hash))
@@ -536,7 +521,6 @@ namespace PasteApeart.Handler.redis
}
return Task.FromResult(new RedisValue[] { });
}
-
/// <summary>
///
/// </summary>
@@ -546,29 +530,10 @@ namespace PasteApeart.Handler.redis
/// <returns></returns>
public Task<long> SortedSetIncrementAsync(string key, string field, long num = 1)
{
- var _result = num;
- key_hash_num.TryGetValue(key, out var _hash);
- if (_hash == null || _hash == default)
- {
- _hash = new ConcurrentDictionary<string, long>() { };
- _hash.TryAdd(field, num);
- key_hash_num.TryAdd(key, _hash);
- }
- else
- {
- if (_hash.ContainsKey(field))
- {
- _hash[field] = _hash[field] + num;
- _result = _hash[field];
- }
- else
- {
- _hash.TryAdd(field, num);
- }
- }
- return Task.FromResult(_result);
+ var dict = key_hash_num.GetOrAdd(key, _ => new ConcurrentDictionary<string, long>());
+ var result = dict.AddOrUpdate(field, num, (k, old) => old + num);
+ return Task.FromResult(result);
}
-
/// <summary>
///
/// </summary>
@@ -578,29 +543,10 @@ namespace PasteApeart.Handler.redis
/// <returns></returns>
public Task<long> SortedSetDecrementAsync(string key, string field, long num)
{
- var _result = num;
- key_hash_num.TryGetValue(key, out var _hash);
- if (_hash == null || _hash == default)
- {
- _hash = new ConcurrentDictionary<string, long>() { };
- _hash.TryAdd(field, num);
- key_hash_num.TryAdd(key, _hash);
- }
- else
- {
- if (_hash.ContainsKey(field))
- {
- _hash[field] = _hash[field] - num;
- _result = _hash[field];
- }
- else
- {
- _hash.TryAdd(field, num);
- }
- }
- return Task.FromResult(_result);
+ var dict = key_hash_num.GetOrAdd(key, _ => new ConcurrentDictionary<string, long>());
+ var result = dict.AddOrUpdate(field, -num, (k, old) => old - num);
+ return Task.FromResult(result);
}
-
/// <summary>
///
/// </summary>
@@ -609,18 +555,12 @@ namespace PasteApeart.Handler.redis
/// <returns></returns>
public Task<bool> SortedSetRemoveAsync(string key, string field)
{
- var _result = false;
if (key_hash_num.TryGetValue(key, out var _hash))
{
- if (_hash.ContainsKey(field))
- {
- _hash.Remove(field, out _);
- _result = true;
- }
+ return Task.FromResult(_hash.TryRemove(field, out _));
}
- return Task.FromResult(_result);
+ return Task.FromResult(false);
}
-
/// <summary>
///
/// </summary>
@@ -630,44 +570,24 @@ namespace PasteApeart.Handler.redis
/// <returns></returns>
public Task<bool> SortedSetAddAsync(string key, string field, long num)
{
- if (key_hash_num.TryGetValue(key, out var _hash))
- {
- if (_hash.ContainsKey(field))
- {
- _hash[field] = num;
- }
- else
- {
- _hash.TryAdd(field, num);
- }
- }
- else
- {
- _hash = new ConcurrentDictionary<string, long>() { };
- _hash.TryAdd(field, num);
- key_hash_num.TryAdd(key, _hash);
- }
+ var dict = key_hash_num.GetOrAdd(key, _ => new ConcurrentDictionary<string, long>());
+ dict[field] = num;
return Task.FromResult(true);
}
-
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
- /// <exception cref="NotImplementedException"></exception>
public Task<bool> ExistsAsync(string key)
{
- var _result = _memoryCache.TryGetValue(key, out var val);
- return Task.FromResult(_result);
+ return Task.FromResult(Exists(key));
}
-
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
- /// <exception cref="NotImplementedException"></exception>
public Task<List<HashKeyValue>> HashGetAllAsync(string key)
{
if (key_hash_set.TryGetValue(key, out var _hash))
@@ -684,13 +604,12 @@ namespace PasteApeart.Handler.redis
var finds = new List<HashKeyValue>();
foreach (var item in _hash_num)
{
- finds.Add(new HashKeyValue { Key = item.Key, Value = item.ToString() });
+ finds.Add(new HashKeyValue { Key = item.Key, Value = item.Value.ToString() });
}
return Task.FromResult(finds);
}
return Task.FromResult(new List<HashKeyValue> { });
}
-
/// <summary>
///
/// </summary>
@@ -699,30 +618,10 @@ namespace PasteApeart.Handler.redis
/// <returns></returns>
public Task<long> HashDecrementAsync(string key, string field)
{
- var num = 1;
- long _result = num;
- key_hash_num.TryGetValue(key, out var _hash);
- if (_hash == null || _hash == default)
- {
- _hash = new ConcurrentDictionary<string, long>() { };
- _hash.TryAdd(field, 0 - num);
- key_hash_num.TryAdd(key, _hash);
- }
- else
- {
- if (_hash.ContainsKey(field))
- {
- _hash[field] = _hash[field] - num;
- _result = _hash[field];
- }
- else
- {
- _hash.TryAdd(field, num);
- }
- }
- return Task.FromResult(_result);
+ var dict = key_hash_num.GetOrAdd(key, _ => new ConcurrentDictionary<string, long>());
+ var result = dict.AddOrUpdate(field, -1, (k, old) => old - 1);
+ return Task.FromResult(result);
}
-
/// <summary>
///
/// </summary>
@@ -732,33 +631,23 @@ namespace PasteApeart.Handler.redis
public Task<bool> HashExistsAsync(string key, string filed)
{
var _result = false;
-
- if (key_hash_num.TryGetValue(key, out var _hash))
+ if (key_hash_num.TryGetValue(key, out var _hash) && _hash.ContainsKey(filed))
{
- if (_hash.ContainsKey(filed))
- {
- _result = true;
- }
+ _result = true;
}
- if (!_result)
+ if (!_result && key_hash_set.TryGetValue(key, out var hash_key) && hash_key.ContainsKey(filed))
{
- if (key_hash_set.TryGetValue(key, out var hash_key))
- {
- if (hash_key.ContainsKey(filed))
- {
- _result = true;
- }
- }
+ _result = true;
}
- return Task.FromResult(true);
+ return Task.FromResult(_result);
}
-
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <param name="field"></param>
/// <param name="value"></param>
+ /// <param name="isnum"></param>
/// <returns></returns>
public async Task HashSetAsync(string key, string field, RedisValue value, bool isnum = false)
{
@@ -766,33 +655,19 @@ namespace PasteApeart.Handler.redis
{
if (isnum)
{
- if (key_hash_num.TryGetValue(key, out var hash_key))
- {
- hash_key.AddOrUpdate(field, long.Parse(value.ToString()), (n, o) => long.Parse(value.ToString()));
- }
- else
+ var dict = key_hash_num.GetOrAdd(key, _ => new ConcurrentDictionary<string, long>());
+ if (long.TryParse(value.ToString(), out var numVal))
{
- var find = new ConcurrentDictionary<string, long>();
- find.TryAdd(field, long.Parse(value.ToString()));
- key_hash_num.TryAdd(key, find);
+ dict[field] = numVal;
}
}
else
{
- if (key_hash_set.TryGetValue(key, out var hash_key))
- {
- hash_key.AddOrUpdate(field, value.ToString(), (n, o) => value.ToString());
- }
- else
- {
- var find = new ConcurrentDictionary<string, string>();
- find.TryAdd(field, value.ToString());
- key_hash_set.TryAdd(key, find);
- }
+ var dict = key_hash_set.GetOrAdd(key, _ => new ConcurrentDictionary<string, string>());
+ dict[field] = value.ToString();
}
});
}
-
/// <summary>
///
/// </summary>
@@ -802,20 +677,16 @@ namespace PasteApeart.Handler.redis
/// <returns></returns>
public Task<T> HashGetObjectAsync<T>(string key, string field)
{
- if (key_hash_set.TryGetValue(key, out var hash_key))
+ if (key_hash_set.TryGetValue(key, out var hash_key) && hash_key.TryGetValue(field, out var _value))
{
- if (hash_key.TryGetValue(field, out var _value))
+ if (!String.IsNullOrEmpty(_value))
{
- if (!String.IsNullOrEmpty(_value))
- {
- var t = JsonSerializer.Deserialize<T>(_value, JsonConfig.Options);// Newtonsoft.Json.JsonConvert.DeserializeObject<T>(_value);
- return Task.FromResult(t);
- }
+ var t = JsonSerializer.Deserialize<T>(_value, JsonConfig.Options);
+ return Task.FromResult(t);
}
}
return Task.FromResult(default(T));
}
-
/// <summary>
///
/// </summary>
@@ -827,22 +698,10 @@ namespace PasteApeart.Handler.redis
public Task<bool> HashSetObjectAsync<T>(string key, string field, T entity)
{
var value = JsonSerializer.Serialize<T>(entity, JsonConfig.Options);
- //Newtonsoft.Json.JsonConvert.SerializeObject(entity);
- if (key_hash_set.TryGetValue(key, out var hash_key))
- {
-
- hash_key.AddOrUpdate(field, value, (n, o) => value);
-
- }
- else
- {
- var find = new ConcurrentDictionary<string, string>();
- find.TryAdd(field, value);
- key_hash_set.TryAdd(key, find);
- }
+ var dict = key_hash_set.GetOrAdd(key, _ => new ConcurrentDictionary<string, string>());
+ dict[field] = value;
return Task.FromResult(true);
}
-
/// <summary>
///
/// </summary>
@@ -850,34 +709,30 @@ namespace PasteApeart.Handler.redis
/// <param name="pattern"></param>
/// <param name="page"></param>
/// <param name="size"></param>
+ /// <param name="isincom"></param>
/// <returns></returns>
public Task<List<HashEntry>> HashScanAsync(string key, string pattern, int page, int size, bool isincom = false)
{
+ //Func<KeyValuePair<string, long>, bool> numFilter = null;
+ //Func<KeyValuePair<string, string>, bool> setFilter = null;
+
+ var position = 3; //1left 2right 3like
+ if (pattern.StartsWith("*")) position = 1;
+ if (pattern.EndsWith("*"))
+ {
+ if (position == 1) position = 3;
+ else position = 2;
+ }
+ var realPattern = pattern.Replace("*", "");
+
if (isincom)
{
if (key_hash_num.TryGetValue(key, out var hash_key))
{
- var position = 3;//1left 2right 3like
- if (pattern.StartsWith("*"))
- {
- position = 1;
- }
- if (pattern.EndsWith("*"))
- {
- if (position == 1)
- {
- position = 3;
- }
- else
- {
- position = 2;
- }
- }
- pattern = pattern.Replace("*", "");
var vals = hash_key
- .PasteWhereIf(position == 1, x => x.Key.EndsWith(pattern))
- .PasteWhereIf(position == 2, x => x.Key.StartsWith(pattern))
- .PasteWhereIf(position == 3, x => x.Key.Contains(pattern))
+ .PasteWhereIf(position == 1, x => x.Key.EndsWith(realPattern))
+ .PasteWhereIf(position == 2, x => x.Key.StartsWith(realPattern))
+ .PasteWhereIf(position == 3, x => x.Key.Contains(realPattern))
.OrderBy(x => x.Key)
.ToList();
var start = (page - 1) * size;
@@ -890,10 +745,7 @@ namespace PasteApeart.Handler.redis
var item = vals[k];
list.Add(new HashEntry(item.Key, item.Value));
}
- if (k > end)
- {
- break;
- }
+ if (k >= end) break;
}
return Task.FromResult(list);
}
@@ -902,27 +754,10 @@ namespace PasteApeart.Handler.redis
{
if (key_hash_set.TryGetValue(key, out var hash_key))
{
- var position = 3;//1left 2right 3like
- if (pattern.StartsWith("*"))
- {
- position = 1;
- }
- if (pattern.EndsWith("*"))
- {
- if (position == 1)
- {
- position = 3;
- }
- else
- {
- position = 2;
- }
- }
- pattern = pattern.Replace("*", "");
var vals = hash_key
- .PasteWhereIf(position == 1, x => x.Key.StartsWith(pattern))
- .PasteWhereIf(position == 2, x => x.Key.EndsWith(pattern))
- .PasteWhereIf(position == 3, x => x.Key.Contains(pattern))
+ .PasteWhereIf(position == 1, x => x.Key.StartsWith(realPattern))
+ .PasteWhereIf(position == 2, x => x.Key.EndsWith(realPattern))
+ .PasteWhereIf(position == 3, x => x.Key.Contains(realPattern))
.OrderBy(x => x.Key)
.ToList();
var start = (page - 1) * size;
@@ -935,22 +770,19 @@ namespace PasteApeart.Handler.redis
var item = vals[k];
list.Add(new HashEntry(item.Key, item.Value));
}
- if (k > end)
- {
- break;
- }
+ if (k >= end) break;
}
return Task.FromResult(list);
}
}
return Task.FromResult(new List<HashEntry> { });
}
-
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <param name="fields"></param>
+ /// <param name="isnum"></param>
/// <returns></returns>
public Task<RedisValue[]> HashGetAsync(string key, RedisValue[] fields, bool isnum = false)
{
@@ -961,10 +793,7 @@ namespace PasteApeart.Handler.redis
{
var haves = hash_key.Where(x => fis.Contains(x.Key)).ToList();
var reds = new List<RedisValue>();
- foreach (var kv in haves)
- {
- reds.Add(kv.Value);
- }
+ foreach (var kv in haves) reds.Add(kv.Value);
return Task.FromResult(reds.ToArray());
}
}
@@ -974,168 +803,115 @@ namespace PasteApeart.Handler.redis
{
var haves = hash_key.Where(x => fis.Contains(x.Key)).ToList();
var reds = new List<RedisValue>();
- foreach (var kv in haves)
- {
- reds.Add(kv.Value);
- }
+ foreach (var kv in haves) reds.Add(kv.Value);
return Task.FromResult(reds.ToArray());
}
}
return Task.FromResult(new RedisValue[] { });
}
-
-
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <param name="field"></param>
/// <returns></returns>
- public async Task<bool> HashDeleteAsync(string key, string field)
+ public Task<bool> HashDeleteAsync(string key, string field)
{
- await Task.Run(() =>
+ var _result = false;
+ if (key_hash_set.TryGetValue(key, out var hash_key) && hash_key.TryRemove(field, out _))
{
- var _result = false;
- if (key_hash_set.TryGetValue(key, out var hash_key))
- {
- if (hash_key.ContainsKey(field))
- {
- _result = true;
- }
- hash_key.Remove(field, out var abc);
- }
- if (!_result)
- {
- if (key_hash_num.TryGetValue(key, out var _hash))
- {
- if (_hash.ContainsKey(field))
- {
- _result = true;
- }
- _hash.Remove(field, out var abc);
- }
- }
- return _result;
- });
- return false;
+ _result = true;
+ }
+ if (key_hash_num.TryGetValue(key, out var _hash) && _hash.TryRemove(field, out _))
+ {
+ _result = true;
+ }
+ return Task.FromResult(_result);
}
-
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <param name="fields"></param>
/// <returns></returns>
- /// <exception cref="NotImplementedException"></exception>
public Task<bool> HashDeleteAsync(string key, RedisValue[] fields)
{
var fis = fields.Select(x => x.ToString()).ToArray();
+ var _result = false;
if (key_hash_set.TryGetValue(key, out var hash_key))
{
foreach (var kv in fis)
{
- hash_key.Remove(kv, out var va);
+ if (hash_key.TryRemove(kv, out _)) _result = true;
}
- var haves = hash_key.Where(x => fis.Contains(x.Key)).ToList();
- var reds = new List<RedisValue>();
- foreach (var kv in haves)
+ }
+ if (key_hash_num.TryGetValue(key, out var num_key))
+ {
+ foreach (var kv in fis)
{
- reds.Add(kv.Value);
+ if (num_key.TryRemove(kv, out _)) _result = true;
}
- return Task.FromResult(true);
}
- return Task.FromResult(false);
+ return Task.FromResult(_result);
}
-
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
- /// <exception cref="NotImplementedException"></exception>
public Task<long> HashLengthAsync(string key)
{
- if (key_hash_set.TryGetValue(key, out var hash_key))
- {
- return Task.FromResult((long)hash_key.Keys.Count);
- }
- return Task.FromResult((long)0);
+ long count = 0;
+ if (key_hash_set.TryGetValue(key, out var hash_key)) count += hash_key.Count;
+ if (key_hash_num.TryGetValue(key, out var num_key)) count += num_key.Count;
+ return Task.FromResult(count);
}
-
/// <summary>
- /// 打印
+ ///
/// </summary>
/// <returns></returns>
public string Print()
{
var sb = new StringBuilder();
-
if (key_hash_set != null && key_hash_set.Any())
{
- //sb.AppendLine(Newtonsoft.Json.JsonConvert.SerializeObject(key_hash_set));
sb.AppendLine(JsonSerializer.Serialize(key_hash_set, JsonConfig.Options));
}
-
if (key_hash_num != null && key_hash_num.Any())
{
- //sb.AppendLine(Newtonsoft.Json.JsonConvert.SerializeObject(key_hash_num));
- sb.AppendLine(JsonSerializer.Serialize(key_hash_set, JsonConfig.Options));
+ sb.AppendLine(JsonSerializer.Serialize(key_hash_num, JsonConfig.Options));
+ }
+ if (key_set != null && key_set.Any())
+ {
+ sb.AppendLine(JsonSerializer.Serialize(key_set, JsonConfig.Options));
+ }
+ if (key_list != null && key_list.Any())
+ {
+ sb.AppendLine(JsonSerializer.Serialize(key_list, JsonConfig.Options));
}
-
return sb.ToString();
}
-
//------------------------------------------------
-
- //private readonly IMemoryCache _memoryCache;
private static readonly Random _random = new();
-
- //public MemoryClient(IMemoryCache memoryCache)
- //{
- // _memoryCache = memoryCache;
- //}
-
- //public bool IsRedis => false;
-
- #region 同步方法
-
- //public bool Delete(string key)
- //{
- // _memoryCache.Remove(key);
- // return true;
- //}
-
- //public bool Exists(string key)
- //{
- // return _memoryCache.TryGetValue(key, out _);
- //}
-
- //public string Get(string key)
- //{
- // return _memoryCache.TryGetValue(key, out string? val) ? val ?? string.Empty : string.Empty;
- //}
-
- //public T GetObject<T>(string key)
- //{
- // if (_memoryCache.TryGetValue(key, out string? val) && !string.IsNullOrEmpty(val))
- // {
- // return JsonConvert.DeserializeObject<T>(val);
- // }
- // return default;
- //}
-
- //public string GetStringValue(string key)
- //{
- // return Get(key);
- //}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <returns></returns>
public object TryGetValue(string key)
{
return _memoryCache.TryGetValue(key, out var val) ? val : null;
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="key"></param>
+ /// <param name="factory"></param>
+ /// <param name="expiration"></param>
+ /// <returns></returns>
public T GetOrCreate<T>(string key, Func<ICacheEntry, T> factory, TimeSpan? expiration = null)
{
return _memoryCache.GetOrCreate(key, entry =>
@@ -1144,37 +920,13 @@ namespace PasteApeart.Handler.redis
return factory(entry);
});
}
-
- //public bool Set(string key, string value, TimeSpan? expiry = null)
- //{
- // using var entry = _memoryCache.CreateEntry(key);
- // entry.Value = value;
- // SetCacheEntryOptions(entry, expiry);
- // return true;
- //}
-
- //public bool Set(string key, string value, int seconds)
- //{
- // return Set(key, value, TimeSpan.FromSeconds(seconds));
- //}
-
- //public bool Set(string key, string value)
- //{
- // using var entry = _memoryCache.CreateEntry(key);
- // entry.Value = value;
- // return true;
- //}
-
- //public bool SetObject<T>(string key, T value, TimeSpan? expiry = null)
- //{
- // return Set(key, JsonConvert.SerializeObject(value), expiry);
- //}
-
- //public bool SetObject<T>(string key, T value, int seconds)
- //{
- // return Set(key, JsonConvert.SerializeObject(value), TimeSpan.FromSeconds(seconds));
- //}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="value"></param>
+ /// <param name="expiry"></param>
+ /// <returns></returns>
public bool CreateEntry(string key, object value, TimeSpan? expiry = null)
{
using var entry = _memoryCache.CreateEntry(key);
@@ -1183,51 +935,12 @@ namespace PasteApeart.Handler.redis
return true;
}
- //public bool SetValue(string key, string val, int second)
- //{
- // return Set(key, val, second);
- //}
-
- //public bool SetValue(string key, string val)
- //{
- // return Set(key, val);
- //}
-
- //public bool SetExpire(string key, TimeSpan? expiry)
- //{
- // if (_memoryCache.TryGetValue(key, out string? val))
- // {
- // return Set(key, val ?? string.Empty, expiry);
- // }
- // return false;
- //}
-
- //public bool SetExpire(string key, int seconds)
- //{
- // return SetExpire(key, TimeSpan.FromSeconds(seconds));
- //}
-
- //public bool Lock(string key, int seconds)
- //{
- // // MemoryCache 不支持分布式锁,直接返回 true
- // return true;
- //}
-
- //public bool UnLock(string key)
- //{
- // return true;
- //}
-
- #endregion
-
- #region 异步方法(同步包装,返回 Task)
-
- //public Task<bool> DeleteAsync(string key)
- //{
- // Delete(key);
- // return Task.FromResult(true);
- //}
-
+ #region 异步方法
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="keys"></param>
+ /// <returns></returns>
public Task BatchRemoveAsync(string[] keys)
{
if (keys != null)
@@ -1236,28 +949,20 @@ namespace PasteApeart.Handler.redis
{
if (!string.IsNullOrEmpty(key))
{
- _memoryCache.Remove(key);
+ Delete(key);
}
}
}
return Task.CompletedTask;
}
-
- //public Task<bool> ExistsAsync(string key)
- //{
- // return Task.FromResult(Exists(key));
- //}
-
- //public Task<string> GetAsync(string key)
- //{
- // return Task.FromResult(Get(key));
- //}
-
- //public Task<T?> GetObjectAsync<T>(string key)
- //{
- // return Task.FromResult(GetObject<T>(key));
- //}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="key"></param>
+ /// <param name="factory"></param>
+ /// <param name="expiration"></param>
+ /// <returns></returns>
public Task<T> GetOrCreateAsync<T>(string key, Func<ICacheEntry, Task<T>> factory, TimeSpan? expiration = null)
{
return _memoryCache.GetOrCreateAsync(key, async entry =>
@@ -1267,114 +972,38 @@ namespace PasteApeart.Handler.redis
});
}
- //public Task<bool> SetAsync(string key, string value, TimeSpan? expiry = null)
- //{
- // return Task.FromResult(Set(key, value, expiry));
- //}
-
- //public Task<bool> SetAsync(string key, string value, int seconds)
- //{
- // return Task.FromResult(Set(key, value, seconds));
- //}
-
- //public Task<bool> SetObjectAsync<T>(string key, T value, int second)
- //{
- // return Task.FromResult(SetObject(key, value, second));
- //}
-
- //public Task<bool> SetExpireAsync(string key, int seconds)
- //{
- // return Task.FromResult(SetExpire(key, seconds));
- //}
-
- //public Task<bool> SetExpireAsync(string key, TimeSpan? expiry)
- //{
- // return Task.FromResult(SetExpire(key, expiry));
- //}
-
- //public Task<bool> LockAsync(string key, int seconds)
- //{
- // return Task.FromResult(Lock(key, seconds));
- //}
-
- //public Task<bool> UnLockAsync(string key)
- //{
- // return Task.FromResult(UnLock(key));
- //}
-
#endregion
#region Hash 操作
-
- //public string HashGet(string key, string subKey)
- //{
- // if (_memoryCache.TryGetValue(key, out var obj) && obj is Dictionary<string, string> dict)
- // {
- // return dict.TryGetValue(subKey, out var val) ? val : string.Empty;
- // }
- // return string.Empty;
- //}
-
- //public HashEntry[] HashGetAll(string key)
- //{
- // if (_memoryCache.TryGetValue(key, out var obj) && obj is Dictionary<string, string> dict)
- // {
- // return dict.Select(x => new HashEntry(x.Key, x.Value)).ToArray();
- // }
- // return Array.Empty<HashEntry>();
- //}
-
- //public void HashSet(string key, HashEntry[] vals)
- //{
- // var dict = _memoryCache.TryGetValue(key, out var obj) && obj is Dictionary<string, string> existing
- // ? existing
- // : new Dictionary<string, string>();
-
- // foreach (var entry in vals)
- // {
- // dict[entry.Name.ToString()] = entry.Value.ToString();
- // }
-
- // _memoryCache.Set(key, dict);
- //}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="subKey"></param>
+ /// <returns></returns>
public Task<string> HashGetAsync(string key, string subKey)
{
return Task.FromResult(HashGet(key, subKey));
}
-
- //public Task<HashEntry[]> HashGetAllAsync(string key)
- //{
- // return Task.FromResult(HashGetAll(key));
- //}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="vals"></param>
+ /// <returns></returns>
public Task HashSetAsync(string key, HashEntry[] vals)
{
HashSet(key, vals);
return Task.CompletedTask;
}
-
- ///// <summary>
- /////
- ///// </summary>
- ///// <param name="key"></param>
- ///// <param name="field"></param>
- ///// <returns></returns>
- //public Task<bool> HashDeleteAsync(string key, string field)
- //{
- // if (_memoryCache.TryGetValue(key, out var obj) && obj is Dictionary<string, string> dict)
- // {
- // if (dict.ContainsKey(field))
- // {
- // dict.Remove(field);
- // }
- // }
- // return Task.FromResult(true);
- //}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <returns></returns>
public Task<HashEntry> HashRandomFieldsWithValuesAsync(string key)
{
- if (_memoryCache.TryGetValue(key, out var obj) && obj is Dictionary<string, string> dict && dict.Count > 0)
+ if (key_hash_set.TryGetValue(key, out var dict) && dict.Count > 0)
{
var keys = dict.Keys.ToArray();
var randomKey = keys[_random.Next(keys.Length)];
@@ -1382,21 +1011,26 @@ namespace PasteApeart.Handler.redis
}
return Task.FromResult(new HashEntry(string.Empty, string.Empty));
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="field"></param>
+ /// <param name="num"></param>
+ /// <returns></returns>
public Task<long> HashIncrementAsync(string key, RedisValue field, long num = 1)
{
- // MemoryCache 不支持原子增减,简单实现
- var current = HashGet(key, field.ToString());
- if (long.TryParse(current, out var value))
- {
- var newValue = value + num;
- HashSet(key, new[] { new HashEntry(field, newValue.ToString()) });
- return Task.FromResult(newValue);
- }
- HashSet(key, new[] { new HashEntry(field, num.ToString()) });
- return Task.FromResult(num);
+ var dict = key_hash_num.GetOrAdd(key, _ => new ConcurrentDictionary<string, long>());
+ var result = dict.AddOrUpdate(field.ToString(), num, (k, old) => old + num);
+ return Task.FromResult(result);
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="field"></param>
+ /// <param name="num"></param>
+ /// <returns></returns>
public Task<long> HashDecrementAsync(string key, RedisValue field, long num = 1)
{
return HashIncrementAsync(key, field, -num);
@@ -1404,31 +1038,62 @@ namespace PasteApeart.Handler.redis
#endregion
- #region 未实现的方法(抛出明确异常)
-
- //public void HashSet(string key, List<HashKeyValue> vals)
- //{
- // throw new NotImplementedException("MemoryCache 不支持此操作");
- //}
-
+ #region 未实现的方法(全部补齐)
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="vals"></param>
+ /// <returns></returns>
public Task HashSetAsync(string key, List<HashKeyValue> vals)
{
- throw new NotImplementedException("MemoryCache 不支持此操作");
- }
-
- List<HashKeyValue> IAppCache.HashGetAll(string key)
- {
- throw new NotImplementedException("MemoryCache 不支持此操作");
+ HashSet(key, vals);
+ return Task.CompletedTask;
}
-
- Task<List<HashKeyValue>> IAppCache.HashGetAllAsync(string key)
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <returns></returns>
+ public List<HashKeyValue> HashGetAll(string key)
{
- throw new NotImplementedException("MemoryCache 不支持此操作");
+ var result = new List<HashKeyValue>();
+ if (key_hash_set.TryGetValue(key, out var _hash))
+ {
+ foreach (var item in _hash) result.Add(new HashKeyValue { Key = item.Key, Value = item.Value });
+ return result;
+ }
+ if (key_hash_num.TryGetValue(key, out var _hash_num))
+ {
+ foreach (var item in _hash_num) result.Add(new HashKeyValue { Key = item.Key, Value = item.Value.ToString() });
+ return result;
+ }
+ return result;
}
-
+ ///// <summary>
+ /////
+ ///// </summary>
+ ///// <param name="key"></param>
+ ///// <returns></returns>
+ //Task<List<HashKeyValue>> IAppCache.HashGetAllAsync(string key)
+ //{
+ // return Task.FromResult(((IAppCache)this).HashGetAll(key));
+ //}
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="pattern"></param>
+ /// <param name="size"></param>
+ /// <param name="cursor"></param>
+ /// <param name="offset"></param>
+ /// <returns></returns>
public Task<HashEntry[]> HashScanAsync(string key, string pattern, int size = 1, int cursor = 0, int offset = 0)
{
- throw new NotImplementedException("MemoryCache 不支持 HashScan");
+ // 简化实现:按 cursor 当 page, size 当每页大小
+ var page = cursor <= 0 ? 1 : cursor;
+ var task = HashScanAsync(key, pattern, page, size, false);
+ return Task.FromResult(task.Result.ToArray());
}
#endregion
@@ -1447,84 +1112,234 @@ namespace PasteApeart.Handler.redis
}
}
+ #endregion
+
+ #region HashIncrement(int) / ReadString / ReadObject / Set / List / SortedSet 补齐
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="felid"></param>
+ /// <param name="num"></param>
+ /// <returns></returns>
public Task HashIncrementAsync(string key, string felid, int num = 1)
{
- throw new NotImplementedException();
+ var dict = key_hash_num.GetOrAdd(key, _ => new ConcurrentDictionary<string, long>());
+ var result = dict.AddOrUpdate(felid, num, (k, old) => old + num);
+ return Task.FromResult(result);
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <returns></returns>
public Task<string> ReadStringAsync(string key)
{
- throw new NotImplementedException();
+ return Task.FromResult(Get(key));
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="key"></param>
+ /// <returns></returns>
public Task<T> ReadObjectAsync<T>(string key)
{
- throw new NotImplementedException();
+ return Task.FromResult(GetObject<T>(key));
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="skey"></param>
+ /// <param name="val"></param>
+ /// <returns></returns>
public Task<bool> SetAddAsync(string skey, int val)
{
- throw new NotImplementedException();
+ var set = key_set.GetOrAdd(skey, _ => new ConcurrentDictionary<int, byte>());
+ return Task.FromResult(set.TryAdd(val, 0));
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="skey"></param>
+ /// <param name="filed"></param>
+ /// <returns></returns>
public Task<bool> SetContainsAsync(string skey, int filed)
{
- throw new NotImplementedException();
+ if (key_set.TryGetValue(skey, out var set))
+ {
+ return Task.FromResult(set.ContainsKey(filed));
+ }
+ return Task.FromResult(false);
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="skey"></param>
+ /// <param name="filed"></param>
+ /// <returns></returns>
public Task<bool> SetRemoveAsync(string skey, int filed)
{
- throw new NotImplementedException();
+ if (key_set.TryGetValue(skey, out var set))
+ {
+ return Task.FromResult(set.TryRemove(filed, out _));
+ }
+ return Task.FromResult(false);
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="skey"></param>
+ /// <returns></returns>
public Task<long> SetRandomMemberAsync(string skey)
{
- throw new NotImplementedException();
+ if (key_set.TryGetValue(skey, out var set) && set.Count > 0)
+ {
+ var keys = set.Keys.ToArray();
+ return Task.FromResult((long)keys[_random.Next(keys.Length)]);
+ }
+ return Task.FromResult(0L);
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="skey"></param>
+ /// <returns></returns>
public Task<long> SetLengthAsync(string skey)
{
- throw new NotImplementedException();
+ if (key_set.TryGetValue(skey, out var set))
+ {
+ return Task.FromResult((long)set.Count);
+ }
+ return Task.FromResult(0L);
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="skey"></param>
+ /// <param name="sval"></param>
+ /// <returns></returns>
public Task<long> ListRightPushAsync(string skey, string sval)
{
- throw new NotImplementedException();
+ lock (_listLock)
+ {
+ var list = key_list.GetOrAdd(skey, _ => new List<string>());
+ list.Add(sval);
+ return Task.FromResult((long)list.Count);
+ }
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="skey"></param>
+ /// <param name="score"></param>
+ /// <returns></returns>
public Task<string> SortedSetRangeByScoreAsync(string skey, long score)
{
- throw new NotImplementedException();
+ if (key_hash_num.TryGetValue(skey, out var _hash))
+ {
+ var item = _hash.FirstOrDefault(x => x.Value == score);
+ if (item.Key != null)
+ {
+ return Task.FromResult(item.Key);
+ }
+ }
+ return Task.FromResult(string.Empty);
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="skey"></param>
+ /// <returns></returns>
public Task<long> SortedSetRangeByRankWithScoresAsync(string skey)
{
- throw new NotImplementedException();
+ if (key_hash_num.TryGetValue(skey, out var _hash))
+ {
+ return Task.FromResult((long)_hash.Count);
+ }
+ return Task.FromResult(0L);
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="skey"></param>
+ /// <returns></returns>
public Task<long> ListLengthAsync(string skey)
{
- throw new NotImplementedException();
+ lock (_listLock)
+ {
+ if (key_list.TryGetValue(skey, out var list))
+ {
+ return Task.FromResult((long)list.Count);
+ }
+ return Task.FromResult(0L);
+ }
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="skey"></param>
+ /// <returns></returns>
public Task<string> ListLeftPopAsync(string skey)
{
- throw new NotImplementedException();
+ lock (_listLock)
+ {
+ if (key_list.TryGetValue(skey, out var list) && list.Count > 0)
+ {
+ var val = list[0];
+ list.RemoveAt(0);
+ return Task.FromResult(val);
+ }
+ return Task.FromResult(string.Empty);
+ }
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="skey"></param>
+ /// <param name="start"></param>
+ /// <param name="stop"></param>
+ /// <returns></returns>
public Task<List<string>> ListRangeAsync(string skey, int start = 0, int stop = 30)
{
- throw new NotImplementedException();
+ lock (_listLock)
+ {
+ if (key_list.TryGetValue(skey, out var list))
+ {
+ if (start < 0) start = 0;
+ if (stop >= list.Count) stop = list.Count - 1;
+ if (start > stop) return Task.FromResult(new List<string>());
+ return Task.FromResult(list.GetRange(start, stop - start + 1));
+ }
+ return Task.FromResult(new List<string>());
+ }
}
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="skey"></param>
+ /// <param name="start"></param>
+ /// <param name="stop"></param>
+ /// <returns></returns>
public Task<List<T>> ListRangeAsync<T>(string skey, int start = 0, int stop = 30)
{
- throw new NotImplementedException();
+ var strList = ListRangeAsync(skey, start, stop).Result;
+ var result = new List<T>();
+ foreach (var s in strList)
+ {
+ try
+ {
+ result.Add(JsonSerializer.Deserialize<T>(s, JsonConfig.Options));
+ }
+ catch
+ {
+ // 忽略反序列化失败项
+ }
+ }
+ return Task.FromResult(result);
}
#endregion
-
-
}
-
-}
+}
\ No newline at end of file
framework/PasteApeart.Handler/redis/RedisClient.cs
diff --git a/framework/PasteApeart.Handler/redis/RedisClient.cs b/framework/PasteApeart.Handler/redis/RedisClient.cs
index 7f68d6d..a9b27d4 100644
--- a/framework/PasteApeart.Handler/redis/RedisClient.cs
+++ b/framework/PasteApeart.Handler/redis/RedisClient.cs
@@ -434,6 +434,27 @@ namespace PasteApeart.Handler.redis
return result;
}
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <returns></returns>
+ public HashEntry[] HashGetAllEntry(string key)
+ {
+ return _database.HashGetAll(setKey(key));
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <returns></returns>
+ public async Task<HashEntry[]> HashGetAllEntryAsync(string key)
+ {
+ return await _database.HashGetAllAsync(setKey(key));
+ }
+
/// <summary>
///
/// </summary>
@@ -470,6 +491,8 @@ namespace PasteApeart.Handler.redis
/// </summary>
/// <param name="key"></param>
/// <param name="vals"></param>
+ /// <param name="isnum"></param>
+ /// <returns></returns>
public async Task HashSetAsync(string key, HashEntry[] vals, bool isnum = false)
{
await _database.HashSetAsync(setKey(key), vals);
@@ -479,12 +502,21 @@ namespace PasteApeart.Handler.redis
///
/// </summary>
/// <param name="key"></param>
- /// <param name="vals"></param>
+ /// <param name="field"></param>
+ /// <param name="value"></param>
+ /// <param name="isnum"></param>
+ /// <returns></returns>
public async Task HashSetAsync(string key, string field, RedisValue value, bool isnum = false)
{
await _database.HashSetAsync(setKey(key), field, value);
}
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="sunkey"></param>
+ /// <returns></returns>
public string HashGet(string key, string sunkey)
{
return _database.HashGet(setKey(key), sunkey);
@@ -495,6 +527,7 @@ namespace PasteApeart.Handler.redis
/// </summary>
/// <param name="key"></param>
/// <param name="sunkey"></param>
+ /// <param name="isnum"></param>
/// <returns></returns>
public async Task<string> HashGetAsync(string key, string sunkey, bool isnum = false)
{
@@ -503,10 +536,11 @@ namespace PasteApeart.Handler.redis
/// <summary>
- /// 同时获取多个
+ ///
/// </summary>
/// <param name="key"></param>
- /// <param name="sunkey"></param>
+ /// <param name="fields"></param>
+ /// <param name="isinnum"></param>
/// <returns></returns>
public async Task<RedisValue[]> HashGetAsync(string key, RedisValue[] fields, bool isinnum = false)
{
@@ -529,7 +563,7 @@ namespace PasteApeart.Handler.redis
///
/// </summary>
/// <param name="key"></param>
- /// <param name="field"></param>
+ /// <param name="fields"></param>
/// <returns></returns>
public async Task<bool> HashDeleteAsync(string key, RedisValue[] fields)
{
@@ -586,6 +620,7 @@ namespace PasteApeart.Handler.redis
/// </summary>
/// <param name="key"></param>
/// <param name="field"></param>
+ /// <param name="num"></param>
/// <returns></returns>
public long HashIncrement(string key, string field, long num = 1)
{
@@ -597,6 +632,7 @@ namespace PasteApeart.Handler.redis
/// </summary>
/// <param name="key"></param>
/// <param name="field"></param>
+ /// <param name="val"></param>
/// <returns></returns>
public async Task<long> HashDecrementAsync(string key, string field, long val = 1)
{
@@ -628,13 +664,13 @@ namespace PasteApeart.Handler.redis
}
/// <summary>
- /// Hash 分页查询
- /// 已测试可以使用
+ ///
/// </summary>
/// <param name="key"></param>
/// <param name="pattern"></param>
- /// <param name="page">页码从1开始</param>
- /// <param name="size">每页的大小</param>
+ /// <param name="page"></param>
+ /// <param name="size"></param>
+ /// <param name="isincom"></param>
/// <returns></returns>
public async Task<List<HashEntry>> HashScanAsync(string key, string pattern, int page, int size, bool isincom = true)
{
@@ -682,6 +718,7 @@ namespace PasteApeart.Handler.redis
/// </summary>
/// <param name="key"></param>
/// <param name="field"></param>
+ /// <param name="isNum"></param>
/// <returns></returns>
public async Task<int> HashGetIntFieldAsync(string key, string field, bool isNum = false)
{
@@ -693,12 +730,12 @@ namespace PasteApeart.Handler.redis
}
return default(int);
}
-
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <param name="field"></param>
+ /// <param name="isNum"></param>
/// <returns></returns>
public async Task<long> HashGetLongFieldAsync(string key, string field, bool isNum = false)
{
@@ -807,7 +844,6 @@ namespace PasteApeart.Handler.redis
/// </summary>
/// <param name="key"></param>
/// <param name="field"></param>
- /// <param name="value"></param>
/// <returns></returns>
public async Task<bool> SortedSetRemoveAsync(string key, string field)
{
@@ -865,6 +901,11 @@ namespace PasteApeart.Handler.redis
return await _database.StringSetBitAsync(setKey(key), offset, bit);
}
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="vals"></param>
public void HashSet(string key, List<HashKeyValue> vals)
{
var list = new List<HashEntry>();
@@ -876,6 +917,13 @@ namespace PasteApeart.Handler.redis
_database.HashSet(setKey(key), list.ToArray());
}
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="vals"></param>
+ /// <param name="isnum"></param>
+ /// <returns></returns>
public async Task HashSetAsync(string key, List<HashKeyValue> vals, bool isnum = false)
{
var list = new List<HashEntry>();
@@ -887,6 +935,12 @@ namespace PasteApeart.Handler.redis
await _database.HashSetAsync(setKey(key), list.ToArray());
}
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="val"></param>
+ /// <returns></returns>
public bool SetValue(string key, string val)
{
return Set(key, val);
@@ -999,7 +1053,12 @@ namespace PasteApeart.Handler.redis
#endregion
-
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="vals"></param>
+ /// <returns></returns>
public async Task HashSetAsync(string key, List<HashKeyValue> vals)
{
var list = new List<HashEntry>();
@@ -1050,7 +1109,6 @@ namespace PasteApeart.Handler.redis
/// 从hash中获取随机一个!!!
/// </summary>
/// <param name="key"></param>
- /// <param name="count"></param>
/// <returns></returns>
public async Task<HashEntry> HashRandomFieldsWithValuesAsync(string key)
{
@@ -1063,11 +1121,13 @@ namespace PasteApeart.Handler.redis
}
/// <summary>
- /// 查询符合条件的
+ ///
/// </summary>
/// <param name="key"></param>
- /// <param name="pattern">*XXX*</param>
+ /// <param name="pattern"></param>
/// <param name="size"></param>
+ /// <param name="cursor"></param>
+ /// <param name="offset"></param>
/// <returns></returns>
public async Task<HashEntry[]> HashScanAsync(string key, string pattern, int size = 1, int cursor = 0, int offset = 0)
{
framework/PasteApeart.Helper/BuilderHelper.cs
diff --git a/framework/PasteApeart.Helper/BuilderHelper.cs b/framework/PasteApeart.Helper/BuilderHelper.cs
index 464eb63..377c7b5 100644
--- a/framework/PasteApeart.Helper/BuilderHelper.cs
+++ b/framework/PasteApeart.Helper/BuilderHelper.cs
@@ -1105,6 +1105,21 @@ namespace PasteApeart.Helper
}
}
}
+
+ // 判断是否为基础类型数组(如 int[]、string[] 等),是则追加特性split
+ var _ele_type = _property.PropertyType.GetElementType();
+ if (_property.PropertyType.IsArray && _ele_type != null && _ele_type.FullName != null && _ele_type.FullName.StartsWith("System"))
+ {
+ if (proInfo.Attributes == null)
+ {
+ proInfo.Attributes = new List<VoloModelAttribute>();
+ }
+ if (!proInfo.Attributes.Any(x => x.Name == "split"))
+ {
+ proInfo.Attributes.Add(new VoloModelAttribute { Name = "split", Args1 = ";" });
+ }
+ }
+
}
//有Description特性的话,如果是空值,可能是故意这么设定的!
framework/PasteApeart.Helper/readme.md
diff --git a/framework/PasteApeart.Helper/readme.md b/framework/PasteApeart.Helper/readme.md
index fbe76c8..08564dd 100644
--- a/framework/PasteApeart.Helper/readme.md
+++ b/framework/PasteApeart.Helper/readme.md
@@ -1,6 +1,10 @@
# 贴代码框架PasteApeart简介
+## 26.10.03
+ 1.如果是string[] int[]等,在表单的时候,追加一个split(;)的特性,这样对于form就可以编辑了!
+
+
## 26.09.21
1.Enum的0全部字段,支持不同i形态,比如全部/无 那么在搜索区域显示的是全部,在表单或者表格则是无
manage/page/pasteform/index.html
diff --git a/manage/page/pasteform/index.html b/manage/page/pasteform/index.html
index cc793bd..ffaab9c 100644
--- a/manage/page/pasteform/index.html
+++ b/manage/page/pasteform/index.html
@@ -22,7 +22,7 @@
<div class="page-container index-page">
<div class="searcharea">
- <form id="formsearch" class="pasteform oneline" onsubmit="return false;" action="javascript:void(0);">
+ <form id="formsearch" class="pasteform oneline" onsubmit="return false;" action="javascript:void(0);">
<div class="searchbox"></div>
</form>
<div class="tap_more">
@@ -32,7 +32,7 @@
</div>
<div class="ppbody">
<div class="st">
-
+
<input type="button" class="isedit btn btnstyle btnadd" value="新增" onclick="tap_add_form(this);" />
<!-- 用于显示表名或者是模块名称 -->
@@ -44,24 +44,28 @@
<div class="func_btn_area"></div>
<!-- 切换table和chart模式 -->
- <div class="show_type">
- <i class="Hui-iconfont Hui-iconfont-zhongtumoshi type_table rbtn selected" onclick="handlerChangeShowType(false,this);"></i>
- <i class="Hui-iconfont Hui-iconfont-tongji-xian type_chart rbtn" onclick="handlerChangeShowType(true,this);"></i>
- </div>
-
+ <div class="show_type">
+ <i class="Hui-iconfont Hui-iconfont-zhongtumoshi type_table rbtn selected"
+ onclick="handlerChangeShowType(false,this);"></i>
+ <i class="Hui-iconfont Hui-iconfont-tongji-xian type_chart rbtn"
+ onclick="handlerChangeShowType(true,this);"></i>
+ </div>
+ <a href="javascript:exportExcel(this);" style="display:none;" class="btnautoarea command_excel_out" title="导出当前页为EXCEL"><i
+ class="Hui-iconfont Hui-iconfont-dangan"></i></a>
<input type="button" class="btnsearch btn" onclick="readPageData(1);" value="查询">
<a class="btnrefush" href="javascript:location.replace(location.href);" title="刷新"><i
class="Hui-iconfont"></i></a>
<a href="javascript:func_auto_searcharea(this);" class="btnautoarea" title="显示更多查询项"><i
class="Hui-iconfont Hui-iconfont-search1"></i></a>
- <a href="javascript:printTable(this);" class="btnautoarea" title="打印当前页,建议使用横向模式"><i
- class="Hui-iconfont Hui-iconfont-dayinji"></i></a>
- <a href="javascript:cleanTableColumnOrder(this);" class="btnautoarea btn_clear_order_column" title="清理列排序缓存"><i
- class="Hui-iconfont Hui-iconfont-del2"></i></a>
+ <a href="javascript:printTable(this);" class="btnautoarea command_print" title="打印当前页,建议使用横向模式"><i
+ class="Hui-iconfont Hui-iconfont-dayinji"></i></a>
+ <a href="javascript:cleanTableColumnOrder(this);" class="btnautoarea btn_clear_order_column"
+ title="清理列排序缓存"><i class="Hui-iconfont Hui-iconfont-del2"></i></a>
</div>
<div class="batcharea"></div>
<div class="mt-20 table_wrap">
- <table id="data-table" class="table table-border table-bordered tb_freeze table-bg table-hover table-sort table-responsive">
+ <table id="data-table"
+ class="table table-border table-bordered tb_freeze table-bg table-hover table-sort table-responsive">
<thead>
</thead>
<tbody>
@@ -251,7 +255,7 @@
</div>
<% } %>
<% }) %>
- </script>
+ </script>
<!-- 头部的批量操作的模板 -->
@@ -505,12 +509,12 @@
<% } %>
</tr>
</script>
- <!-- 版本二 -->
+ <!-- 版本二 -->
<script type="text/html" id="template_body_tbody">
<!-- 注意花括号百分比的是当前的模板 2个花括号的是占位,下一个的模板代码 -->
- <% list.forEach(ii=>{ %>
- <%:=templatetr({item:ii,config:config}) %>
- <% }) %>
+ <% list.forEach(ii=>{ %>
+ <%:=templatetr({item:ii,config:config}) %>
+ <% }) %>
</script>
<!-- 生成后的模板内容,用于排错用 -->
@@ -526,7 +530,7 @@
<script type="text/javascript" src="./lib/template.js"></script>
<script type="text/javascript" src="./lib/My97DatePicker/4.8/WdatePicker.js"></script>
<script type="text/javascript" src="../lib/api.js?v=251002"></script>
-
+
<!-- <script type="text/javascript" src="../lib/page.min.js"></script> -->
<script type="text/javascript" src="../lib/jquery.pagination.js"></script>
manage/page/pasteform/index.js
diff --git a/manage/page/pasteform/index.js b/manage/page/pasteform/index.js
index 46a22a7..ec90d06 100644
--- a/manage/page/pasteform/index.js
+++ b/manage/page/pasteform/index.js
@@ -79,6 +79,7 @@ var _config = {
search_after_selected: true,//搜索区域outer选择后,是否直接查询
trclass: null,//表格中trclass的字段名称,实际中这个值中去获取
batch: false,//是否启用批量操作
+ show_excel:false,//是否启用导出excel功能
orderby:"id",//排序
update_row_min_match_rate: 0.6,//更新行数据的时候,最小匹配率,低于这个值则不进行更新
bind_with_edit: false,//绑定模式下,是否启用编辑模式
@@ -185,6 +186,13 @@ $(window).ready(function () {
addImgTapListenter();
QueryModel();
+
+ //显示导出功能
+ if(_config.show_excel){
+ $(".command_excel_out").show();
+ //载入资源组件 导出到excel
+ loadResource("./lib/xlsx.js",false);
+ }
});
/**
manage/page/pasteform/lib/xlsx.js
diff --git a/manage/page/pasteform/lib/xlsx.js b/manage/page/pasteform/lib/xlsx.js
new file mode 100644
index 0000000..dc3eb01
--- /dev/null
+++ b/manage/page/pasteform/lib/xlsx.js
@@ -0,0 +1,177 @@
+// expend.js
+// window._global_list_properties
+// window.global_page_data
+// window._global_list_properties
+// window.global_page_data
+(function () {
+
+ // 保存原始函数引用
+ const oldPageLoad = window.afterReadPageData;
+
+ // console.log(oldPageLoad, 'oldPageLoad');
+
+ // 闭包内缓存当前页面数据,避免跨页面数据污染
+ var pageDataCache = null;
+
+ window.afterReadPageData = function (code, obj, page) {
+ if (obj && Array.isArray(obj)) {
+ pageDataCache = obj;
+ } else if (obj && typeof obj === 'object' && obj.items && Array.isArray(obj.items)) {
+ pageDataCache = obj.items;
+ }
+
+ let result;
+ if (oldPageLoad) {
+ result = oldPageLoad.call(this, code, obj, page);
+ }
+ return result;
+ };
+
+ // HTML转纯文本
+ function htmlToText(html) {
+ if (html === null || html === undefined) return '';
+ if (typeof html !== 'string') return String(html);
+ // 处理<br>和<br/>换行
+ let text = html.replace(/<br\s*\/?>/gi, '\n');
+ // 处理</span>、</div>等块级元素闭合标签后加换行
+ text = text.replace(/<\/(span|div|p|li|tr)>/gi, function (match, tag) {
+ return tag === 'span' ? ' ' : '\n';
+ });
+ // 去除所有HTML标签
+ text = text.replace(/<[^>]+>/g, '');
+ // 解码HTML实体
+ text = text.replace(/&/g, '&')
+ .replace(/</g, '<')
+ .replace(/>/g, '>')
+ .replace(/"/g, '"')
+ .replace(/'/g, "'")
+ .replace(/ /g, ' ');
+ // 清理多余空白
+ text = text.replace(/[ \t]+/g, ' ').trim();
+ return text;
+ }
+
+ // 获取单元格的值,处理对象和HTML
+ function getCellValue(value) {
+ if (value === null || value === undefined) return '';
+ // 对象类型取name属性(如 extendSubject: {id: 11, name: "财聚天下"})
+ if (typeof value === 'object') {
+ if (value.name !== undefined) return value.name;
+ if (value.id !== undefined) return value.id;
+ return JSON.stringify(value);
+ }
+ // 字符串类型检查是否包含HTML标签
+ if (typeof value === 'string' && /<[a-zA-Z][^>]*>/.test(value)) {
+ return htmlToText(value);
+ }
+ return String(value);
+ }
+
+ // 导出Excel
+ function exportExcel() {
+ var properties = window._global_list_properties;
+ var cache = pageDataCache;
+ // console.log(properties, 'properties');
+
+ if (!properties || !Array.isArray(properties) || properties.length === 0) {
+ console.warn('导出Excel: 未找到表头配置 _global_list_properties');
+ return;
+ }
+ if (!cache || !Array.isArray(cache) || cache.length === 0) {
+ console.warn('导出Excel: 未找到数据 _pageDataCache');
+ return;
+ }
+
+ // 获取数据列表
+ var items = cache;
+ // 如果缓存的是分页对象,取items
+ if (cache.items && Array.isArray(cache.items)) {
+ items = cache.items;
+ }
+
+ // 过滤隐藏列,构建表头
+ // ★ 过滤 attributes 含 outignore / ifmenu 的列(操作按钮、忽略导出类字段)
+ var visibleProps = properties.filter(function (p) {
+ if(p.name == p.title) return false;
+ if (!p.attributes || !Array.isArray(p.attributes) || !p.attributes.length) return true;
+ return !p.attributes.some(function (a) {
+ return a.name === 'outignore' || a.name === 'ifmenu' || a.name === 'menuhtml' ;
+ });
+ });
+
+ var headers = visibleProps.map(function (p) {
+ return p.title || p.name || '';
+ });
+
+ var keys = visibleProps.map(function (p) {
+ return p.name;
+ });
+
+ // console.log('★ headers:', headers, '| keys:', keys);
+
+ // 构建HTML表格
+ var html = '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40">';
+ html += '<head><meta charset="UTF-8">';
+ html += '<!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>Sheet1</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]-->';
+ html += '<style>td{mso-number-format:"\\@";}</style>';
+ html += '</head><body>';
+ html += '<table border="1">';
+
+ // 表头行(用<td>+内联样式,Excel兼容性更好)
+ html += '<tr>';
+ headers.forEach(function (h) {
+ html += '<td style="background:#4472C4;color:#fff;font-weight:bold;text-align:center;">' + h + '</td>';
+ });
+ html += '</tr>';
+
+ // console.log('★ 表头HTML:', html); // 验证表头是否写入
+
+ // 数据行
+ items.forEach(function (row) {
+ html += '<tr>';
+ keys.forEach(function (key) {
+ var val = '';
+ // 处理嵌套字段(如 extendBusinessModel?.name)
+ if (key.indexOf('?.') !== -1) {
+ var parts = key.split('?.');
+ var cur = row;
+ for (var pi = 0; pi < parts.length; pi++) {
+ if (cur == null || typeof cur !== 'object') { cur = undefined; break; }
+ cur = cur[parts[pi]];
+ }
+ val = getCellValue(cur);
+ } else {
+ val = getCellValue(row[key]);
+ }
+ html += '<td>' + val + '</td>';
+ });
+ html += '</tr>';
+ });
+
+ html += '</table></body></html>';
+
+ // 生成Blob并下载
+ var blob = new Blob([html], { type: 'application/vnd.ms-excel;charset=utf-8' });
+ var url = URL.createObjectURL(blob);
+ var link = document.createElement('a');
+ link.href = url;
+
+ // 生成文件名:列表数据_日期
+ var now = new Date();
+ var dateStr = now.getFullYear() + '-' +
+ String(now.getMonth() + 1).padStart(2, '0') + '-' +
+ String(now.getDate()).padStart(2, '0') + ' ' +
+ String(now.getHours()).padStart(2, '0') + ':' +
+ String(now.getMinutes()).padStart(2, '0');
+ link.download = '列表数据_' + dateStr + '.xls';
+
+ document.body.appendChild(link);
+ link.click();
+ document.body.removeChild(link);
+ URL.revokeObjectURL(url);
+ }
+
+ // 暴露到全局,外部可直接调用
+ window.exportExcel = exportExcel;
+
+})();
\ No newline at end of file