Browse Source

Apewer-6.7.2

dev
王厅 2 years ago
parent
commit
0d041854fc
  1. 2
      Apewer.Source/Apewer.Source.csproj
  2. 3
      Apewer.Source/Source/Sqlite.cs
  3. 23
      Apewer.Web/Web/AspNetCoreServer.cs
  4. 2
      Apewer/Apewer.props
  5. 51
      Apewer/Json.cs
  6. 38
      Apewer/Network/HttpClient.cs
  7. 13
      Apewer/RuntimeUtility.cs
  8. 2
      Apewer/Web/ApiOptions.cs
  9. 67
      Apewer/Web/ApiProcessor.cs
  10. 4
      Apewer/Web/ApiResponse.cs
  11. 2
      Apewer/_Extensions.cs
  12. 10
      ChangeLog.md

2
Apewer.Source/Apewer.Source.csproj

@ -11,7 +11,7 @@
<ItemGroup>
<ProjectReference Include="..\Apewer\Apewer.csproj" />
<PackageReference Include="System.Data.SQLite.Core" Version="1.0.110" />
<PackageReference Include="System.Data.SQLite.Core" Version="1.0.110" PrivateAssets="all" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'=='netstandard2.0'">

3
Apewer.Source/Source/Sqlite.cs

@ -12,6 +12,7 @@ namespace Apewer.Source
{
/// <summary>连接 SQLite 数据库的客户端。</summary>
/// <remarks>Require System.Data.SQLite.Core v1.0.110</remarks>
public class Sqlite : DbClient
{
@ -61,7 +62,7 @@ namespace Apewer.Source
// 使用文件。
if (!File.Exists(path)) throw new FileNotFoundException("文件不存在。", path);
_connstr = $"data source='{_path}'; version=3; ";
_connstr = $"data source='{path}'; version=3; ";
_path = path;
if (!string.IsNullOrEmpty(pass))
{

23
Apewer.Web/Web/AspNetCoreServer.cs

@ -14,6 +14,7 @@ using System.Net.WebSockets;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using System.Security.Authentication;
using Microsoft.Extensions.Logging.Console;
namespace Apewer.Web
{
@ -38,6 +39,24 @@ namespace Apewer.Web
try
{
_builder = Host.CreateDefaultBuilder();
if (!LogConsole)
{
_builder.ConfigureLogging((context, builder) =>
{
if (context.HostingEnvironment.IsProduction())
{
foreach (var sd in builder.Services)
{
if (sd.ImplementationType.Equals(typeof(ConsoleLoggerProvider)))
{
builder.Services.Remove(sd);
break;
}
}
}
});
}
_builder.ConfigureWebHostDefaults((builder) =>
{
Configure(builder);
@ -117,6 +136,10 @@ namespace Apewer.Web
set { if (!_running) _compression = value; }
}
/// <summary>使用默认的控制台日志。</summary>
/// <remarks>默认值:TRUE</remarks>
public bool LogConsole { get; set; } = true;
#endregion
}

2
Apewer/Apewer.props

@ -9,7 +9,7 @@
<Description></Description>
<RootNamespace>Apewer</RootNamespace>
<Product>Apewer Libraries</Product>
<Version>6.7.1</Version>
<Version>6.7.2</Version>
</PropertyGroup>
<!-- 生成 -->

51
Apewer/Json.cs

@ -36,7 +36,7 @@ namespace Apewer
private static bool _recursively = true;
[NonSerialized]
private static bool _forceall = false;
private static bool _forceall = true;
/// <summary>允许产生 Exception,默认为不允许。</summary>
public static bool AllowException { get { return _throw; } set { _throw = value; } }
@ -1166,17 +1166,20 @@ namespace Apewer
{
if (list == null) return null;
if (list is IToJson) return ((IToJson)list).ToJson();
// IList 不再需要 SerializableAttribute 特性。
// {
// var ltype = list.GetType();
// var sas = ltype.GetCustomAttributes(typeof(SerializableAttribute), false);
// if (sas == null || sas.Length < 1) return null;
// }
var checker = list as IToJsonChecker;
var json = NewArray();
try
{
if (list is Array array)
{
if (array != null && array.Rank > 1)
{
ToJson(json, array, array.Rank, new int[0]);
return json;
}
}
foreach (var item in list)
{
// 由 IToJsonChecker 实现的方法检查是否包含元素。
@ -1584,6 +1587,38 @@ namespace Apewer
}
}
private static void ToJson(Json parent, Array array, int rank, int[] indices)
{
var dimension = indices.Length;
var subIndices = new int[dimension + 1];
if (dimension > 0) indices.CopyTo(subIndices, 0);
var subLength = array.GetLength(dimension);
var end = dimension + 1 >= rank;
if (end)
{
var subLinear = new object[subLength];
for (var i = 0; i < subLength; i++)
{
subIndices[dimension] = i;
subLinear[i] = array.GetValue(subIndices);
}
var subJson = Json.From(subLinear);
parent.Reset(subJson);
}
else
{
for (var i = 0; i < subLength; i++)
{
subIndices[dimension] = i;
var subJson = Json.NewArray();
ToJson(subJson, array, rank, subIndices);
parent.AddItem(subJson);
}
}
}
#endregion
#region Json -> String
@ -1624,7 +1659,7 @@ namespace Apewer
}
/// <summary>将 Json 填充到数组列表,失败时返回 NULL 值。</summary>
internal static T[] Array<T>(Json json, bool ignoreCase = true, string ignoreCharacters = null, bool force = false) where T : class, new()
internal static T[] Array<T>(Json json, bool ignoreCase = true, string ignoreCharacters = null, bool force = false)
{
if (json == null) return null;
if (json._jtoken == null) return null;

38
Apewer/Network/HttpClient.cs

@ -121,7 +121,9 @@ namespace Apewer.Network
}
/// <summary>发送请求,并获取响应。</summary>
public Exception Send()
/// <param name="catchEx">捕获发生的异常,将异常作为返回值。</param>
/// <returns>发生的异常。</returns>
public Exception Send(bool catchEx = true)
{
lock (_locker)
{
@ -134,7 +136,12 @@ namespace Apewer.Network
ResponseData = default;
var url = Url;
if (url.IsEmpty()) return Return(new MissingMemberException("未指定 URL。"));
if (url.IsEmpty())
{
var ex = new MissingMemberException("未指定 URL。");
if (!catchEx) throw ex;
return Return(ex);
}
var method = Method;
if (method == HttpMethod.NULL)
@ -143,21 +150,30 @@ namespace Apewer.Network
else method = HttpMethod.GET;
}
try
if (catchEx)
{
try
{
_request = Prepare(url, method);
_response = _request.GetResponse() as HttpWebResponse;
Parse(_response);
}
catch (Exception ex)
{
_exception = ex;
if (ex is WebException webEx) Parse((HttpWebResponse)webEx.Response);
return ex;
}
}
else
{
_request = Prepare(url, method);
_response = _request.GetResponse() as HttpWebResponse;
Parse(_response);
return null;
}
catch (Exception ex)
{
_exception = ex;
if (ex is WebException webEx) Parse((HttpWebResponse)webEx.Response);
return ex;
}
}
return null;
}
/// <exception cref="System.ArgumentException"></exception>

13
Apewer/RuntimeUtility.cs

@ -794,16 +794,9 @@ namespace Apewer
if (action == null) return 0;
var stopwatch = new Stopwatch();
stopwatch.Start();
try
{
action.Invoke();
stopwatch.Stop();
return stopwatch.ElapsedMilliseconds;
}
finally
{
stopwatch.Stop();
}
action.Invoke();
stopwatch.Stop();
return stopwatch.ElapsedMilliseconds;
}
#endregion

2
Apewer/Web/ApiOptions.cs

@ -7,7 +7,7 @@ namespace Apewer.Web
{
/// <summary>选项。</summary>
public class ApiOptions
public sealed class ApiOptions
{
/// <summary>允许压缩。</summary>

67
Apewer/Web/ApiProcessor.cs

@ -1,11 +1,7 @@
using Apewer.Network;
using Apewer.Source;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Reflection;
using static Apewer.Web.ApiUtility;
@ -21,8 +17,7 @@ namespace Apewer.Web
internal Action<ApiCatch> Catcher = null;
ApiOptions Options = null;
Stopwatch Stopwatch = null;
DateTime Begin = DateTime.UtcNow;
Uri Url = null;
HttpMethod Method = HttpMethod.NULL;
ApiRequest ApiRequest = null;
@ -36,31 +31,21 @@ namespace Apewer.Web
public string Run()
{
if (Options == null) Options = new ApiOptions();
if (Options.WithDuration)
{
Stopwatch = new Stopwatch();
Stopwatch.Start();
}
var error = Flow();
if (Stopwatch != null)
{
Stopwatch.Stop();
Stopwatch = null;
}
return error;
}
string Flow()
{
// 传入字段。
if (Provider == null) return "服务程序无效。";
if (Invoker == null) return "调用器无效。";
if (Entries == null) return "入口无效。";
Options = Invoker.Options ?? new ApiOptions();
Provider.Options = Options;
try
{
// 传入字段。
if (Provider == null) return "服务程序无效。";
if (Invoker == null) return "调用器无效。";
if (Entries == null) return "入口无效。";
Options = Invoker.Options ?? new ApiOptions();
Provider.Options = Options;
// 检查执行的前提条件,获取 Method 和 URL。
var check = Check();
if (!string.IsNullOrEmpty(check)) return check;
@ -77,28 +62,36 @@ namespace Apewer.Web
if (!string.IsNullOrEmpty(invoke)) return invoke;
// 输出。
if (Stopwatch != null)
{
Stopwatch.Stop();
ApiResponse.Duration = Stopwatch.ElapsedMilliseconds;
Stopwatch = null;
}
ApiResponse.Duration = Duration();
Output(Provider, Options, ApiResponse, ApiRequest, Method);
return null;
}
catch (Exception ex)
{
if (Stopwatch != null)
{
Stopwatch.Stop();
Stopwatch = null;
}
var message = ex.Message();
Logger.Internals.Error(typeof(ApiInvoker), message);
return message;
}
}
string Duration()
{
var span = DateTime.UtcNow - Begin;
var ms = span.TotalMilliseconds;
if (ms > 0D)
{
var s = span.TotalMilliseconds / 1000D;
if (s > 10D) return Math.Round(s, 1).ToString() + "s";
if (s > 1D) return Math.Round(s, 2).ToString() + "s";
if (ms > 10D) return Math.Round(ms, 0).ToString() + "ms";
return Math.Round(ms, 1).ToString() + "ms";
}
else
{
return null;
}
}
string Check()
{
// 服务程序检查。
@ -147,7 +140,7 @@ namespace Apewer.Web
Invoke(Entries.Get(appName));
if (Stopwatch != null) ApiResponse.Duration = Stopwatch.ElapsedMilliseconds;
ApiResponse.Duration = Duration();
ApiResponse.Application = appName;
ApiResponse.Function = funcName;
ApiResponse.Random = random;
@ -489,7 +482,7 @@ namespace Apewer.Web
// 包含 API 的处理时间。
if (options.WithDuration && response != null)
{
merged.Add("Duration", response.Duration.ToString() + "ms");
if (response.Duration.NotEmpty()) merged.Add("Duration", response.Duration);
}
}
if (response != null)
@ -534,7 +527,7 @@ namespace Apewer.Web
// 持续时间。
if (options.WithDuration)
{
json.SetProperty("duration", response.Duration);
if (response.Duration.NotEmpty()) json.SetProperty("duration", response.Duration);
}
// 随机值。

4
Apewer/Web/ApiResponse.cs

@ -18,8 +18,8 @@ namespace Apewer.Web
internal bool StopReturn = false;
/// <summary>API 的执行时间,以毫秒为单位。</summary>
public long Duration { get; set; }
/// <summary>API 的执行时间。</summary>
public string Duration { get; set; }
/// <summary>Application。</summary>
public string Application { get; set; }

2
Apewer/_Extensions.cs

@ -346,7 +346,7 @@ public static class Extensions
/// <param name="ignoreCase">忽略属性名称大小写。</param>
/// <param name="ignoreChars">忽略的属性名称字符。</param>
/// <param name="force">强制填充,忽略 <typeparamref name="T"/> 的 Serializable 特性。</param>
public static T[] Array<T>(this Json @this, bool ignoreCase = true, string ignoreChars = null, bool force = false) where T : class, new() => Apewer.Json.Array<T>(@this, ignoreCase, ignoreChars, force);
public static T[] Array<T>(this Json @this, bool ignoreCase = true, string ignoreChars = null, bool force = false) => Apewer.Json.Array<T>(@this, ignoreCase, ignoreChars, force);
/// <summary>设置属性名称为小写。</summary>
public static Json Lower(this Json @this) => Apewer.Json.Lower(@this);

10
ChangeLog.md

@ -1,6 +1,16 @@

### 最新提交
### 6.7.2
- 问题修正
- 修正了 SQLite 的构造函数中的 path 参数;
- Apewer.Source 不再包含对 System.Data.SQLite.Core 的依赖,最终代码项目中需要额外添加引用。
- 新特性
- Json 强制序列化选项已修改为 true,以简化最终代码;
- Json 解析新增支持数组类型,提升性能;
- HttpClient 增加了参数 catchEx = true;
- AspNetCoreServer 新增了 LogConsole 属性,默认值为 true,用于配置控制台输出。
### 6.7.1
- 问题修正
- 修正了 Evaluate 可能不释放计时器的问题;

Loading…
Cancel
Save