diff --git a/Apewer/ForbiddenException.cs b/Apewer/ForbiddenException.cs
new file mode 100644
index 0000000..df1191e
--- /dev/null
+++ b/Apewer/ForbiddenException.cs
@@ -0,0 +1,24 @@
+using Apewer.Web;
+using System;
+
+namespace Apewer
+{
+
+ /// 表示被禁止访问的错误。
+ public sealed class ForbiddenException : Exception, IApiException
+ {
+
+ const string DefaultMessage = "禁止访问。";
+
+ /// 表示禁止访问的状态。
+ public string Status { get => "Forbidden"; }
+
+ ///
+ public ForbiddenException(string message = DefaultMessage) : base(message.IsEmpty() ? DefaultMessage : message) { }
+
+ ///
+ public override string ToString() => $" {Message}";
+
+ }
+
+}
diff --git a/Apewer/NotFoundException.cs b/Apewer/NotFoundException.cs
new file mode 100644
index 0000000..3188338
--- /dev/null
+++ b/Apewer/NotFoundException.cs
@@ -0,0 +1,46 @@
+using Apewer.Web;
+using System;
+
+namespace Apewer
+{
+
+ /// 表示目标资源不存在的错误。
+ public class NotFoundException : Exception, IApiException
+ {
+
+ static string _default = FixMessage(null);
+
+ static string FixMessage(string message)
+ {
+ const string Preset = "Resource not found.";
+ if (message != null)
+ {
+ message = message.Trim();
+ if (!string.IsNullOrEmpty(message)) return message;
+ }
+
+ return Preset;
+ }
+
+ /// 获取或设置默认消息。
+ public static string DefaultMessage { get => _default; set => _default = FixMessage(value); }
+
+ /// 状态。
+ /// Unauthorized
+ public virtual string Status { get => "Not Found"; }
+
+ /// 表示目标资源不存在的错误。
+ /// 默认消息:Operation is not authorized.
+ public NotFoundException() : base(DefaultMessage) { }
+
+ /// 表示目标资源不存在的错误。
+ /// 默认消息:Operation is not authorized.
+ public NotFoundException(string message) : base(FixMessage(message)) { }
+
+ /// 表示目标资源不存在的错误。
+ /// 默认消息:Operation is not authorized.
+ public NotFoundException(string message, Exception innerException) : base(FixMessage(message), innerException) { }
+
+ }
+
+}
diff --git a/Apewer/RedundanceException.cs b/Apewer/RedundanceException.cs
index c9c8fb3..d17a04f 100644
--- a/Apewer/RedundanceException.cs
+++ b/Apewer/RedundanceException.cs
@@ -1,9 +1,4 @@
-using Apewer.Internals;
-using System;
-using System.Collections.Generic;
-using System.Runtime.InteropServices;
-using System.Runtime.Serialization;
-using System.Text;
+using System;
namespace Apewer
{
diff --git a/Apewer/UnauthorizedException.cs b/Apewer/UnauthorizedException.cs
index 6931754..9c0cc28 100644
--- a/Apewer/UnauthorizedException.cs
+++ b/Apewer/UnauthorizedException.cs
@@ -1,11 +1,12 @@
-using System;
+using Apewer.Web;
+using System;
namespace Apewer
{
/// 表示未授权的错误。
/// 默认消息:Operation is not authorized.
- public class UnauthorizedException : Exception
+ public class UnauthorizedException : Exception, IApiException
{
static string _default = FixMessage(null);
diff --git a/Apewer/Web/ApiProcessor.cs b/Apewer/Web/ApiProcessor.cs
index 8a70f0a..cf0d26f 100644
--- a/Apewer/Web/ApiProcessor.cs
+++ b/Apewer/Web/ApiProcessor.cs
@@ -1,4 +1,5 @@
-using Apewer.Network;
+using Apewer.Internals;
+using Apewer.Network;
using System;
using System.Collections.Generic;
using System.Net;
@@ -305,7 +306,17 @@ namespace Apewer.Web
if (action != null)
{
_context.ApiAction = action;
- InvokeAction(action);
+ if (action.Unparallel)
+ {
+ UnparallelLocker.InLock(GetUnparallelKey(action.MethodInfo), () =>
+ {
+ InvokeAction(action);
+ });
+ }
+ else
+ {
+ InvokeAction(action);
+ }
return;
}
}
@@ -438,15 +449,27 @@ namespace Apewer.Web
{
// 控制器初始化。
var initializer = ApiUtility.GetInitialier(controller);
- var match = initializer == null ? true : initializer.Invoke(controller);
- if (!match) return;
+ if (initializer != null)
+ {
+ var @continue = true;
+ UnparallelLocker.InLock(GetUnparallelKey(controller.GetType()), () =>
+ {
+ @continue = initializer.Invoke(controller);
+ });
+ if (!@continue) return;
+ }
+
+ // 此应用独立处理,不受反射控制。
if (application.Independent) return;
if (function != null)
{
// 调用 API,获取返回值。
_context.Controller = controller;
- Invoke(_context, function.Method, function.Parameters);
+ UnparallelLocker.InLock(GetUnparallelKey(function.Method), () =>
+ {
+ Invoke(_context, function.Method, function.Parameters);
+ });
}
else
{
@@ -454,8 +477,11 @@ namespace Apewer.Web
var @default = ApiUtility.GetDefault(controller);
if (@default != null)
{
- @default.Invoke(controller);
- return;
+ UnparallelLocker.InLock(GetUnparallelKey(controller.GetType()), () =>
+ {
+ @default.Invoke(controller);
+ return;
+ });
}
// 没有执行任何 Function,尝试枚举。
@@ -803,6 +829,22 @@ namespace Apewer.Web
#endregion
+ #region 不可并行
+
+ static TextLocker UnparallelLocker = new TextLocker();
+
+ static string GetUnparallelKey(MethodInfo method)
+ {
+ return $"{method.DeclaringType.Assembly.ToString()} | {method.DeclaringType.FullName} | {method.ToString()}";
+ }
+
+ static string GetUnparallelKey(Type type)
+ {
+ return $"{type.DeclaringType.Assembly.ToString()}";
+ }
+
+ #endregion
+
}
}
diff --git a/Apewer/Web/IApiException.cs b/Apewer/Web/IApiException.cs
new file mode 100644
index 0000000..f6ec856
--- /dev/null
+++ b/Apewer/Web/IApiException.cs
@@ -0,0 +1,16 @@
+namespace Apewer.Web
+{
+
+ /// 执行 API 时发生的异常。
+ public interface IApiException
+ {
+
+ /// 异常状态。
+ string Status { get; }
+
+ /// 错误消息。
+ string Message { get; }
+
+ }
+
+}