parent
68e179b442
commit
d997e57c63
1120 changed files with 4 additions and 79545 deletions
@ -1,5 +1,5 @@ |
|||||||
fileFormatVersion: 2 |
fileFormatVersion: 2 |
||||||
guid: e1da1eafda489e846a172d3f088c7de3 |
guid: 2c9e2272c07c90a4eb03ef74f9a87470 |
||||||
folderAsset: yes |
folderAsset: yes |
||||||
DefaultImporter: |
DefaultImporter: |
||||||
externalObjects: {} |
externalObjects: {} |
||||||
@ -1,698 +0,0 @@ |
|||||||
using NaughtyAttributes; |
|
||||||
using System.Collections.Generic; |
|
||||||
using TouchSocket.Core; |
|
||||||
using UnityEngine; |
|
||||||
|
|
||||||
public class HandDriver : MonoBehaviour |
|
||||||
{ |
|
||||||
public Network Network; |
|
||||||
|
|
||||||
public enum HandType |
|
||||||
{ |
|
||||||
Left, |
|
||||||
Right |
|
||||||
} |
|
||||||
|
|
||||||
public enum Axis |
|
||||||
{ |
|
||||||
x, |
|
||||||
y, |
|
||||||
z, |
|
||||||
x_n, |
|
||||||
y_n, |
|
||||||
z_n |
|
||||||
} |
|
||||||
|
|
||||||
public string CharacterName = string.Empty; |
|
||||||
public HandType Hand; |
|
||||||
private Dictionary<string, Quaternion> _originQuaternionDic; |
|
||||||
|
|
||||||
public Transform Thumb1; |
|
||||||
public Transform Thumb2; |
|
||||||
public Transform Thumb3; |
|
||||||
|
|
||||||
public Transform Index1; |
|
||||||
public Transform Index2; |
|
||||||
public Transform Index3; |
|
||||||
|
|
||||||
public Transform Middle1; |
|
||||||
public Transform Middle2; |
|
||||||
public Transform Middle3; |
|
||||||
|
|
||||||
public Transform Ring1; |
|
||||||
public Transform Ring2; |
|
||||||
public Transform Ring3; |
|
||||||
|
|
||||||
public Transform Pinky1; |
|
||||||
public Transform Pinky2; |
|
||||||
public Transform Pinky3; |
|
||||||
|
|
||||||
public Transform Wrist; |
|
||||||
|
|
||||||
[Header("[Axis OffSet]")]
|
|
||||||
public Axis Pitch = Axis.x; |
|
||||||
|
|
||||||
public Axis Roll = Axis.y; |
|
||||||
|
|
||||||
public Axis Yaw = Axis.z; |
|
||||||
|
|
||||||
[Header("[IMU(On/Off)]")] public bool HasIMU = false;
|
|
||||||
|
|
||||||
[Header("[Thumb Root Coefficient]")] [Range(0, 1)] public float coefficient = 0.6f;
|
|
||||||
|
|
||||||
[Header("[Thumb Root OffSet]")] public Vector3 Thumb1Offset;
|
|
||||||
|
|
||||||
[Header("[App Options]")]
|
|
||||||
public bool NeedRealTransfrom; |
|
||||||
|
|
||||||
//[HideInInspector] |
|
||||||
public bool UsingNetwork; |
|
||||||
|
|
||||||
public bool UsingAndroidService; |
|
||||||
|
|
||||||
[Header("[Vector3 Angles]")]
|
|
||||||
public Vector3 thumb1; |
|
||||||
public Vector3 thumb2; |
|
||||||
public Vector3 thumb3; |
|
||||||
|
|
||||||
public Vector3 index1; |
|
||||||
public Vector3 index2; |
|
||||||
public Vector3 index3; |
|
||||||
|
|
||||||
public Vector3 middle1; |
|
||||||
public Vector3 middle2; |
|
||||||
public Vector3 middle3; |
|
||||||
|
|
||||||
public Vector3 ring1; |
|
||||||
public Vector3 ring2; |
|
||||||
public Vector3 ring3; |
|
||||||
|
|
||||||
public Vector3 pinky1; |
|
||||||
public Vector3 pinky2; |
|
||||||
public Vector3 pinky3; |
|
||||||
|
|
||||||
[Header("[Controller Values]")]
|
|
||||||
public float Joy_X; |
|
||||||
public float Joy_Y; |
|
||||||
public bool Button_A; |
|
||||||
public bool Button_B; |
|
||||||
public bool Button_Joystick; |
|
||||||
public bool Button_Menu; |
|
||||||
public InputData inputData = new(); |
|
||||||
|
|
||||||
[Header("[Vibration Control]")]
|
|
||||||
public string SendBackIP; |
|
||||||
public VibrationData vibrationData; |
|
||||||
|
|
||||||
[BoxGroup("Vibrator 1"), Min(0), Label("Million Second")] |
|
||||||
public int Duration1 = 20; |
|
||||||
[BoxGroup("Vibrator 1"), Range(4, 10)] |
|
||||||
public int Amplitude1 = 4; |
|
||||||
[Button] |
|
||||||
public void Vibrator_1Active() |
|
||||||
{ |
|
||||||
if (Network == null) return; |
|
||||||
SingleVirbator[] Virbators; |
|
||||||
if (Hand == HandType.Left) |
|
||||||
{ |
|
||||||
Virbators = new SingleVirbator[2] |
|
||||||
{ |
|
||||||
new SingleVirbator(1, Duration1, Amplitude1), |
|
||||||
new SingleVirbator() |
|
||||||
}; |
|
||||||
vibrationData = new VibrationData(Virbators); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
Virbators = new SingleVirbator[2] |
|
||||||
{ |
|
||||||
new SingleVirbator(), |
|
||||||
new SingleVirbator(1, Duration1, Amplitude1), |
|
||||||
}; |
|
||||||
vibrationData = new VibrationData(Virbators); |
|
||||||
} |
|
||||||
Network.SendVibrationMsg(CharacterName, SendBackIP, vibrationData); |
|
||||||
} |
|
||||||
|
|
||||||
[BoxGroup("Vibrator 2"), Min(0), Label("Million Second")] |
|
||||||
public int Duration2 = 20; |
|
||||||
[BoxGroup("Vibrator 2"), Range(4, 10)] |
|
||||||
public int Amplitude2 = 4; |
|
||||||
[Button] |
|
||||||
public void Vibrator_2Active() |
|
||||||
{ |
|
||||||
if (Network == null) return; |
|
||||||
SingleVirbator[] Virbators; |
|
||||||
if (Hand == HandType.Left) |
|
||||||
{ |
|
||||||
Virbators = new SingleVirbator[2] |
|
||||||
{ |
|
||||||
new SingleVirbator(2, Duration2, Amplitude2), |
|
||||||
new SingleVirbator() |
|
||||||
}; |
|
||||||
vibrationData = new VibrationData(Virbators); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
Virbators = new SingleVirbator[2] |
|
||||||
{ |
|
||||||
new SingleVirbator(), |
|
||||||
new SingleVirbator(2, Duration2, Amplitude2), |
|
||||||
}; |
|
||||||
vibrationData = new VibrationData(Virbators); |
|
||||||
} |
|
||||||
Network.SendVibrationMsg(CharacterName, SendBackIP, vibrationData); |
|
||||||
} |
|
||||||
[Button] |
|
||||||
public void BothActiveWithVibrator_1Parameters() |
|
||||||
{ |
|
||||||
if (Network == null) return; |
|
||||||
SingleVirbator[] Virbators; |
|
||||||
if (Hand == HandType.Left) |
|
||||||
{ |
|
||||||
Virbators = new SingleVirbator[2] |
|
||||||
{ |
|
||||||
new SingleVirbator(3, Duration1, Amplitude1), |
|
||||||
new SingleVirbator() |
|
||||||
}; |
|
||||||
vibrationData = new VibrationData(Virbators); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
Virbators = new SingleVirbator[2] |
|
||||||
{ |
|
||||||
new SingleVirbator(), |
|
||||||
new SingleVirbator(3, Duration1, Amplitude1), |
|
||||||
}; |
|
||||||
vibrationData = new VibrationData(Virbators); |
|
||||||
} |
|
||||||
Network.SendVibrationMsg(CharacterName, SendBackIP, vibrationData); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
// Start is called before the first frame update |
|
||||||
void Start() |
|
||||||
{ |
|
||||||
if (GameObject.Find("Network") == null && (UsingAndroidService || UsingNetwork)) |
|
||||||
{ |
|
||||||
GameObject network = new GameObject("Network"); |
|
||||||
network.AddComponent<Network>(); |
|
||||||
Network = GameObject.Find("Network").GetComponent<Network>(); |
|
||||||
} |
|
||||||
else if (UsingAndroidService || UsingNetwork) |
|
||||||
{ |
|
||||||
Network = GameObject.Find("Network").GetComponent<Network>(); |
|
||||||
} |
|
||||||
|
|
||||||
_originQuaternionDic = new Dictionary<string, Quaternion>(); |
|
||||||
InitJoints(); |
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(SendBackIP) || UsingAndroidService) |
|
||||||
{ |
|
||||||
SendBackIP = "127.0.0.1"; |
|
||||||
} |
|
||||||
|
|
||||||
var Virbators = new SingleVirbator[2] |
|
||||||
{ |
|
||||||
new SingleVirbator(0, 0, 1), |
|
||||||
new SingleVirbator(0, 0, 1) |
|
||||||
}; |
|
||||||
|
|
||||||
vibrationData = new VibrationData(Virbators); |
|
||||||
|
|
||||||
if(UsingAndroidService) |
|
||||||
{ |
|
||||||
CharacterName = "AndroidService"; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private void InitJoints() |
|
||||||
{ |
|
||||||
_originQuaternionDic.AddOrUpdate(Thumb1.name, Thumb1.localRotation); |
|
||||||
_originQuaternionDic.AddOrUpdate(Thumb2.name, Thumb2.localRotation); |
|
||||||
_originQuaternionDic.AddOrUpdate(Thumb3.name, Thumb3.localRotation); |
|
||||||
|
|
||||||
_originQuaternionDic.AddOrUpdate(Index1.name, Index1.localRotation); |
|
||||||
_originQuaternionDic.AddOrUpdate(Index2.name, Index2.localRotation); |
|
||||||
_originQuaternionDic.AddOrUpdate(Index3.name, Index3.localRotation); |
|
||||||
|
|
||||||
_originQuaternionDic.AddOrUpdate(Middle1.name, Middle1.localRotation); |
|
||||||
_originQuaternionDic.AddOrUpdate(Middle2.name, Middle2.localRotation); |
|
||||||
_originQuaternionDic.AddOrUpdate(Middle3.name, Middle3.localRotation); |
|
||||||
|
|
||||||
_originQuaternionDic.AddOrUpdate(Ring1.name, Ring1.localRotation); |
|
||||||
_originQuaternionDic.AddOrUpdate(Ring2.name, Ring2.localRotation); |
|
||||||
_originQuaternionDic.AddOrUpdate(Ring3.name, Ring3.localRotation); |
|
||||||
|
|
||||||
_originQuaternionDic.AddOrUpdate(Pinky1.name, Pinky1.localRotation); |
|
||||||
_originQuaternionDic.AddOrUpdate(Pinky2.name, Pinky2.localRotation); |
|
||||||
_originQuaternionDic.AddOrUpdate(Pinky3.name, Pinky3.localRotation); |
|
||||||
|
|
||||||
_originQuaternionDic.AddOrUpdate(Wrist.name, Wrist.localRotation); |
|
||||||
} |
|
||||||
|
|
||||||
private void Rotate(Transform tran, float angle, Axis angleType) |
|
||||||
{ |
|
||||||
if (!NeedRealTransfrom) return; |
|
||||||
|
|
||||||
float angleX = 0; |
|
||||||
float angleY = 0; |
|
||||||
float angleZ = 0; |
|
||||||
|
|
||||||
switch (angleType) |
|
||||||
{ |
|
||||||
case Axis.x_n: |
|
||||||
angleX = -angle; |
|
||||||
break; |
|
||||||
case Axis.y_n: |
|
||||||
angleY = -angle; |
|
||||||
break; |
|
||||||
case Axis.z_n: |
|
||||||
angleZ = -angle; |
|
||||||
break; |
|
||||||
case Axis.x: |
|
||||||
angleX = angle; |
|
||||||
break; |
|
||||||
case Axis.y: |
|
||||||
angleY = angle; |
|
||||||
break; |
|
||||||
case Axis.z: |
|
||||||
angleZ = angle; |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
tran.Rotate(angleX, angleY, angleZ); |
|
||||||
} |
|
||||||
|
|
||||||
private Vector3 ConvertAngleToVec3(Vector3 current, float angle, Axis angleType) |
|
||||||
{ |
|
||||||
float angleX = 0; |
|
||||||
float angleY = 0; |
|
||||||
float angleZ = 0; |
|
||||||
|
|
||||||
switch (angleType) |
|
||||||
{ |
|
||||||
case Axis.x_n: |
|
||||||
angleX = -angle; |
|
||||||
break; |
|
||||||
case Axis.y_n: |
|
||||||
angleY = -angle; |
|
||||||
break; |
|
||||||
case Axis.z_n: |
|
||||||
angleZ = -angle; |
|
||||||
break; |
|
||||||
case Axis.x: |
|
||||||
angleX = angle; |
|
||||||
break; |
|
||||||
case Axis.y: |
|
||||||
angleY = angle; |
|
||||||
break; |
|
||||||
case Axis.z: |
|
||||||
angleZ = angle; |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
return current + new Vector3(angleX, angleY, angleZ); |
|
||||||
} |
|
||||||
|
|
||||||
private void ResetRotation(Transform trans) |
|
||||||
{ |
|
||||||
if (_originQuaternionDic.TryGetValue(trans.name, out Quaternion rot)) |
|
||||||
{ |
|
||||||
trans.localRotation = rot; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public void GetVec3Value(Vector3[] value) |
|
||||||
{ |
|
||||||
thumb1 = value[0]; |
|
||||||
thumb2 = value[1]; |
|
||||||
thumb3 = value[2]; |
|
||||||
|
|
||||||
index1 = value[3]; |
|
||||||
index2 = value[4]; |
|
||||||
index3 = value[5]; |
|
||||||
|
|
||||||
middle1 = value[6]; |
|
||||||
middle2 = value[7]; |
|
||||||
middle3 = value[8]; |
|
||||||
|
|
||||||
ring1 = value[9]; |
|
||||||
ring2 = value[10]; |
|
||||||
ring3 = value[11]; |
|
||||||
|
|
||||||
pinky1 = value[12]; |
|
||||||
pinky2 = value[13]; |
|
||||||
pinky3 = value[14]; |
|
||||||
} |
|
||||||
|
|
||||||
// Update is called once per frame |
|
||||||
void Update() |
|
||||||
{ |
|
||||||
if (UsingNetwork || UsingAndroidService) |
|
||||||
{ |
|
||||||
UpdateThumb(); |
|
||||||
UpdateIndex(); |
|
||||||
UpdateMiddle(); |
|
||||||
UpdateRing(); |
|
||||||
UpdatePinky(); |
|
||||||
|
|
||||||
UpdateWrist(); |
|
||||||
UpdateController(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private void UpdateWrist() |
|
||||||
{ |
|
||||||
if (HasIMU) |
|
||||||
{ |
|
||||||
if (Hand == HandType.Left) |
|
||||||
{ |
|
||||||
Quaternion quat_r = new Quaternion( |
|
||||||
Network.Convert2Angle(CharacterName, "l26"),//x |
|
||||||
Network.Convert2Angle(CharacterName, "l25"),//y |
|
||||||
Network.Convert2Angle(CharacterName, "l27"),//z |
|
||||||
Network.Convert2Angle(CharacterName, "l24"));//w |
|
||||||
ResetRotation(Wrist); |
|
||||||
quat_r = ConvertQuaternion(quat_r); |
|
||||||
Wrist.rotation = quat_r; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
Quaternion quat_r = new Quaternion(Network.Convert2Angle(CharacterName, "r26"), |
|
||||||
Network.Convert2Angle(CharacterName, "r25"), |
|
||||||
Network.Convert2Angle(CharacterName, "r27"), Network.Convert2Angle(CharacterName, "r24")); |
|
||||||
ResetRotation(Wrist); |
|
||||||
quat_r = ConvertQuaternion(quat_r); |
|
||||||
Wrist.rotation = quat_r; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private void UpdateController() |
|
||||||
{ |
|
||||||
if (Hand == HandType.Left) |
|
||||||
{ |
|
||||||
Joy_X = Network.Convert2Angle(CharacterName, "l_joyX"); |
|
||||||
Joy_Y = Network.Convert2Angle(CharacterName, "l_joyY"); |
|
||||||
Button_A = Network.Convert2Bool(CharacterName, "l_aButton"); |
|
||||||
Button_B = Network.Convert2Bool(CharacterName, "l_bButton"); |
|
||||||
Button_Joystick = Network.Convert2Bool(CharacterName, "l_joyButton"); |
|
||||||
Button_Menu = Network.Convert2Bool(CharacterName, "l_menu"); |
|
||||||
inputData.joyX = Joy_X; |
|
||||||
inputData.joyY = Joy_Y; |
|
||||||
inputData.aButton = Button_A; |
|
||||||
inputData.bButton = Button_B; |
|
||||||
inputData.joyButton = Button_Joystick; |
|
||||||
inputData.menu = Button_Menu; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
Joy_X = Network.Convert2Angle(CharacterName, "r_joyX"); |
|
||||||
Joy_Y = Network.Convert2Angle(CharacterName, "r_joyY"); |
|
||||||
Button_A = Network.Convert2Bool(CharacterName, "r_aButton"); |
|
||||||
Button_B = Network.Convert2Bool(CharacterName, "r_bButton"); |
|
||||||
Button_Joystick = Network.Convert2Bool(CharacterName, "r_joyButton"); |
|
||||||
Button_Menu = Network.Convert2Bool(CharacterName, "r_menu"); |
|
||||||
inputData.joyX = Joy_X; |
|
||||||
inputData.joyY = Joy_Y; |
|
||||||
inputData.aButton = Button_A; |
|
||||||
inputData.bButton = Button_B; |
|
||||||
inputData.joyButton = Button_Joystick; |
|
||||||
inputData.menu = Button_Menu; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
//z轴朝上的右手坐标系 四元数 转换为 Y轴朝上的左手坐标系 四元数 |
|
||||||
private Quaternion ConvertQuaternion(Quaternion quat) |
|
||||||
{ |
|
||||||
Quaternion quat_r = new Quaternion(quat.x, quat.y, quat.z, quat.w); |
|
||||||
quat_r = Quaternion.Euler(quat_r.eulerAngles.z, -quat_r.eulerAngles.x, quat_r.eulerAngles.y); |
|
||||||
return quat_r; |
|
||||||
} |
|
||||||
|
|
||||||
private void UpdateThumb() |
|
||||||
{ |
|
||||||
if (NeedRealTransfrom) |
|
||||||
{ |
|
||||||
ResetRotation(Thumb1); |
|
||||||
ResetRotation(Thumb2); |
|
||||||
ResetRotation(Thumb3); |
|
||||||
} |
|
||||||
if (Hand == HandType.Left) |
|
||||||
{ |
|
||||||
var thumb3Pitch = Network.Convert2Angle(CharacterName, "l0"); |
|
||||||
var thumb2Pitch = Network.Convert2Angle(CharacterName, "l1"); |
|
||||||
var thumb1Pitch = Network.Convert2Angle(CharacterName, "l2") * coefficient + Thumb1Offset.y; |
|
||||||
var thumb1Yaw = Network.Convert2Angle(CharacterName, "l3") + Thumb1Offset.z; |
|
||||||
var thumb1Roll = Network.Convert2Angle(CharacterName, "l20") + Thumb1Offset.x; |
|
||||||
|
|
||||||
thumb3 = ConvertAngleToVec3(Vector3.zero, thumb3Pitch, Pitch); |
|
||||||
thumb2 = ConvertAngleToVec3(Vector3.zero, thumb2Pitch, Pitch); |
|
||||||
thumb1 = ConvertAngleToVec3(Vector3.zero, thumb1Pitch, Pitch); |
|
||||||
thumb1 = ConvertAngleToVec3(thumb1, thumb1Yaw, Yaw); |
|
||||||
thumb1 = ConvertAngleToVec3(thumb1, thumb1Roll, Roll); |
|
||||||
|
|
||||||
Rotate(Thumb3, thumb3Pitch, Pitch); |
|
||||||
Rotate(Thumb2, thumb2Pitch, Pitch); |
|
||||||
Rotate(Thumb1, thumb1Pitch, Pitch); |
|
||||||
Rotate(Thumb1, thumb1Yaw, Yaw); |
|
||||||
Rotate(Thumb1, thumb1Roll, Roll); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
|
|
||||||
var thumb3Pitch = Network.Convert2Angle(CharacterName, "r0"); |
|
||||||
var thumb2Pitch = Network.Convert2Angle(CharacterName, "r1"); |
|
||||||
var thumb1Pitch = Network.Convert2Angle(CharacterName, "r2") * coefficient + Thumb1Offset.y; |
|
||||||
var thumb1Yaw = Network.Convert2Angle(CharacterName, "r3") + Thumb1Offset.z; |
|
||||||
var thumb1Roll = Network.Convert2Angle(CharacterName, "r20") + Thumb1Offset.x; |
|
||||||
|
|
||||||
thumb3 = ConvertAngleToVec3(Vector3.zero, thumb3Pitch, Pitch); |
|
||||||
thumb2 = ConvertAngleToVec3(Vector3.zero, thumb2Pitch, Pitch); |
|
||||||
thumb1 = ConvertAngleToVec3(Vector3.zero, thumb1Pitch, Pitch); |
|
||||||
thumb1 = ConvertAngleToVec3(thumb1, thumb1Yaw, Yaw); |
|
||||||
thumb1 = ConvertAngleToVec3(thumb1, thumb1Roll, Roll); |
|
||||||
|
|
||||||
Rotate(Thumb3, thumb3Pitch, Pitch); |
|
||||||
Rotate(Thumb2, thumb2Pitch, Pitch); |
|
||||||
Rotate(Thumb1, thumb1Pitch, Pitch); |
|
||||||
Rotate(Thumb1, thumb1Yaw, Yaw); |
|
||||||
Rotate(Thumb1, thumb1Roll, Roll); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private void UpdateIndex() |
|
||||||
{ |
|
||||||
if (NeedRealTransfrom) |
|
||||||
{ |
|
||||||
ResetRotation(Index1); |
|
||||||
ResetRotation(Index2); |
|
||||||
ResetRotation(Index3); |
|
||||||
} |
|
||||||
if (Hand == HandType.Left) |
|
||||||
{ |
|
||||||
var index3Pitch = Network.Convert2Angle(CharacterName, "l4"); |
|
||||||
var index2Pitch = Network.Convert2Angle(CharacterName, "l5"); |
|
||||||
var index1Pitch = Network.Convert2Angle(CharacterName, "l6"); |
|
||||||
var index1Yaw = Network.Convert2Angle(CharacterName, "l7"); |
|
||||||
var index1Roll = Network.Convert2Angle(CharacterName, "l21"); |
|
||||||
|
|
||||||
index3 = ConvertAngleToVec3(Vector3.zero, index3Pitch, Pitch); |
|
||||||
index2 = ConvertAngleToVec3(Vector3.zero, index2Pitch, Pitch); |
|
||||||
index1 = ConvertAngleToVec3(Vector3.zero, index1Pitch, Pitch); |
|
||||||
index1 = ConvertAngleToVec3(index1, index1Yaw, Yaw); |
|
||||||
index1 = ConvertAngleToVec3(index1, index1Roll, Roll); |
|
||||||
|
|
||||||
Rotate(Index3, index3Pitch, Pitch); |
|
||||||
Rotate(Index2, index2Pitch, Pitch); |
|
||||||
Rotate(Index1, index1Pitch, Pitch); |
|
||||||
Rotate(Index1, index1Yaw, Yaw); |
|
||||||
Rotate(Index1, index1Roll, Roll); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
var index3Pitch = Network.Convert2Angle(CharacterName, "r4"); |
|
||||||
var index2Pitch = Network.Convert2Angle(CharacterName, "r5"); |
|
||||||
var index1Pitch = Network.Convert2Angle(CharacterName, "r6"); |
|
||||||
var index1Yaw = Network.Convert2Angle(CharacterName, "r7"); |
|
||||||
var index1Roll = Network.Convert2Angle(CharacterName, "r21"); |
|
||||||
|
|
||||||
index3 = ConvertAngleToVec3(Vector3.zero, index3Pitch, Pitch); |
|
||||||
index2 = ConvertAngleToVec3(Vector3.zero, index2Pitch, Pitch); |
|
||||||
index1 = ConvertAngleToVec3(Vector3.zero, index1Pitch, Pitch); |
|
||||||
index1 = ConvertAngleToVec3(index1, index1Yaw, Yaw); |
|
||||||
index1 = ConvertAngleToVec3(index1, index1Roll, Roll); |
|
||||||
|
|
||||||
Rotate(Index3, index3Pitch, Pitch); |
|
||||||
Rotate(Index2, index2Pitch, Pitch); |
|
||||||
Rotate(Index1, index1Pitch, Pitch); |
|
||||||
Rotate(Index1, index1Yaw, Yaw); |
|
||||||
Rotate(Index1, index1Roll, Roll); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private void UpdateMiddle() |
|
||||||
{ |
|
||||||
if (NeedRealTransfrom) |
|
||||||
{ |
|
||||||
ResetRotation(Middle1); |
|
||||||
ResetRotation(Middle2); |
|
||||||
ResetRotation(Middle3); |
|
||||||
} |
|
||||||
if (Hand == HandType.Left) |
|
||||||
{ |
|
||||||
var middle3Pitch = Network.Convert2Angle(CharacterName, "l8"); |
|
||||||
var middle2Pitch = Network.Convert2Angle(CharacterName, "l9"); |
|
||||||
var middle1Pitch = Network.Convert2Angle(CharacterName, "l10"); |
|
||||||
var middle1Yaw = Network.Convert2Angle(CharacterName, "l11"); |
|
||||||
|
|
||||||
middle3 = ConvertAngleToVec3(Vector3.zero, middle3Pitch, Pitch); |
|
||||||
middle2 = ConvertAngleToVec3(Vector3.zero, middle2Pitch, Pitch); |
|
||||||
middle1 = ConvertAngleToVec3(Vector3.zero, middle1Pitch, Pitch); |
|
||||||
middle1 = ConvertAngleToVec3(middle1, middle1Yaw, Yaw); |
|
||||||
|
|
||||||
Rotate(Middle3, middle3Pitch, Pitch); |
|
||||||
Rotate(Middle2, middle2Pitch, Pitch); |
|
||||||
Rotate(Middle1, middle1Pitch, Pitch); |
|
||||||
Rotate(Middle1, middle1Yaw, Yaw); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
var middle3Pitch = Network.Convert2Angle(CharacterName, "r8"); |
|
||||||
var middle2Pitch = Network.Convert2Angle(CharacterName, "r9"); |
|
||||||
var middle1Pitch = Network.Convert2Angle(CharacterName, "r10"); |
|
||||||
var middle1Yaw = Network.Convert2Angle(CharacterName, "r11"); |
|
||||||
|
|
||||||
middle3 = ConvertAngleToVec3(Vector3.zero, middle3Pitch, Pitch); |
|
||||||
middle2 = ConvertAngleToVec3(Vector3.zero, middle2Pitch, Pitch); |
|
||||||
middle1 = ConvertAngleToVec3(Vector3.zero, middle1Pitch, Pitch); |
|
||||||
middle1 = ConvertAngleToVec3(middle1, middle1Yaw, Yaw); |
|
||||||
|
|
||||||
Rotate(Middle3, middle3Pitch, Pitch); |
|
||||||
Rotate(Middle2, middle2Pitch, Pitch); |
|
||||||
Rotate(Middle1, middle1Pitch, Pitch); |
|
||||||
Rotate(Middle1, middle1Yaw, Yaw); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private void UpdateRing() |
|
||||||
{ |
|
||||||
if (NeedRealTransfrom) |
|
||||||
{ |
|
||||||
ResetRotation(Ring1); |
|
||||||
ResetRotation(Ring2); |
|
||||||
ResetRotation(Ring3); |
|
||||||
} |
|
||||||
if (Hand == HandType.Left) |
|
||||||
{ |
|
||||||
var ring3Pitch = Network.Convert2Angle(CharacterName, "l12"); |
|
||||||
var ring2Pitch = Network.Convert2Angle(CharacterName, "l13"); |
|
||||||
var ring1Pitch = Network.Convert2Angle(CharacterName, "l14"); |
|
||||||
var ring1Yaw = Network.Convert2Angle(CharacterName, "l15"); |
|
||||||
|
|
||||||
ring3 = ConvertAngleToVec3(Vector3.zero, ring3Pitch, Pitch); |
|
||||||
ring2 = ConvertAngleToVec3(Vector3.zero, ring2Pitch, Pitch); |
|
||||||
ring1 = ConvertAngleToVec3(Vector3.zero, ring1Pitch, Pitch); |
|
||||||
ring1 = ConvertAngleToVec3(ring1, ring1Yaw, Yaw); |
|
||||||
|
|
||||||
Rotate(Ring3, ring3Pitch, Pitch); |
|
||||||
Rotate(Ring2, ring2Pitch, Pitch); |
|
||||||
Rotate(Ring1, ring1Pitch, Pitch); |
|
||||||
Rotate(Ring1, ring1Yaw, Yaw); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
var ring3Pitch = Network.Convert2Angle(CharacterName, "r12"); |
|
||||||
var ring2Pitch = Network.Convert2Angle(CharacterName, "r13"); |
|
||||||
var ring1Pitch = Network.Convert2Angle(CharacterName, "r14"); |
|
||||||
var ring1Yaw = Network.Convert2Angle(CharacterName, "r15"); |
|
||||||
|
|
||||||
ring3 = ConvertAngleToVec3(Vector3.zero, ring3Pitch, Pitch); |
|
||||||
ring2 = ConvertAngleToVec3(Vector3.zero, ring2Pitch, Pitch); |
|
||||||
ring1 = ConvertAngleToVec3(Vector3.zero, ring1Pitch, Pitch); |
|
||||||
ring1 = ConvertAngleToVec3(ring1, ring1Yaw, Yaw); |
|
||||||
|
|
||||||
Rotate(Ring3, ring3Pitch, Pitch); |
|
||||||
Rotate(Ring2, ring2Pitch, Pitch); |
|
||||||
Rotate(Ring1, ring1Pitch, Pitch); |
|
||||||
Rotate(Ring1, ring1Yaw, Yaw); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private void UpdatePinky() |
|
||||||
{ |
|
||||||
if (NeedRealTransfrom) |
|
||||||
{ |
|
||||||
ResetRotation(Pinky1); |
|
||||||
ResetRotation(Pinky2); |
|
||||||
ResetRotation(Pinky3); |
|
||||||
} |
|
||||||
if (Hand == HandType.Left) |
|
||||||
{ |
|
||||||
var pinky3Pitch = Network.Convert2Angle(CharacterName, "l16"); |
|
||||||
var pinky2Pitch = Network.Convert2Angle(CharacterName, "l17"); |
|
||||||
var pinky1Pitch = Network.Convert2Angle(CharacterName, "l18"); |
|
||||||
var pinky1Yaw = Network.Convert2Angle(CharacterName, "l19"); |
|
||||||
var pinky1Roll = Network.Convert2Angle(CharacterName, "l22"); |
|
||||||
|
|
||||||
pinky3 = ConvertAngleToVec3(Vector3.zero, pinky3Pitch, Pitch); |
|
||||||
pinky2 = ConvertAngleToVec3(Vector3.zero, pinky2Pitch, Pitch); |
|
||||||
pinky1 = ConvertAngleToVec3(Vector3.zero, pinky1Pitch, Pitch); |
|
||||||
pinky1 = ConvertAngleToVec3(pinky1, pinky1Yaw, Yaw); |
|
||||||
pinky1 = ConvertAngleToVec3(pinky1, pinky1Roll, Roll); |
|
||||||
|
|
||||||
Rotate(Pinky3, pinky3Pitch, Pitch); |
|
||||||
Rotate(Pinky2, pinky2Pitch, Pitch); |
|
||||||
Rotate(Pinky1, pinky1Pitch, Pitch); |
|
||||||
Rotate(Pinky1, pinky1Yaw, Yaw); |
|
||||||
Rotate(Pinky1, pinky1Roll, Roll); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
var pinky3Pitch = Network.Convert2Angle(CharacterName, "r16"); |
|
||||||
var pinky2Pitch = Network.Convert2Angle(CharacterName, "r17"); |
|
||||||
var pinky1Pitch = Network.Convert2Angle(CharacterName, "r18"); |
|
||||||
var pinky1Yaw = Network.Convert2Angle(CharacterName, "r19"); |
|
||||||
var pinky1Roll = Network.Convert2Angle(CharacterName, "r22"); |
|
||||||
|
|
||||||
pinky3 = ConvertAngleToVec3(Vector3.zero, pinky3Pitch, Pitch); |
|
||||||
pinky2 = ConvertAngleToVec3(Vector3.zero, pinky2Pitch, Pitch); |
|
||||||
pinky1 = ConvertAngleToVec3(Vector3.zero, pinky1Pitch, Pitch); |
|
||||||
pinky1 = ConvertAngleToVec3(pinky1, pinky1Yaw, Yaw); |
|
||||||
pinky1 = ConvertAngleToVec3(pinky1, pinky1Roll, Roll); |
|
||||||
|
|
||||||
Rotate(Pinky3, pinky3Pitch, Pitch); |
|
||||||
Rotate(Pinky2, pinky2Pitch, Pitch); |
|
||||||
Rotate(Pinky1, pinky1Pitch, Pitch); |
|
||||||
Rotate(Pinky1, pinky1Yaw, Yaw); |
|
||||||
Rotate(Pinky1, pinky1Roll, Roll); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public void ServiceVibrationControl(int VirbatorIndex = 1, int DurationSecond = 20, int Strength = 10) |
|
||||||
{ |
|
||||||
if (Network == null || !UsingAndroidService) return; |
|
||||||
|
|
||||||
SingleVirbator[] Virbators; |
|
||||||
if (Hand == HandType.Left) |
|
||||||
{ |
|
||||||
Virbators = new SingleVirbator[2] |
|
||||||
{ |
|
||||||
new SingleVirbator(VirbatorIndex, DurationSecond, Strength), |
|
||||||
new SingleVirbator() |
|
||||||
}; |
|
||||||
vibrationData = new VibrationData(Virbators); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
Virbators = new SingleVirbator[2] |
|
||||||
{ |
|
||||||
new SingleVirbator(), |
|
||||||
new SingleVirbator(VirbatorIndex, DurationSecond, Strength), |
|
||||||
}; |
|
||||||
vibrationData = new VibrationData(Virbators); |
|
||||||
} |
|
||||||
Network.SendVibrationMsg("AndroidService", "127.0.0.1", vibrationData); |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: c4912e9bafca683489c72f3a27094c57 |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,35 +0,0 @@ |
|||||||
//Struct InputData is a struct that contains all of the button, finger, and linear inputs. This is what's sent to the driver via the named pipe. |
|
||||||
public struct InputData |
|
||||||
{ |
|
||||||
|
|
||||||
public float joyX; //range: -1 -> 1 |
|
||||||
public float joyY; //range: -1 -> 1 |
|
||||||
public bool joyButton; |
|
||||||
public bool trgButton; |
|
||||||
public bool aButton; |
|
||||||
public bool bButton; |
|
||||||
public bool grab; |
|
||||||
//public bool pinch; |
|
||||||
public bool menu; |
|
||||||
//public bool calibrate; |
|
||||||
public bool trackpad_touch; |
|
||||||
public float trgValue; //range: 0 -> 1 |
|
||||||
|
|
||||||
//constructor that uses a 1d array for flexion. |
|
||||||
public InputData(float joyX, float joyY, bool joyButton, bool trgButton, |
|
||||||
bool aButton, bool bButton, bool grab, bool pinch, bool menu, bool calibrate, float trgValue,bool trackpad_touch) |
|
||||||
{ |
|
||||||
this.joyX = joyX; |
|
||||||
this.joyY = joyY; |
|
||||||
this.joyButton = joyButton; |
|
||||||
this.trgButton = trgButton; |
|
||||||
this.aButton = aButton; |
|
||||||
this.bButton = bButton; |
|
||||||
this.grab = grab; |
|
||||||
//this.pinch = pinch; |
|
||||||
this.menu = menu; |
|
||||||
//this.calibrate = calibrate; |
|
||||||
this.trgValue = trgValue; |
|
||||||
this.trackpad_touch = trackpad_touch; |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 0dcc86f284979df4ead3842bec665562 |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,207 +0,0 @@ |
|||||||
using Newtonsoft.Json.Linq; |
|
||||||
using System; |
|
||||||
using System.Collections.Concurrent; |
|
||||||
using System.IO; |
|
||||||
using System.Net; |
|
||||||
using System.Text; |
|
||||||
using TouchSocket.Core; |
|
||||||
using TouchSocket.Sockets; |
|
||||||
using UnityEngine; |
|
||||||
|
|
||||||
public class Network : MonoBehaviour |
|
||||||
{ |
|
||||||
|
|
||||||
public int Port = 5555; |
|
||||||
|
|
||||||
private UdpSession _udpClient; |
|
||||||
|
|
||||||
private ConcurrentDictionary<string, ConcurrentDictionary<string, string>> _deviceReadMessages; |
|
||||||
|
|
||||||
private StreamWriter writer; |
|
||||||
private string _txtPath; |
|
||||||
void Start() |
|
||||||
{ |
|
||||||
_txtPath = Application.dataPath + "stream.data"; |
|
||||||
_deviceReadMessages = new ConcurrentDictionary<string, ConcurrentDictionary<string, string>>(); |
|
||||||
_udpClient = new UdpSession(); |
|
||||||
|
|
||||||
_udpClient.Received += ReceiveMsg; |
|
||||||
|
|
||||||
_udpClient.Setup(new TouchSocketConfig() |
|
||||||
.SetBindIPHost(new IPHost(Port)) |
|
||||||
.SetUdpDataHandlingAdapter(() => new NormalUdpDataHandlingAdapter())) |
|
||||||
.Start(); |
|
||||||
|
|
||||||
Debug.Log("UDP Client Start!!"); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
private void WriteIntoTxt(string message) |
|
||||||
{ |
|
||||||
FileInfo file = new FileInfo(_txtPath); |
|
||||||
if (!file.Exists) |
|
||||||
{ |
|
||||||
writer = file.CreateText(); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
writer = file.AppendText(); |
|
||||||
} |
|
||||||
|
|
||||||
writer.WriteLine(message); |
|
||||||
writer.Flush(); |
|
||||||
writer.Dispose(); |
|
||||||
writer.Close(); |
|
||||||
} |
|
||||||
|
|
||||||
private void ReceiveMsg(EndPoint endpoint, ByteBlock byteblock, IRequestInfo requestinfo) |
|
||||||
{ |
|
||||||
string msg = Encoding.UTF8.GetString(byteblock.Buffer, 0, byteblock.Len); |
|
||||||
Debug.Log(msg); |
|
||||||
//WriteIntoTxt(msg); |
|
||||||
JObject obj = JObject.Parse(msg); |
|
||||||
var jps = obj.Properties(); |
|
||||||
foreach (var jp in jps) |
|
||||||
{ |
|
||||||
string role_name = jp.Name; |
|
||||||
|
|
||||||
JToken token = obj.GetValue(role_name); |
|
||||||
JArray array = token["Parameter"] as JArray; |
|
||||||
ConcurrentDictionary<string, string> _deviceMsg = new ConcurrentDictionary<string, string>(); |
|
||||||
for (int i = 0; i < array.Count; i++) |
|
||||||
{ |
|
||||||
JObject obj1 = array[i] as JObject; |
|
||||||
string key = obj1.GetValue("Name").ToString(); |
|
||||||
string value = obj1.GetValue("Value").ToString(); |
|
||||||
_deviceMsg.TryAdd(key, value); |
|
||||||
} |
|
||||||
if (_deviceReadMessages.ContainsKey(role_name)) |
|
||||||
{ |
|
||||||
_deviceReadMessages[role_name] = _deviceMsg; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
_deviceReadMessages.TryAdd(role_name, _deviceMsg); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
//JToken token = obj.GetValue("Device1_"+Port); |
|
||||||
//JArray array = token["Parameter"] as JArray; |
|
||||||
//for (int i = 0; i < array.Count; i++) |
|
||||||
//{ |
|
||||||
// JObject obj1 = array[i] as JObject; |
|
||||||
// string key = obj1.GetValue("Name").ToString(); |
|
||||||
// string value = obj1.GetValue("Value").ToString(); |
|
||||||
// _device1ReadMessages.AddOrUpdate(key, value); |
|
||||||
//} |
|
||||||
|
|
||||||
//JToken token2 = obj.GetValue("Device2_"+Port); |
|
||||||
//JArray array2 = token2["Parameter"] as JArray; |
|
||||||
//for (int i = 0; i < array.Count; i++) |
|
||||||
//{ |
|
||||||
// JObject obj1 = array2[i] as JObject; |
|
||||||
// string key = obj1.GetValue("Name").ToString(); |
|
||||||
// string value = obj1.GetValue("Value").ToString(); |
|
||||||
// _device2ReadMessages.AddOrUpdate(key, value); |
|
||||||
//} |
|
||||||
} |
|
||||||
|
|
||||||
// Update is called once per frame |
|
||||||
void Update() |
|
||||||
{ |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
public float Convert2Angle(string role_name, string key) |
|
||||||
{ |
|
||||||
float angle = 0; |
|
||||||
if (!string.IsNullOrEmpty(role_name)) |
|
||||||
{ |
|
||||||
if (!_deviceReadMessages.ContainsKey(role_name)) |
|
||||||
{ |
|
||||||
return 0; |
|
||||||
} |
|
||||||
string str = _deviceReadMessages[role_name][key]; |
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(str)) |
|
||||||
{ |
|
||||||
angle = Single.Parse(str); |
|
||||||
} |
|
||||||
} |
|
||||||
return angle; |
|
||||||
} |
|
||||||
|
|
||||||
public bool Convert2Bool(string role_name, string key) |
|
||||||
{ |
|
||||||
bool flag = false; |
|
||||||
if (!string.IsNullOrEmpty(role_name)) |
|
||||||
{ |
|
||||||
if (!_deviceReadMessages.ContainsKey(role_name)) |
|
||||||
{ |
|
||||||
return false; |
|
||||||
} |
|
||||||
string str = _deviceReadMessages[role_name][key]; |
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(str)) |
|
||||||
{ |
|
||||||
flag = bool.Parse(str); |
|
||||||
} |
|
||||||
} |
|
||||||
return flag; |
|
||||||
} |
|
||||||
|
|
||||||
public void SendVibrationMsg(string RoleName, string IP, VibrationData data) |
|
||||||
{ |
|
||||||
var json_role = new JObject(); |
|
||||||
var json_one = new JObject(); |
|
||||||
var parameterArrayLeft = new JArray(); |
|
||||||
var parameterArrayRight = new JArray(); |
|
||||||
|
|
||||||
var _Lpara_active = new JObject(); |
|
||||||
_Lpara_active.Add("Name", "Vibrators"); |
|
||||||
_Lpara_active.Add("Value", data.Virbators[0].ActiveCommand); |
|
||||||
|
|
||||||
var _Lpara_duration = new JObject(); |
|
||||||
_Lpara_duration.Add("Name", "Duration"); |
|
||||||
_Lpara_duration.Add("Value", data.Virbators[0].Duration); |
|
||||||
|
|
||||||
var _Lpara_amplitude = new JObject(); |
|
||||||
_Lpara_amplitude.Add("Name", "Amplitude"); |
|
||||||
_Lpara_amplitude.Add("Value", data.Virbators[0].Amplitude); |
|
||||||
|
|
||||||
parameterArrayLeft.Add(_Lpara_active); |
|
||||||
parameterArrayLeft.Add(_Lpara_duration); |
|
||||||
parameterArrayLeft.Add(_Lpara_amplitude); |
|
||||||
|
|
||||||
var _Rpara_active = new JObject(); |
|
||||||
_Rpara_active.Add("Name", "Vibrators"); |
|
||||||
_Rpara_active.Add("Value", data.Virbators[1].ActiveCommand); |
|
||||||
|
|
||||||
var _Rpara_duration = new JObject(); |
|
||||||
_Rpara_duration.Add("Name", "Duration"); |
|
||||||
_Rpara_duration.Add("Value", data.Virbators[1].Duration); |
|
||||||
|
|
||||||
var _Rpara_amplitude = new JObject(); |
|
||||||
_Rpara_amplitude.Add("Name", "Amplitude"); |
|
||||||
_Rpara_amplitude.Add("Value", data.Virbators[1].Amplitude); |
|
||||||
|
|
||||||
parameterArrayRight.Add(_Rpara_active); |
|
||||||
parameterArrayRight.Add(_Rpara_duration); |
|
||||||
parameterArrayRight.Add(_Rpara_amplitude); |
|
||||||
|
|
||||||
json_one.Add("LeftHand", parameterArrayLeft); |
|
||||||
json_one.Add("RightHand", parameterArrayRight); |
|
||||||
json_role.Add(RoleName, json_one); |
|
||||||
|
|
||||||
Debug.Log(json_role.ToJson()); |
|
||||||
_udpClient.Send(new IPEndPoint(IPAddress.Parse(IP), 8920), Encoding.UTF8.GetBytes(json_role.ToJson())); |
|
||||||
} |
|
||||||
|
|
||||||
private void OnDestroy() |
|
||||||
{ |
|
||||||
_udpClient.Received -= ReceiveMsg; |
|
||||||
_udpClient.Stop(); |
|
||||||
_udpClient.Dispose(); |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 09a3acc4e9487ff42a0d425e4f64d16c |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,33 +0,0 @@ |
|||||||
|
|
||||||
public struct SingleVirbator |
|
||||||
{ |
|
||||||
public int ActiveCommand; |
|
||||||
public int Duration; |
|
||||||
public int Amplitude; |
|
||||||
|
|
||||||
public SingleVirbator(int command = 1, int duration = 0, int amplitude = 4) |
|
||||||
{ |
|
||||||
command = command < 1 ? 1 : command > 3 ? 3 : command; |
|
||||||
duration = duration < 0 ? 0 : duration; |
|
||||||
amplitude = amplitude < 4 ? 4 : amplitude > 10 ? 10 : amplitude; |
|
||||||
|
|
||||||
ActiveCommand = command; |
|
||||||
Duration = duration; |
|
||||||
Amplitude = amplitude; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public class VibrationData |
|
||||||
{ |
|
||||||
public SingleVirbator[] Virbators = new SingleVirbator[2]; |
|
||||||
|
|
||||||
public VibrationData(SingleVirbator[] virbators) |
|
||||||
{ |
|
||||||
if (virbators.Length != 2) return; |
|
||||||
|
|
||||||
for (int i = 0; i < virbators.Length; i++) |
|
||||||
{ |
|
||||||
Virbators[i] = virbators[i]; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 75c4983c107b62942888902b38f76ba6 |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,8 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: cdf9bacc33468244686934a49aa9a620 |
|
||||||
folderAsset: yes |
|
||||||
DefaultImporter: |
|
||||||
externalObjects: {} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,8 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: e1102a8bb1c06f94880e4da841d2732a |
|
||||||
folderAsset: yes |
|
||||||
DefaultImporter: |
|
||||||
externalObjects: {} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,8 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: b771b2c214473934a9045eb277704b07 |
|
||||||
folderAsset: yes |
|
||||||
DefaultImporter: |
|
||||||
externalObjects: {} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,8 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: fb3f51f059e0164419ceba82a86e529d |
|
||||||
folderAsset: yes |
|
||||||
DefaultImporter: |
|
||||||
externalObjects: {} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 5e025222c673874469ee491627182d5b |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,438 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
using System; |
|
||||||
using System.Collections.Concurrent; |
|
||||||
using System.Collections.Generic; |
|
||||||
using System.Linq; |
|
||||||
using System.Runtime.CompilerServices; |
|
||||||
using System.Threading; |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 内存池 |
|
||||||
/// </summary> |
|
||||||
//[IntelligentCoder.AsyncMethodPoster(Flags = IntelligentCoder.MemberFlags.Public)] |
|
||||||
public partial class BytePool |
|
||||||
{ |
|
||||||
private readonly ConcurrentDictionary<long, BytesQueue> bytesDictionary = new ConcurrentDictionary<long, BytesQueue>(); |
|
||||||
private readonly Timer m_timer; |
|
||||||
private long m_fullSize; |
|
||||||
private long m_maxSize; |
|
||||||
|
|
||||||
static BytePool() |
|
||||||
{ |
|
||||||
Default = new BytePool(); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 内存池 |
|
||||||
/// </summary> |
|
||||||
public BytePool() |
|
||||||
{ |
|
||||||
m_timer = new Timer((o) => |
|
||||||
{ |
|
||||||
Clear(); |
|
||||||
}, null, 1000 * 60 * 60, 1000 * 60 * 60); |
|
||||||
KeyCapacity = 100; |
|
||||||
AutoZero = false; |
|
||||||
m_maxSize = 1024 * 1024 * 512; |
|
||||||
SetBlockSize(1024, 1024 * 1024 * 20); |
|
||||||
AddSizeKey(10240); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 默认的内存池实例 |
|
||||||
/// </summary> |
|
||||||
public static BytePool Default { get; } |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 回收内存时,自动归零 |
|
||||||
/// </summary> |
|
||||||
public bool AutoZero { get; set; } |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 键容量 |
|
||||||
/// </summary> |
|
||||||
public int KeyCapacity { get; set; } |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 单个块最大值 |
|
||||||
/// </summary> |
|
||||||
public int MaxBlockSize { get; private set; } |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 允许的内存池最大值 |
|
||||||
/// </summary> |
|
||||||
public long MaxSize |
|
||||||
{ |
|
||||||
get => m_maxSize; |
|
||||||
set |
|
||||||
{ |
|
||||||
if (value < 1024) |
|
||||||
{ |
|
||||||
value = 1024; |
|
||||||
} |
|
||||||
m_maxSize = value; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 单个块最小值 |
|
||||||
/// </summary> |
|
||||||
public int MinBlockSize { get; private set; } |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 添加尺寸键 |
|
||||||
/// </summary> |
|
||||||
/// <param name="byteSize"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public bool AddSizeKey(int byteSize) |
|
||||||
{ |
|
||||||
if (bytesDictionary.TryAdd(byteSize, new BytesQueue(byteSize))) |
|
||||||
{ |
|
||||||
return true; |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 清理 |
|
||||||
/// </summary> |
|
||||||
public void Clear() |
|
||||||
{ |
|
||||||
bytesDictionary.Clear(); |
|
||||||
GC.Collect(); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 确定是否包含指定尺寸键 |
|
||||||
/// </summary> |
|
||||||
/// <param name="byteSize"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public bool ContainsSizeKey(int byteSize) |
|
||||||
{ |
|
||||||
return bytesDictionary.ContainsKey(byteSize); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 获取所以内存键 |
|
||||||
/// </summary> |
|
||||||
/// <returns></returns> |
|
||||||
public long[] GetAllSizeKeys() |
|
||||||
{ |
|
||||||
return bytesDictionary.Keys.ToArray(); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 获取ByteBlock |
|
||||||
/// </summary> |
|
||||||
/// <param name="byteSize">长度</param> |
|
||||||
/// <param name="equalSize">要求长度相同</param> |
|
||||||
/// <returns></returns> |
|
||||||
public ByteBlock GetByteBlock(int byteSize, bool equalSize) |
|
||||||
{ |
|
||||||
return new ByteBlock(byteSize, equalSize); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 获取ByteBlock |
|
||||||
/// </summary> |
|
||||||
/// <param name="byteSize"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public ByteBlock GetByteBlock(int byteSize) |
|
||||||
{ |
|
||||||
return new ByteBlock(byteSize, false); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 获取内存核心。获取的核心可以不用归还。 |
|
||||||
/// 如果要调用<see cref="Recycle(byte[])"/>归还,切记不要有持久性引用。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="byteSize"></param> |
|
||||||
/// <param name="equalSize"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public byte[] GetByteCore(int byteSize, bool equalSize = false) |
|
||||||
{ |
|
||||||
BytesQueue bytesCollection; |
|
||||||
if (equalSize) |
|
||||||
{ |
|
||||||
//等长 |
|
||||||
if (bytesDictionary.TryGetValue(byteSize, out bytesCollection)) |
|
||||||
{ |
|
||||||
if (bytesCollection.TryGet(out byte[] bytes)) |
|
||||||
{ |
|
||||||
m_fullSize -= byteSize; |
|
||||||
return bytes; |
|
||||||
} |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
CheckKeyCapacity(byteSize); |
|
||||||
} |
|
||||||
return new byte[byteSize]; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
//byteSize = HitSize(byteSize); |
|
||||||
//byteSize = byteSize; |
|
||||||
//搜索已创建集合 |
|
||||||
if (bytesDictionary.TryGetValue(byteSize, out bytesCollection)) |
|
||||||
{ |
|
||||||
if (bytesCollection.TryGet(out byte[] bytes)) |
|
||||||
{ |
|
||||||
m_fullSize -= byteSize; |
|
||||||
return bytes; |
|
||||||
} |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
CheckKeyCapacity(byteSize); |
|
||||||
} |
|
||||||
return new byte[byteSize]; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 获取内存池容量 |
|
||||||
/// </summary> |
|
||||||
/// <returns></returns> |
|
||||||
public long GetPoolSize() |
|
||||||
{ |
|
||||||
long size = 0; |
|
||||||
foreach (var item in bytesDictionary.Values) |
|
||||||
{ |
|
||||||
size += item.FullSize; |
|
||||||
} |
|
||||||
return size; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 获取ValueByteBlock |
|
||||||
/// </summary> |
|
||||||
/// <param name="byteSize"></param> |
|
||||||
/// <param name="equalSize"></param> |
|
||||||
/// <returns></returns> |
|
||||||
//[IntelligentCoder.AsyncMethodIgnore] |
|
||||||
public ValueByteBlock GetValueByteBlock(int byteSize, bool equalSize) |
|
||||||
{ |
|
||||||
return new ValueByteBlock(byteSize, equalSize); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 获取ValueByteBlock |
|
||||||
/// </summary> |
|
||||||
/// <param name="byteSize"></param> |
|
||||||
/// <returns></returns> |
|
||||||
//[IntelligentCoder.AsyncMethodIgnore] |
|
||||||
public ValueByteBlock GetValueByteBlock(int byteSize) |
|
||||||
{ |
|
||||||
return new ValueByteBlock(byteSize, false); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 回收内存核心。 |
|
||||||
/// <para>注意:回收的内存,必须百分百确定该对象没有再被其他引用。不然这属于危险操作。</para> |
|
||||||
/// </summary> |
|
||||||
/// <param name="bytes"></param> |
|
||||||
public void Recycle(byte[] bytes) |
|
||||||
{ |
|
||||||
if (bytes == null || bytes.Length > MaxBlockSize || bytes.Length < MinBlockSize) |
|
||||||
{ |
|
||||||
return; |
|
||||||
} |
|
||||||
if (m_maxSize > m_fullSize) |
|
||||||
{ |
|
||||||
if (bytesDictionary.TryGetValue(bytes.Length, out BytesQueue bytesQueue)) |
|
||||||
{ |
|
||||||
if (AutoZero) |
|
||||||
{ |
|
||||||
Array.Clear(bytes, 0, bytes.Length); |
|
||||||
} |
|
||||||
m_fullSize += bytes.Length; |
|
||||||
bytesQueue.Add(bytes); |
|
||||||
} |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
long size = 0; |
|
||||||
foreach (var collection in bytesDictionary.Values) |
|
||||||
{ |
|
||||||
size += collection.FullSize; |
|
||||||
} |
|
||||||
m_fullSize = size; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 移除尺寸键 |
|
||||||
/// </summary> |
|
||||||
/// <param name="byteSize"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public bool RemoveSizeKey(int byteSize) |
|
||||||
{ |
|
||||||
if (bytesDictionary.TryRemove(byteSize, out BytesQueue queue)) |
|
||||||
{ |
|
||||||
queue.Clear(); |
|
||||||
return true; |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 设置内存块参数 |
|
||||||
/// </summary> |
|
||||||
/// <param name="minBlockSize"></param> |
|
||||||
/// <param name="maxBlockSize"></param> |
|
||||||
public void SetBlockSize(int minBlockSize, int maxBlockSize) |
|
||||||
{ |
|
||||||
this.MaxBlockSize = maxBlockSize; |
|
||||||
this.MinBlockSize = minBlockSize; |
|
||||||
bytesDictionary.Clear(); |
|
||||||
} |
|
||||||
|
|
||||||
private void CheckKeyCapacity(int byteSize) |
|
||||||
{ |
|
||||||
if (byteSize < MinBlockSize || byteSize > MaxBlockSize) |
|
||||||
{ |
|
||||||
return; |
|
||||||
} |
|
||||||
if (bytesDictionary.Count < KeyCapacity) |
|
||||||
{ |
|
||||||
bytesDictionary.TryAdd(byteSize, new BytesQueue(byteSize)); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
List<BytesQueue> bytesQueues = bytesDictionary.Values.ToList(); |
|
||||||
bytesQueues.Sort((x, y) => { return x.m_referenced > y.m_referenced ? -1 : 1; }); |
|
||||||
for (int i = (int)(bytesQueues.Count * 0.2); i < bytesQueues.Count; i++) |
|
||||||
{ |
|
||||||
if (bytesDictionary.TryRemove(bytesQueues[i].m_size, out BytesQueue queue)) |
|
||||||
{ |
|
||||||
queue.Clear(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|
||||||
private int HitSize(int num) |
|
||||||
{ |
|
||||||
if (num < MinBlockSize) |
|
||||||
{ |
|
||||||
num = MinBlockSize; |
|
||||||
} |
|
||||||
|
|
||||||
if (num <= 10240)//10k |
|
||||||
{ |
|
||||||
return 10240; |
|
||||||
} |
|
||||||
else if (num <= 65536)//64k |
|
||||||
{ |
|
||||||
return 65536; |
|
||||||
} |
|
||||||
else if (num <= 102400)//100k |
|
||||||
{ |
|
||||||
return 102400; |
|
||||||
} |
|
||||||
else if (num <= 524288) //512k |
|
||||||
{ |
|
||||||
return 524288; |
|
||||||
} |
|
||||||
else if (num <= 1048576)//1Mb |
|
||||||
{ |
|
||||||
return 1048576; |
|
||||||
} |
|
||||||
else if (num <= 1048576 * 2)//2Mb |
|
||||||
{ |
|
||||||
return 1048576 * 2; |
|
||||||
} |
|
||||||
else if (num <= 1048576 * 3)//3Mb |
|
||||||
{ |
|
||||||
return 1048576 * 3; |
|
||||||
} |
|
||||||
else if (num <= 1048576 * 4)//4Mb |
|
||||||
{ |
|
||||||
return 1048576 * 4; |
|
||||||
} |
|
||||||
else if (num <= 1048576 * 5)//5Mb |
|
||||||
{ |
|
||||||
return 1048576 * 5; |
|
||||||
} |
|
||||||
else if (num <= 1048576 * 6)//6Mb |
|
||||||
{ |
|
||||||
return 1048576 * 6; |
|
||||||
} |
|
||||||
else if (num <= 1048576 * 7)//7Mb |
|
||||||
{ |
|
||||||
return 1048576 * 7; |
|
||||||
} |
|
||||||
else if (num <= 1048576 * 8)//8Mb |
|
||||||
{ |
|
||||||
return 1048576 * 8; |
|
||||||
} |
|
||||||
else if (num <= 1048576 * 9)//9Mb |
|
||||||
{ |
|
||||||
return 1048576 * 9; |
|
||||||
} |
|
||||||
else if (num <= 10485760)//10Mb |
|
||||||
{ |
|
||||||
return 10485760; |
|
||||||
} |
|
||||||
else if (num <= 1024 * 1024 * 12)//12Mb |
|
||||||
{ |
|
||||||
return 1024 * 1024 * 12; |
|
||||||
} |
|
||||||
else if (num <= 1024 * 1024 * 15)//15Mb |
|
||||||
{ |
|
||||||
return 1024 * 1024 * 15; |
|
||||||
} |
|
||||||
else if (num <= 1024 * 1024 * 18)//18Mb |
|
||||||
{ |
|
||||||
return 1024 * 1024 * 18; |
|
||||||
} |
|
||||||
else if (num <= 1024 * 1024 * 20)//20Mb |
|
||||||
{ |
|
||||||
return 1024 * 1024 * 20; |
|
||||||
} |
|
||||||
else if (num <= 1024 * 1024 * 30)//30Mb |
|
||||||
{ |
|
||||||
return 1024 * 1024 * 30; |
|
||||||
} |
|
||||||
else if (num <= 1024 * 1024 * 40)//40Mb |
|
||||||
{ |
|
||||||
return 1024 * 1024 * 40; |
|
||||||
} |
|
||||||
else if (num <= 1024 * 1024 * 50)//50Mb |
|
||||||
{ |
|
||||||
return 1024 * 1024 * 50; |
|
||||||
} |
|
||||||
else if (num <= 1024 * 1024 * 100)//100Mb |
|
||||||
{ |
|
||||||
return 1024 * 1024 * 100; |
|
||||||
} |
|
||||||
else if (num <= 1024 * 1024 * 500)//500Mb |
|
||||||
{ |
|
||||||
return 1024 * 1024 * 500; |
|
||||||
} |
|
||||||
else if (num <= 1024 * 1024 * 1024)//1Gb |
|
||||||
{ |
|
||||||
return 1024 * 1024 * 1024; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
return num; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: d0213f3d33332ec4894a79908796fd7d |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,57 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
using System.Collections.Concurrent; |
|
||||||
using System.Diagnostics; |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 字节块集合 |
|
||||||
/// </summary> |
|
||||||
[DebuggerDisplay("Count = {bytesQueue.Count}")] |
|
||||||
internal class BytesQueue: ConcurrentStack<byte[]> |
|
||||||
{ |
|
||||||
internal int m_size; |
|
||||||
|
|
||||||
internal BytesQueue(int size) |
|
||||||
{ |
|
||||||
m_size = size; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 占用空间 |
|
||||||
/// </summary> |
|
||||||
public long FullSize => m_size * this.Count; |
|
||||||
|
|
||||||
internal long m_referenced; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 获取当前实例中的空闲的Block |
|
||||||
/// </summary> |
|
||||||
/// <returns></returns> |
|
||||||
public bool TryGet(out byte[] bytes) |
|
||||||
{ |
|
||||||
m_referenced++; |
|
||||||
return base.TryPop(out bytes); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 向当前集合添加Block |
|
||||||
/// </summary> |
|
||||||
/// <param name="bytes"></param> |
|
||||||
public void Add(byte[] bytes) |
|
||||||
{ |
|
||||||
base.Push(bytes); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 48fa07724e84cff4b9fefcdc297de2cb |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 69963a4ed1efd8b4292882fc18c40d1f |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,8 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 099facefef446734ca86eadc8cff4368 |
|
||||||
folderAsset: yes |
|
||||||
DefaultImporter: |
|
||||||
externalObjects: {} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,61 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
using System; |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 缓存实体 |
|
||||||
/// </summary> |
|
||||||
public class CacheEntry<TKey, TValue> : ICacheEntry<TKey, TValue> |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 缓存实体 |
|
||||||
/// </summary> |
|
||||||
/// <param name="key"></param> |
|
||||||
public CacheEntry(TKey key) : this(key, default) |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 缓存实体 |
|
||||||
/// </summary> |
|
||||||
public CacheEntry(TKey key, TValue value) |
|
||||||
{ |
|
||||||
UpdateTime = DateTime.Now; |
|
||||||
Duration = TimeSpan.FromSeconds(60); |
|
||||||
Key = key; |
|
||||||
Value = value; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 有效区间。如果想长期有效,请使用<see cref="TimeSpan.Zero"/> |
|
||||||
/// </summary> |
|
||||||
public TimeSpan Duration { get; set; } |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 键 |
|
||||||
/// </summary> |
|
||||||
public TKey Key { get; set; } |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 更新时间 |
|
||||||
/// </summary> |
|
||||||
public DateTime UpdateTime { get; set; } |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 值 |
|
||||||
/// </summary> |
|
||||||
public TValue Value { get; set; } |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 4f36c7b895e102b4a81b60fee294aee8 |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,58 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
using System; |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// CacheExtensions |
|
||||||
/// </summary> |
|
||||||
public static class CacheManagementExtensions |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="ICache{TKey, TValue}.AddCache(ICacheEntry{TKey, TValue})"/> |
|
||||||
/// </summary> |
|
||||||
/// <typeparam name="TKey"></typeparam> |
|
||||||
/// <typeparam name="TValue"></typeparam> |
|
||||||
/// <param name="cacheManagement"></param> |
|
||||||
/// <param name="key"></param> |
|
||||||
/// <param name="value"></param> |
|
||||||
/// <param name="duration"></param> |
|
||||||
public static void AddCache<TKey, TValue>(this ICache<TKey, TValue> cacheManagement, TKey key, TValue value, int duration = 60 * 1000) |
|
||||||
{ |
|
||||||
cacheManagement.AddCache(new CacheEntry<TKey, TValue>(key) |
|
||||||
{ |
|
||||||
Value = value, |
|
||||||
Duration = TimeSpan.FromMilliseconds(duration) |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="ICache{TKey, TValue}.SetCache(ICacheEntry{TKey, TValue})"/> |
|
||||||
/// </summary> |
|
||||||
/// <typeparam name="TKey"></typeparam> |
|
||||||
/// <typeparam name="TValue"></typeparam> |
|
||||||
/// <param name="cacheManagement"></param> |
|
||||||
/// <param name="key"></param> |
|
||||||
/// <param name="value"></param> |
|
||||||
/// <param name="duration"></param> |
|
||||||
public static void SetCache<TKey, TValue>(this ICache<TKey, TValue> cacheManagement, TKey key, TValue value, int duration = 60 * 1000) |
|
||||||
{ |
|
||||||
cacheManagement.SetCache(new CacheEntry<TKey, TValue>(key) |
|
||||||
{ |
|
||||||
Value = value, |
|
||||||
Duration = TimeSpan.FromMilliseconds(duration) |
|
||||||
}); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: d1c861758d68ec041b7cb600b09a1c12 |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,106 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
using System; |
|
||||||
using System.Threading.Tasks; |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 缓存键值 |
|
||||||
/// </summary> |
|
||||||
//[IntelligentCoder.AsyncMethodPoster(Flags = IntelligentCoder.MemberFlags.Public)] |
|
||||||
public partial interface ICache<TKey, TValue> |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 添加缓存。当缓存存在时,不会添加成功。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="entity">缓存实体</param> |
|
||||||
/// <exception cref="ArgumentNullException"></exception> |
|
||||||
bool AddCache(ICacheEntry<TKey, TValue> entity); |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 清空所有缓存 |
|
||||||
/// </summary> |
|
||||||
void ClearCache(); |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 清空所有缓存 |
|
||||||
/// </summary> |
|
||||||
/// <returns></returns> |
|
||||||
Task ClearCacheAsync(); |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 判断缓存是否存在,且在生命周期内。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="key"></param> |
|
||||||
/// <returns></returns> |
|
||||||
/// <exception cref="ArgumentNullException"></exception> |
|
||||||
bool ContainsCache(TKey key); |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 判断缓存是否存在,且在生命周期内。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="key"></param> |
|
||||||
/// <returns></returns> |
|
||||||
/// <exception cref="ArgumentNullException"></exception> |
|
||||||
Task<bool> ContainsCacheAsync(TKey key); |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 设置缓存,不管缓存存不存在,都会添加。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="entity"></param> |
|
||||||
/// <returns></returns> |
|
||||||
/// <exception cref="ArgumentNullException"></exception> |
|
||||||
bool SetCache(ICacheEntry<TKey, TValue> entity); |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 设置缓存,不管缓存存不存在,都会添加。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="entity"></param> |
|
||||||
/// <returns></returns> |
|
||||||
/// <exception cref="ArgumentNullException"></exception> |
|
||||||
Task<bool> SetCacheAsync(ICacheEntry<TKey, TValue> entity); |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 获取指定键的缓存。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="key">键</param> |
|
||||||
/// <returns></returns> |
|
||||||
/// <exception cref="ArgumentNullException"></exception> |
|
||||||
ICacheEntry<TKey, TValue> GetCache(TKey key); |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 获取指定键的缓存。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="key">键</param> |
|
||||||
/// <returns></returns> |
|
||||||
/// <exception cref="ArgumentNullException"></exception> |
|
||||||
Task<ICacheEntry<TKey, TValue>> GetCacheAsync(TKey key); |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 移除指定键的缓存。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="key">键</param> |
|
||||||
/// <returns></returns> |
|
||||||
/// <exception cref="ArgumentNullException"></exception> |
|
||||||
bool RemoveCache(TKey key); |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 移除指定键的缓存。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="key">键</param> |
|
||||||
/// <returns></returns> |
|
||||||
/// <exception cref="ArgumentNullException"></exception> |
|
||||||
Task<bool> RemoveCacheAsync(TKey key); |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 036e455d275f6c642967a23b65a1372e |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,48 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
using System; |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 缓存实体接口 |
|
||||||
/// </summary> |
|
||||||
public interface ICacheEntry |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 有效区间。如果想长期有效,请使用<see cref="TimeSpan.Zero"/> |
|
||||||
/// </summary> |
|
||||||
public TimeSpan Duration { get; } |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 更新时间 |
|
||||||
/// </summary> |
|
||||||
public DateTime UpdateTime { get; set; } |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 缓存实体接口 |
|
||||||
/// </summary> |
|
||||||
public interface ICacheEntry<out TKey, TValue> : ICacheEntry |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 键 |
|
||||||
/// </summary> |
|
||||||
public TKey Key { get; } |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 值 |
|
||||||
/// </summary> |
|
||||||
public TValue Value { get; set; } |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 186923a2693c896438dff3ee3e9a97c4 |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,319 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
using System; |
|
||||||
using System.Collections; |
|
||||||
using System.Collections.Concurrent; |
|
||||||
using System.Collections.Generic; |
|
||||||
using System.Threading; |
|
||||||
using System.Threading.Tasks; |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 一个简单的内存缓存 |
|
||||||
/// </summary> |
|
||||||
public class MemoryCache<TKey, TValue> : IEnumerable<ICacheEntry<TKey, TValue>>, ICache<TKey, TValue> |
|
||||||
{ |
|
||||||
private readonly ConcurrentDictionary<TKey, ICacheEntry<TKey, TValue>> m_pairs = new ConcurrentDictionary<TKey, ICacheEntry<TKey, TValue>>(); |
|
||||||
private readonly Timer m_timer; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 一个简单的内存缓存 |
|
||||||
/// </summary> |
|
||||||
public MemoryCache() |
|
||||||
{ |
|
||||||
m_timer = new Timer((o) => |
|
||||||
{ |
|
||||||
List<TKey> list = new List<TKey>(); |
|
||||||
foreach (var item in m_pairs) |
|
||||||
{ |
|
||||||
if (DateTime.Now - item.Value.UpdateTime > item.Value.Duration) |
|
||||||
{ |
|
||||||
list.Add(item.Key); |
|
||||||
} |
|
||||||
} |
|
||||||
foreach (var item in list) |
|
||||||
{ |
|
||||||
OnRemove(item, out _); |
|
||||||
} |
|
||||||
}, null, 0, 60 * 1000); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 当每个元素超时被移除时触发。 |
|
||||||
/// </summary> |
|
||||||
public Action<ICacheEntry<TKey, TValue>> Remove { get; set; } |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="entity"></param> |
|
||||||
public bool AddCache(ICacheEntry<TKey, TValue> entity) |
|
||||||
{ |
|
||||||
return m_pairs.TryAdd(entity.Key, entity); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="entity"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public Task<bool> AddCacheAsync(ICacheEntry<TKey, TValue> entity) |
|
||||||
{ |
|
||||||
return EasyTask.Run(() => |
|
||||||
{ |
|
||||||
return AddCache(entity); |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 清空所有缓存 |
|
||||||
/// </summary> |
|
||||||
public void ClearCache() |
|
||||||
{ |
|
||||||
m_pairs.Clear(); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc/> |
|
||||||
/// </summary> |
|
||||||
/// <returns></returns> |
|
||||||
public Task ClearCacheAsync() |
|
||||||
{ |
|
||||||
return EasyTask.Run(() => |
|
||||||
{ |
|
||||||
ClearCache(); |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="key"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public bool ContainsCache(TKey key) |
|
||||||
{ |
|
||||||
if (m_pairs.TryGetValue(key, out ICacheEntry<TKey, TValue> cache)) |
|
||||||
{ |
|
||||||
if (cache.Duration == TimeSpan.Zero) |
|
||||||
{ |
|
||||||
return true; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
if (DateTime.Now - cache.UpdateTime > cache.Duration) |
|
||||||
{ |
|
||||||
OnRemove(key, out _); |
|
||||||
return false; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="key"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public Task<bool> ContainsCacheAsync(TKey key) |
|
||||||
{ |
|
||||||
return EasyTask.Run(() => |
|
||||||
{ |
|
||||||
return ContainsCache(key); |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 获取缓存实体。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="key"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public ICacheEntry<TKey, TValue> GetCache(TKey key) |
|
||||||
{ |
|
||||||
ICacheEntry<TKey, TValue> cache; |
|
||||||
if (m_pairs.TryGetValue(key, out cache)) |
|
||||||
{ |
|
||||||
if (cache.Duration == TimeSpan.Zero) |
|
||||||
{ |
|
||||||
return cache; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
if (DateTime.Now - cache.UpdateTime > cache.Duration) |
|
||||||
{ |
|
||||||
OnRemove(key, out _); |
|
||||||
return default; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
return cache; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return default; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="key"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public Task<ICacheEntry<TKey, TValue>> GetCacheAsync(TKey key) |
|
||||||
{ |
|
||||||
return EasyTask.Run(() => |
|
||||||
{ |
|
||||||
return GetCache(key); |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc/> |
|
||||||
/// </summary> |
|
||||||
/// <returns></returns> |
|
||||||
public IEnumerator<ICacheEntry<TKey, TValue>> GetEnumerator() |
|
||||||
{ |
|
||||||
return m_pairs.Values.GetEnumerator(); |
|
||||||
} |
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator() |
|
||||||
{ |
|
||||||
return GetEnumerator(); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 移除缓存 |
|
||||||
/// </summary> |
|
||||||
/// <param name="key"></param> |
|
||||||
/// <param name="entity"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public bool RemoveCache(TKey key, out ICacheEntry<TKey, TValue> entity) |
|
||||||
{ |
|
||||||
return OnRemove(key, out entity); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 移除缓存 |
|
||||||
/// </summary> |
|
||||||
/// <param name="key"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public bool RemoveCache(TKey key) |
|
||||||
{ |
|
||||||
return OnRemove(key, out _); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="key"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public Task<bool> RemoveCacheAsync(TKey key) |
|
||||||
{ |
|
||||||
return EasyTask.Run(() => |
|
||||||
{ |
|
||||||
return RemoveCache(key); |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="entity"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public bool SetCache(ICacheEntry<TKey, TValue> entity) |
|
||||||
{ |
|
||||||
m_pairs.AddOrUpdate(entity.Key, entity, (k, v) => |
|
||||||
{ |
|
||||||
return entity; |
|
||||||
}); |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="entity"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public Task<bool> SetCacheAsync(ICacheEntry<TKey, TValue> entity) |
|
||||||
{ |
|
||||||
return EasyTask.Run(() => |
|
||||||
{ |
|
||||||
return SetCache(entity); |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 获取对应的值。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="key"></param> |
|
||||||
/// <param name="value"></param> |
|
||||||
/// <param name="update"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public bool TryGetValue(TKey key, out TValue value, bool update = false) |
|
||||||
{ |
|
||||||
if (m_pairs.TryGetValue(key, out ICacheEntry<TKey, TValue> cache)) |
|
||||||
{ |
|
||||||
if (cache.Duration == TimeSpan.Zero) |
|
||||||
{ |
|
||||||
if (update) |
|
||||||
{ |
|
||||||
cache.UpdateTime = DateTime.Now; |
|
||||||
} |
|
||||||
value = cache.Value; |
|
||||||
return true; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
if (DateTime.Now - cache.UpdateTime > cache.Duration) |
|
||||||
{ |
|
||||||
RemoveCache(key); |
|
||||||
value = default; |
|
||||||
return false; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
if (update) |
|
||||||
{ |
|
||||||
cache.UpdateTime = DateTime.Now; |
|
||||||
} |
|
||||||
value = (TValue)cache.Value; |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
value = default; |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
private bool OnRemove(TKey key, out ICacheEntry<TKey, TValue> cache) |
|
||||||
{ |
|
||||||
if (m_pairs.TryRemove(key, out cache)) |
|
||||||
{ |
|
||||||
try |
|
||||||
{ |
|
||||||
Remove?.Invoke(cache); |
|
||||||
return true; |
|
||||||
} |
|
||||||
catch |
|
||||||
{ |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return false; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 595e92394929b464db002876421876cf |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,8 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: b55d252855eec1e41848165741d9255d |
|
||||||
folderAsset: yes |
|
||||||
DefaultImporter: |
|
||||||
externalObjects: {} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,8 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: ba1a0091c88ead841b9bd84996f3716e |
|
||||||
folderAsset: yes |
|
||||||
DefaultImporter: |
|
||||||
externalObjects: {} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,125 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
using System.Collections.Concurrent; |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 安全双向字典 |
|
||||||
/// </summary> |
|
||||||
public class ConcurrentDoublyDictionary<TKey, TValue> |
|
||||||
{ |
|
||||||
private readonly ConcurrentDictionary<TKey, TValue> m_keyToValue; |
|
||||||
private readonly ConcurrentDictionary<TValue, TKey> m_valueToKey; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 构造函数 |
|
||||||
/// </summary> |
|
||||||
public ConcurrentDoublyDictionary() |
|
||||||
{ |
|
||||||
m_keyToValue = new ConcurrentDictionary<TKey, TValue>(); |
|
||||||
m_valueToKey = new ConcurrentDictionary<TValue, TKey>(); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 由键指向值得集合 |
|
||||||
/// </summary> |
|
||||||
public ConcurrentDictionary<TKey, TValue> KeyToValue => m_keyToValue; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 由值指向键的集合 |
|
||||||
/// </summary> |
|
||||||
public ConcurrentDictionary<TValue, TKey> ValueToKey => m_valueToKey; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 尝试将指定的键和值添加到字典中。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="key"></param> |
|
||||||
/// <param name="value"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public bool TryAdd(TKey key, TValue value) |
|
||||||
{ |
|
||||||
if (m_keyToValue.TryAdd(key, value)) |
|
||||||
{ |
|
||||||
if (m_valueToKey.TryAdd(value, key)) |
|
||||||
{ |
|
||||||
return true; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
m_keyToValue.TryRemove(key, out _); |
|
||||||
return false; |
|
||||||
} |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 由键尝试移除 |
|
||||||
/// </summary> |
|
||||||
/// <param name="key"></param> |
|
||||||
/// <param name="value"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public bool TryRemoveFromKey(TKey key, out TValue value) |
|
||||||
{ |
|
||||||
if (m_keyToValue.TryRemove(key, out value)) |
|
||||||
{ |
|
||||||
if (m_valueToKey.TryRemove(value, out _)) |
|
||||||
{ |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 由值尝试移除 |
|
||||||
/// </summary> |
|
||||||
/// <param name="value"></param> |
|
||||||
/// <param name="key"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public bool TryRemoveFromValue(TValue value, out TKey key) |
|
||||||
{ |
|
||||||
if (m_valueToKey.TryRemove(value, out key)) |
|
||||||
{ |
|
||||||
if (m_keyToValue.TryRemove(key, out _)) |
|
||||||
{ |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 由键获取到值 |
|
||||||
/// </summary> |
|
||||||
/// <param name="key"></param> |
|
||||||
/// <param name="value"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public bool TryGetFromKey(TKey key, out TValue value) |
|
||||||
{ |
|
||||||
return m_keyToValue.TryGetValue(key, out value); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 由值获取到键 |
|
||||||
/// </summary> |
|
||||||
/// <param name="value"></param> |
|
||||||
/// <param name="key"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public bool TryGetFromValue(TValue value, out TKey key) |
|
||||||
{ |
|
||||||
return m_valueToKey.TryGetValue(value, out key); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: e247cd100a0596046a960c4d9dabbd81 |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,680 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
using System; |
|
||||||
using System.Collections; |
|
||||||
using System.Collections.Generic; |
|
||||||
using System.Linq; |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 线程安全的List,其基本操作和List一致。 |
|
||||||
/// </summary> |
|
||||||
/// <typeparam name="T"></typeparam> |
|
||||||
public class ConcurrentList<T> : IList<T> |
|
||||||
{ |
|
||||||
private readonly List<T> m_list; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 构造函数 |
|
||||||
/// </summary> |
|
||||||
/// <param name="collection"></param> |
|
||||||
public ConcurrentList(IEnumerable<T> collection) |
|
||||||
{ |
|
||||||
m_list = new List<T>(collection); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 构造函数 |
|
||||||
/// </summary> |
|
||||||
public ConcurrentList() |
|
||||||
{ |
|
||||||
m_list = new List<T>(); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 构造函数 |
|
||||||
/// </summary> |
|
||||||
/// <param name="capacity"></param> |
|
||||||
public ConcurrentList(int capacity) |
|
||||||
{ |
|
||||||
m_list = new List<T>(capacity); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 元素数量 |
|
||||||
/// </summary> |
|
||||||
public int Count |
|
||||||
{ |
|
||||||
get |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
return m_list.Count; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 是否为只读 |
|
||||||
/// </summary> |
|
||||||
public bool IsReadOnly => false; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 获取索引元素 |
|
||||||
/// </summary> |
|
||||||
/// <param name="index"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public T this[int index] |
|
||||||
{ |
|
||||||
get |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
return m_list[index]; |
|
||||||
} |
|
||||||
} |
|
||||||
set |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
m_list[index] = value; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 添加元素 |
|
||||||
/// </summary> |
|
||||||
/// <param name="item"></param> |
|
||||||
public void Add(T item) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
m_list.Add(item); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 清空所有元素 |
|
||||||
/// </summary> |
|
||||||
public void Clear() |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
m_list.Clear(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 是否包含某个元素 |
|
||||||
/// </summary> |
|
||||||
/// <param name="item"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public bool Contains(T item) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
return m_list.Contains(item); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 复制到 |
|
||||||
/// </summary> |
|
||||||
/// <param name="array"></param> |
|
||||||
/// <param name="arrayIndex"></param> |
|
||||||
public void CopyTo(T[] array, int arrayIndex) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
m_list.CopyTo(array, arrayIndex); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 返回迭代器 |
|
||||||
/// </summary> |
|
||||||
/// <returns></returns> |
|
||||||
public IEnumerator<T> GetEnumerator() |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
return m_list.ToList().GetEnumerator(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 返回迭代器组合 |
|
||||||
/// </summary> |
|
||||||
/// <returns></returns> |
|
||||||
IEnumerator IEnumerable.GetEnumerator() |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
return GetEnumerator(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 索引 |
|
||||||
/// </summary> |
|
||||||
/// <param name="item"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public int IndexOf(T item) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
return m_list.IndexOf(item); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 插入 |
|
||||||
/// </summary> |
|
||||||
/// <param name="index"></param> |
|
||||||
/// <param name="item"></param> |
|
||||||
public void Insert(int index, T item) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
m_list.Insert(index, item); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 移除元素 |
|
||||||
/// </summary> |
|
||||||
/// <param name="item"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public bool Remove(T item) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
return m_list.Remove(item); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 按索引移除 |
|
||||||
/// </summary> |
|
||||||
/// <param name="index"></param> |
|
||||||
public void RemoveAt(int index) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
if (index < m_list.Count) |
|
||||||
{ |
|
||||||
m_list.RemoveAt(index); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 获取或设置容量 |
|
||||||
/// </summary> |
|
||||||
public int Capacity |
|
||||||
{ |
|
||||||
get |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
return m_list.Capacity; |
|
||||||
} |
|
||||||
} |
|
||||||
set |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
m_list.Capacity = value; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.AddRange(IEnumerable{T})"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="collection"></param> |
|
||||||
public void AddRange(IEnumerable<T> collection) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
m_list.AddRange(collection); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.BinarySearch(T)"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="item"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public int BinarySearch(T item) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
return m_list.BinarySearch(item); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.BinarySearch(T, IComparer{T})"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="item"></param> |
|
||||||
/// <param name="comparer"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public int BinarySearch(T item, IComparer<T> comparer) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
return m_list.BinarySearch(item, comparer); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.BinarySearch(int, int, T, IComparer{T})"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="index"></param> |
|
||||||
/// <param name="count"></param> |
|
||||||
/// <param name="item"></param> |
|
||||||
/// <param name="comparer"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public int BinarySearch(int index, int count, T item, IComparer<T> comparer) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
return m_list.BinarySearch(index, count, item, comparer); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.ConvertAll{TOutput}(Converter{T, TOutput})"/> |
|
||||||
/// </summary> |
|
||||||
/// <typeparam name="TOutput"></typeparam> |
|
||||||
/// <param name="converter"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public List<TOutput> ConvertAll<TOutput>(Converter<T, TOutput> converter) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
return m_list.ConvertAll(converter); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.Find(Predicate{T})"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="match"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public T Find(Predicate<T> match) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
return m_list.Find(match); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.FindAll(Predicate{T})"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="match"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public List<T> FindAll(Predicate<T> match) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
return m_list.FindAll(match); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.FindIndex(int, int, Predicate{T})"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="startIndex"></param> |
|
||||||
/// <param name="count"></param> |
|
||||||
/// <param name="match"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public int FindIndex(int startIndex, int count, Predicate<T> match) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
return m_list.FindIndex(startIndex, count, match); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.FindIndex(int, Predicate{T})"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="startIndex"></param> |
|
||||||
/// <param name="match"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public int FindIndex(int startIndex, Predicate<T> match) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
return m_list.FindIndex(startIndex, match); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.FindIndex(Predicate{T})"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="match"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public int FindIndex(Predicate<T> match) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
return m_list.FindIndex(match); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.FindLast(Predicate{T})"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="match"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public T FindLast(Predicate<T> match) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
return m_list.FindLast(match); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.FindLastIndex(int, int, Predicate{T})"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="startIndex"></param> |
|
||||||
/// <param name="count"></param> |
|
||||||
/// <param name="match"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public int FindLastIndex(int startIndex, int count, Predicate<T> match) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
return m_list.FindLastIndex(startIndex, count, match); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.FindLastIndex(int, Predicate{T})"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="startIndex"></param> |
|
||||||
/// <param name="match"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public int FindLastIndex(int startIndex, Predicate<T> match) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
return m_list.FindLastIndex(startIndex, match); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.FindLastIndex(Predicate{T})"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="match"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public int FindLastIndex(Predicate<T> match) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
return m_list.FindLastIndex(match); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.ForEach(Action{T})"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="action"></param> |
|
||||||
public void ForEach(Action<T> action) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
m_list.ForEach(action); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.GetRange(int, int)"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="index"></param> |
|
||||||
/// <param name="count"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public List<T> GetRange(int index, int count) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
return m_list.GetRange(index, count); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.IndexOf(T, int)"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="item"></param> |
|
||||||
/// <param name="index"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public int IndexOf(T item, int index) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
return m_list.IndexOf(item, index); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.IndexOf(T, int, int)"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="item"></param> |
|
||||||
/// <param name="index"></param> |
|
||||||
/// <param name="count"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public int IndexOf(T item, int index, int count) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
return m_list.IndexOf(item, index, count); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.InsertRange(int, IEnumerable{T})"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="index"></param> |
|
||||||
/// <param name="collection"></param> |
|
||||||
public void InsertRange(int index, IEnumerable<T> collection) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
m_list.InsertRange(index, collection); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.LastIndexOf(T)"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="item"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public int LastIndexOf(T item) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
return m_list.IndexOf(item); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.LastIndexOf(T, int)"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="item"></param> |
|
||||||
/// <param name="index"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public int LastIndexOf(T item, int index) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
return m_list.LastIndexOf(item, index); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.LastIndexOf(T, int, int)"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="item"></param> |
|
||||||
/// <param name="index"></param> |
|
||||||
/// <param name="count"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public int LastIndexOf(T item, int index, int count) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
return m_list.LastIndexOf(item, index, count); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.RemoveAll(Predicate{T})"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="match"></param> |
|
||||||
public void RemoveAll(Predicate<T> match) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
m_list.RemoveAll(match); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.RemoveRange(int, int)"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="index"></param> |
|
||||||
/// <param name="count"></param> |
|
||||||
public void RemoveRange(int index, int count) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
m_list.RemoveRange(index, count); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.Reverse()"/> |
|
||||||
/// </summary> |
|
||||||
public void Reverse() |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
m_list.Reverse(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.Reverse(int, int)"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="index"></param> |
|
||||||
/// <param name="count"></param> |
|
||||||
public void Reverse(int index, int count) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
m_list.Reverse(index, count); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.Sort()"/> |
|
||||||
/// </summary> |
|
||||||
public void Sort() |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
m_list.Sort(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.Sort(Comparison{T})"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="comparison"></param> |
|
||||||
public void Sort(Comparison<T> comparison) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
m_list.Sort(comparison); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.Sort(IComparer{T})"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="comparer"></param> |
|
||||||
public void Sort(IComparer<T> comparer) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
m_list.Sort(comparer); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.Sort(int, int, IComparer{T})"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="index"></param> |
|
||||||
/// <param name="count"></param> |
|
||||||
/// <param name="comparer"></param> |
|
||||||
public void Sort(int index, int count, IComparer<T> comparer) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
m_list.Sort(index, count, comparer); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.ToArray"/> |
|
||||||
/// </summary> |
|
||||||
/// <returns></returns> |
|
||||||
public T[] ToArray() |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
return m_list.ToArray(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.TrimExcess"/> |
|
||||||
/// </summary> |
|
||||||
public void TrimExcess() |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
m_list.TrimExcess(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc cref="List{T}.TrueForAll(Predicate{T})"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="match"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public bool TrueForAll(Predicate<T> match) |
|
||||||
{ |
|
||||||
lock (((ICollection)m_list).SyncRoot) |
|
||||||
{ |
|
||||||
return m_list.TrueForAll(match); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 0a03d08c18b538c478ee7a58941caf96 |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,194 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
using System.Collections.Concurrent; |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 三元组合 |
|
||||||
/// </summary> |
|
||||||
/// <typeparam name="TKey1"></typeparam> |
|
||||||
/// <typeparam name="TKey2"></typeparam> |
|
||||||
/// <typeparam name="TValue"></typeparam> |
|
||||||
public readonly struct Ternary<TKey1, TKey2, TValue> |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 三元组合 |
|
||||||
/// </summary> |
|
||||||
/// <param name="key1"></param> |
|
||||||
/// <param name="key2"></param> |
|
||||||
/// <param name="value"></param> |
|
||||||
public Ternary(TKey1 key1, TKey2 key2, TValue value) |
|
||||||
{ |
|
||||||
Key1 = key1; |
|
||||||
Key2 = key2; |
|
||||||
Value = value; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 首键 |
|
||||||
/// </summary> |
|
||||||
public readonly TKey1 Key1 { get; } |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 次键 |
|
||||||
/// </summary> |
|
||||||
public readonly TKey2 Key2 { get; } |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 值 |
|
||||||
/// </summary> |
|
||||||
public readonly TValue Value { get; } |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 线程安全的双键字典 |
|
||||||
/// </summary> |
|
||||||
/// <typeparam name="TKey1"></typeparam> |
|
||||||
/// <typeparam name="TKey2"></typeparam> |
|
||||||
/// <typeparam name="TValue"></typeparam> |
|
||||||
public class ConcurrentMultiDictionary<TKey1, TKey2, TValue> |
|
||||||
{ |
|
||||||
private readonly ConcurrentDictionary<TKey1, Ternary<TKey1, TKey2, TValue>> m_key1ToValue = |
|
||||||
new ConcurrentDictionary<TKey1, Ternary<TKey1, TKey2, TValue>>(); |
|
||||||
|
|
||||||
private readonly ConcurrentDictionary<TKey2, Ternary<TKey1, TKey2, TValue>> m_key2ToValue = |
|
||||||
new ConcurrentDictionary<TKey2, Ternary<TKey1, TKey2, TValue>>(); |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 元素数量。 |
|
||||||
/// </summary> |
|
||||||
public int Count { get => m_key1ToValue.Count; } |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 清空所有元素。 |
|
||||||
/// </summary> |
|
||||||
public void Clear() |
|
||||||
{ |
|
||||||
m_key1ToValue.Clear(); |
|
||||||
m_key2ToValue.Clear(); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 是否包含指定键。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="key"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public bool ContainsKey(TKey2 key) |
|
||||||
{ |
|
||||||
return m_key2ToValue.ContainsKey(key); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 是否包含指定键。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="key"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public bool ContainsKey(TKey1 key) |
|
||||||
{ |
|
||||||
return m_key1ToValue.ContainsKey(key); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 尝试添加。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="key1"></param> |
|
||||||
/// <param name="key2"></param> |
|
||||||
/// <param name="value"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public bool TryAdd(TKey1 key1, TKey2 key2, TValue value) |
|
||||||
{ |
|
||||||
var ternary = new Ternary<TKey1, TKey2, TValue>(key1, key2, value); |
|
||||||
if (m_key1ToValue.TryAdd(key1, ternary) && m_key2ToValue.TryAdd(key2, ternary)) |
|
||||||
{ |
|
||||||
return true; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
m_key1ToValue.TryRemove(key1, out _); |
|
||||||
m_key2ToValue.TryRemove(key2, out _); |
|
||||||
return false; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 由首键删除 |
|
||||||
/// </summary> |
|
||||||
/// <param name="key"></param> |
|
||||||
/// <param name="value"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public bool TryRemove(TKey1 key, out TValue value) |
|
||||||
{ |
|
||||||
if (m_key1ToValue.TryRemove(key, out var ternary)) |
|
||||||
{ |
|
||||||
m_key2ToValue.TryRemove(ternary.Key2, out _); |
|
||||||
value = ternary.Value; |
|
||||||
return true; |
|
||||||
} |
|
||||||
value = default; |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 由次键删除 |
|
||||||
/// </summary> |
|
||||||
/// <param name="key"></param> |
|
||||||
/// <param name="value"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public bool TryRemove(TKey2 key, out TValue value) |
|
||||||
{ |
|
||||||
if (m_key2ToValue.TryRemove(key, out var ternary)) |
|
||||||
{ |
|
||||||
m_key1ToValue.TryRemove(ternary.Key1, out _); |
|
||||||
value = ternary.Value; |
|
||||||
return true; |
|
||||||
} |
|
||||||
value = default; |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 由首键获取值 |
|
||||||
/// </summary> |
|
||||||
/// <param name="key"></param> |
|
||||||
/// <param name="value"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public bool TryGetValue(TKey1 key, out TValue value) |
|
||||||
{ |
|
||||||
if (m_key1ToValue.TryGetValue(key, out var ternary)) |
|
||||||
{ |
|
||||||
value = ternary.Value; |
|
||||||
return true; |
|
||||||
} |
|
||||||
value = default; |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 由次键获取值 |
|
||||||
/// </summary> |
|
||||||
/// <param name="key"></param> |
|
||||||
/// <param name="value"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public bool TryGetValue(TKey2 key, out TValue value) |
|
||||||
{ |
|
||||||
if (m_key2ToValue.TryGetValue(key, out var ternary)) |
|
||||||
{ |
|
||||||
value = ternary.Value; |
|
||||||
return true; |
|
||||||
} |
|
||||||
value = default; |
|
||||||
return false; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: d48f1d5ad25c0f24cbb44c2688506d63 |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,78 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
using System.Collections.Concurrent; |
|
||||||
using System.Threading; |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 智能安全队列 |
|
||||||
/// </summary> |
|
||||||
/// <typeparam name="T"></typeparam> |
|
||||||
public class IntelligentConcurrentQueue<T> : ConcurrentQueue<T> |
|
||||||
{ |
|
||||||
private int m_count; |
|
||||||
|
|
||||||
private readonly int m_maxCount; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 构造函数 |
|
||||||
/// </summary> |
|
||||||
/// <param name="maxCount"></param> |
|
||||||
public IntelligentConcurrentQueue(int maxCount) |
|
||||||
{ |
|
||||||
m_maxCount = maxCount; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 允许的最大长度 |
|
||||||
/// </summary> |
|
||||||
public int MaxCount => m_maxCount; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 长度 |
|
||||||
/// </summary> |
|
||||||
public new int Count => m_count; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 入队 |
|
||||||
/// </summary> |
|
||||||
/// <param name="item"></param> |
|
||||||
public new void Enqueue(T item) |
|
||||||
{ |
|
||||||
SpinWait.SpinUntil(Check); |
|
||||||
Interlocked.Increment(ref m_count); |
|
||||||
base.Enqueue(item); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 出队 |
|
||||||
/// </summary> |
|
||||||
/// <param name="result"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public new bool TryDequeue(out T result) |
|
||||||
{ |
|
||||||
if (base.TryDequeue(out result)) |
|
||||||
{ |
|
||||||
Interlocked.Decrement(ref m_count); |
|
||||||
return true; |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
private bool Check() |
|
||||||
{ |
|
||||||
return m_count < m_maxCount; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 29754dfd266b0d44fa5cbdea9915b2f2 |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,233 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
using System; |
|
||||||
using System.Collections.Concurrent; |
|
||||||
using System.Threading; |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 队列数据 |
|
||||||
/// </summary> |
|
||||||
public interface IQueueData |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 数据长度 |
|
||||||
/// </summary> |
|
||||||
int Size { get; } |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 传输字节 |
|
||||||
/// </summary> |
|
||||||
public class QueueDataBytes : IQueueData |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 构造函数 |
|
||||||
/// </summary> |
|
||||||
/// <param name="buffer"></param> |
|
||||||
/// <param name="offset"></param> |
|
||||||
/// <param name="length"></param> |
|
||||||
public QueueDataBytes(byte[] buffer, int offset, int length) |
|
||||||
{ |
|
||||||
Offset = offset; |
|
||||||
Length = length; |
|
||||||
Buffer = buffer; |
|
||||||
Size = length; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 从指定内存创建一个新对象,且内存也为新创建。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="buffer"></param> |
|
||||||
/// <param name="offset"></param> |
|
||||||
/// <param name="length"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public static QueueDataBytes CreateNew(byte[] buffer, int offset, int length) |
|
||||||
{ |
|
||||||
byte[] buf = new byte[length]; |
|
||||||
Array.Copy(buffer, offset, buf, 0, length); |
|
||||||
return new QueueDataBytes(buf); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 构造函数 |
|
||||||
/// </summary> |
|
||||||
/// <param name="buffer"></param> |
|
||||||
public QueueDataBytes(byte[] buffer) : this(buffer, 0, buffer.Length) |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 数据内存 |
|
||||||
/// </summary> |
|
||||||
public byte[] Buffer { get; } |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 长度 |
|
||||||
/// </summary> |
|
||||||
public int Length { get; } |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 偏移 |
|
||||||
/// </summary> |
|
||||||
public int Offset { get; } |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 尺寸 |
|
||||||
/// </summary> |
|
||||||
public int Size { get; } |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 智能数据安全队列 |
|
||||||
/// </summary> |
|
||||||
/// <typeparam name="T"></typeparam> |
|
||||||
public class IntelligentDataQueue<T> : ConcurrentQueue<T> where T : IQueueData |
|
||||||
{ |
|
||||||
private long m_actualSize; |
|
||||||
private bool m_free; |
|
||||||
private long m_maxSize; |
|
||||||
private Action<bool> m_onQueueChanged; |
|
||||||
private bool m_overflowWait; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 构造函数 |
|
||||||
/// </summary> |
|
||||||
/// <param name="maxSize"></param> |
|
||||||
public IntelligentDataQueue(long maxSize) |
|
||||||
{ |
|
||||||
m_free = true; |
|
||||||
m_overflowWait = true; |
|
||||||
MaxSize = maxSize; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 构造函数 |
|
||||||
/// </summary> |
|
||||||
public IntelligentDataQueue() : this(1024 * 1024 * 10) |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 实际尺寸 |
|
||||||
/// </summary> |
|
||||||
public long ActualSize => m_actualSize; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 是否有空位允许入队 |
|
||||||
/// </summary> |
|
||||||
public bool Free => m_free; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 允许的最大长度 |
|
||||||
/// </summary> |
|
||||||
public long MaxSize |
|
||||||
{ |
|
||||||
get => m_maxSize; |
|
||||||
set |
|
||||||
{ |
|
||||||
if (value < 1) |
|
||||||
{ |
|
||||||
value = 1; |
|
||||||
} |
|
||||||
m_maxSize = value; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 在队列修改时 |
|
||||||
/// </summary> |
|
||||||
public Action<bool> OnQueueChanged |
|
||||||
{ |
|
||||||
get => m_onQueueChanged; |
|
||||||
set => m_onQueueChanged = value; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 溢出等待 |
|
||||||
/// </summary> |
|
||||||
public bool OverflowWait |
|
||||||
{ |
|
||||||
get => m_overflowWait; |
|
||||||
set => m_overflowWait = value; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 超时时间。默认1000*30ms; |
|
||||||
/// </summary> |
|
||||||
public int Timeout { get; set; } = 1000 * 30; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 清空队列 |
|
||||||
/// </summary> |
|
||||||
public void Clear(Action<T> onClear) |
|
||||||
{ |
|
||||||
while (base.TryDequeue(out T t)) |
|
||||||
{ |
|
||||||
onClear?.Invoke(t); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 入队 |
|
||||||
/// </summary> |
|
||||||
/// <param name="item"></param> |
|
||||||
public new void Enqueue(T item) |
|
||||||
{ |
|
||||||
lock (this) |
|
||||||
{ |
|
||||||
bool free = m_actualSize < m_maxSize; |
|
||||||
if (m_free != free) |
|
||||||
{ |
|
||||||
m_free = free; |
|
||||||
m_onQueueChanged?.Invoke(m_free); |
|
||||||
} |
|
||||||
|
|
||||||
if (m_overflowWait) |
|
||||||
{ |
|
||||||
SpinWait.SpinUntil(Check, Timeout); |
|
||||||
} |
|
||||||
|
|
||||||
Interlocked.Add(ref m_actualSize, item.Size); |
|
||||||
base.Enqueue(item); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 出队 |
|
||||||
/// </summary> |
|
||||||
/// <param name="result"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public new bool TryDequeue(out T result) |
|
||||||
{ |
|
||||||
if (base.TryDequeue(out result)) |
|
||||||
{ |
|
||||||
Interlocked.Add(ref m_actualSize, -result.Size); |
|
||||||
bool free = m_actualSize < m_maxSize; |
|
||||||
if (m_free != free) |
|
||||||
{ |
|
||||||
m_free = free; |
|
||||||
m_onQueueChanged?.Invoke(m_free); |
|
||||||
} |
|
||||||
return true; |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
private bool Check() |
|
||||||
{ |
|
||||||
return m_actualSize < m_maxSize; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: eb105b942646d4d40a0a70436afdb4d2 |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,150 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
using System; |
|
||||||
using System.Collections.Concurrent; |
|
||||||
using System.Threading; |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 触发器队列 |
|
||||||
/// </summary> |
|
||||||
/// <typeparam name="T"></typeparam> |
|
||||||
public class TriggerQueue<T> : DisposableObject |
|
||||||
{ |
|
||||||
private readonly ReaderWriterLockSlim m_lockSlim; |
|
||||||
private readonly ConcurrentQueue<T> m_queue; |
|
||||||
private readonly Timer m_timer; |
|
||||||
private volatile bool m_sending; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 触发器队列 |
|
||||||
/// </summary> |
|
||||||
public TriggerQueue() |
|
||||||
{ |
|
||||||
m_lockSlim = new ReaderWriterLockSlim(); |
|
||||||
m_queue = new ConcurrentQueue<T>(); |
|
||||||
m_timer = new Timer(TimerRun, null, 10, 10); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 析构函数 |
|
||||||
/// </summary> |
|
||||||
~TriggerQueue() |
|
||||||
{ |
|
||||||
Dispose(false); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 出队列处理。 |
|
||||||
/// </summary> |
|
||||||
public Action<T> OnDequeue { get; set; } |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 发生错误 |
|
||||||
/// </summary> |
|
||||||
public Action<Exception> OnError { get; set; } |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 是否处于发送状态 |
|
||||||
/// </summary> |
|
||||||
public bool Sending |
|
||||||
{ |
|
||||||
get |
|
||||||
{ |
|
||||||
using (new ReadLock(m_lockSlim)) |
|
||||||
{ |
|
||||||
return m_sending; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private set |
|
||||||
{ |
|
||||||
using (new WriteLock(m_lockSlim)) |
|
||||||
{ |
|
||||||
m_sending = value; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 发送 |
|
||||||
/// </summary> |
|
||||||
public void Enqueue(T data) |
|
||||||
{ |
|
||||||
m_queue.Enqueue(data); |
|
||||||
if (SwitchToRun()) |
|
||||||
{ |
|
||||||
ThreadPool.QueueUserWorkItem(BeginTrigger); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 释放 |
|
||||||
/// </summary> |
|
||||||
/// <param name="disposing"></param> |
|
||||||
protected override void Dispose(bool disposing) |
|
||||||
{ |
|
||||||
m_timer.SafeDispose(); |
|
||||||
m_queue.Clear(); |
|
||||||
base.Dispose(disposing); |
|
||||||
} |
|
||||||
|
|
||||||
private void BeginTrigger(object o) |
|
||||||
{ |
|
||||||
while (true) |
|
||||||
{ |
|
||||||
try |
|
||||||
{ |
|
||||||
if (m_queue.TryDequeue(out T data)) |
|
||||||
{ |
|
||||||
OnDequeue?.Invoke(data); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
catch (Exception ex) |
|
||||||
{ |
|
||||||
OnError?.Invoke(ex); |
|
||||||
} |
|
||||||
} |
|
||||||
Sending = false; |
|
||||||
} |
|
||||||
|
|
||||||
private bool SwitchToRun() |
|
||||||
{ |
|
||||||
using (new ReadLock(m_lockSlim)) |
|
||||||
{ |
|
||||||
if (m_sending) |
|
||||||
{ |
|
||||||
return false; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
m_sending = true; |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private void TimerRun(object state) |
|
||||||
{ |
|
||||||
if (SwitchToRun()) |
|
||||||
{ |
|
||||||
BeginTrigger(null); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: d6c2b97fb85402b4aacc29a71b0d1784 |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,32 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
using System; |
|
||||||
using System.Collections.Specialized; |
|
||||||
using System.Diagnostics; |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// IgnoreCaseNameValueCollection |
|
||||||
/// </summary> |
|
||||||
[DebuggerTypeProxy(typeof(NameValueCollectionDebugView))] |
|
||||||
public class IgnoreCaseNameValueCollection : NameValueCollection |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// IgnoreCaseNameValueCollection |
|
||||||
/// </summary> |
|
||||||
public IgnoreCaseNameValueCollection() : base(StringComparer.OrdinalIgnoreCase) |
|
||||||
{ |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 11250ac29f2560a478feec47aac8d9dc |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,50 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
using System.Collections.Generic; |
|
||||||
using System.Collections.Specialized; |
|
||||||
using System.Diagnostics; |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// NameValueCollectionDebugView |
|
||||||
/// </summary> |
|
||||||
public class NameValueCollectionDebugView |
|
||||||
{ |
|
||||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)] |
|
||||||
private readonly NameValueCollection m_nameValue; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// NameValueCollectionDebugView |
|
||||||
/// </summary> |
|
||||||
/// <param name="nameValue"></param> |
|
||||||
public NameValueCollectionDebugView(NameValueCollection nameValue) |
|
||||||
{ |
|
||||||
m_nameValue = nameValue; |
|
||||||
} |
|
||||||
|
|
||||||
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] |
|
||||||
private Dictionary<string, string> KV |
|
||||||
{ |
|
||||||
get |
|
||||||
{ |
|
||||||
var dic = new Dictionary<string, string>(); |
|
||||||
foreach (var item in m_nameValue.AllKeys) |
|
||||||
{ |
|
||||||
dic.TryAdd(item, m_nameValue[item]); |
|
||||||
} |
|
||||||
return dic; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: be3c35ae29a02064ea1bb53301d80a47 |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,8 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 98b94db8e772cf14f8654cb30632412e |
|
||||||
folderAsset: yes |
|
||||||
DefaultImporter: |
|
||||||
externalObjects: {} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,137 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
|
|
||||||
using System; |
|
||||||
using System.Collections.Generic; |
|
||||||
using System.IO; |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 运行配置类 |
|
||||||
/// </summary> |
|
||||||
public abstract class AppConfigBase |
|
||||||
{ |
|
||||||
private readonly string m_fullPath; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 构造函数 |
|
||||||
/// </summary> |
|
||||||
/// <param name="fullPath"></param> |
|
||||||
public AppConfigBase(string fullPath) |
|
||||||
{ |
|
||||||
if (string.IsNullOrEmpty(fullPath)) |
|
||||||
{ |
|
||||||
throw new ArgumentException($"“{nameof(fullPath)}”不能为 null 或空。", nameof(fullPath)); |
|
||||||
} |
|
||||||
|
|
||||||
m_fullPath = fullPath; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 保存配置 |
|
||||||
/// </summary> |
|
||||||
/// <param name="overwrite"></param> |
|
||||||
/// <param name="msg"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public bool Save(bool overwrite, out string msg) |
|
||||||
{ |
|
||||||
if (overwrite == false && File.Exists(m_fullPath)) |
|
||||||
{ |
|
||||||
msg = null; |
|
||||||
return true; |
|
||||||
} |
|
||||||
try |
|
||||||
{ |
|
||||||
File.WriteAllText(m_fullPath, this.ToJson()); |
|
||||||
msg = null; |
|
||||||
return true; |
|
||||||
} |
|
||||||
catch (Exception ex) |
|
||||||
{ |
|
||||||
msg = ex.Message; |
|
||||||
return false; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 加载配置 |
|
||||||
/// </summary> |
|
||||||
/// <param name="msg"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public bool Load(out string msg) |
|
||||||
{ |
|
||||||
try |
|
||||||
{ |
|
||||||
if (!File.Exists(m_fullPath)) |
|
||||||
{ |
|
||||||
Save(false, out _); |
|
||||||
} |
|
||||||
var obj = File.ReadAllText(m_fullPath).FromJson(GetType()); |
|
||||||
var ps = GetType().GetProperties(); |
|
||||||
|
|
||||||
foreach (var item in ps) |
|
||||||
{ |
|
||||||
item.SetValue(this, item.GetValue(obj)); |
|
||||||
} |
|
||||||
msg = null; |
|
||||||
return true; |
|
||||||
} |
|
||||||
catch (Exception ex) |
|
||||||
{ |
|
||||||
msg = ex.Message; |
|
||||||
return false; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 获取默认配置。 |
|
||||||
/// </summary> |
|
||||||
/// <typeparam name="T"></typeparam> |
|
||||||
/// <returns></returns> |
|
||||||
public static T GetDefault<T>() where T : AppConfigBase, new() |
|
||||||
{ |
|
||||||
Type type = typeof(T); |
|
||||||
if (list.TryGetValue(type, out object value)) |
|
||||||
{ |
|
||||||
return (T)value; |
|
||||||
} |
|
||||||
T _default = ((T)Activator.CreateInstance(typeof(T))); |
|
||||||
_default.Load(out _); |
|
||||||
list.Add(type, _default); |
|
||||||
return _default; |
|
||||||
} |
|
||||||
|
|
||||||
private static readonly Dictionary<Type, object> list = new Dictionary<Type, object>(); |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 获取默认配置,每次调用该方法时,都会重新加载配置。 |
|
||||||
/// </summary> |
|
||||||
/// <typeparam name="T"></typeparam> |
|
||||||
/// <returns></returns> |
|
||||||
public static T GetNewDefault<T>() where T : AppConfigBase, new() |
|
||||||
{ |
|
||||||
T _default = ((T)Activator.CreateInstance(typeof(T))); |
|
||||||
_default.Load(out _); |
|
||||||
if (list.ContainsKey(_default.GetType())) |
|
||||||
{ |
|
||||||
list[_default.GetType()] = _default; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
list.Add(_default.GetType(), _default); |
|
||||||
} |
|
||||||
return _default; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: e9867e63be774a84a9f14ff6e552458c |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,48 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
using System; |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// DateExtensions |
|
||||||
/// </summary> |
|
||||||
public static class DateExtensions |
|
||||||
{ |
|
||||||
private static readonly DateTime m_utc_time = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 将时间转为毫秒级别的短整形 |
|
||||||
/// </summary> |
|
||||||
/// <param name="time"></param> |
|
||||||
/// <returns></returns> |
|
||||||
//[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|
||||||
public static uint ConvertTime(this in DateTime time) |
|
||||||
{ |
|
||||||
return (uint)(Convert.ToInt64(time.Subtract(m_utc_time).TotalMilliseconds) & 0xffffffff); |
|
||||||
} |
|
||||||
|
|
||||||
private static readonly DateTimeOffset m_utc1970 = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero); |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 将时间转为毫秒级别的短整形 |
|
||||||
/// </summary> |
|
||||||
/// <param name="time"></param> |
|
||||||
/// <returns></returns> |
|
||||||
//[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|
||||||
public static uint ConvertTime(this in DateTimeOffset time) |
|
||||||
{ |
|
||||||
return (uint)(Convert.ToInt64(time.Subtract(m_utc1970).TotalMilliseconds) & 0xffffffff); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 1849d956dfbc9c543a8ce47583057ece |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,51 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
using System; |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 具有释放的对象。 |
|
||||||
/// 并未实现析构函数相关。 |
|
||||||
/// </summary> |
|
||||||
public class DisposableObject : IDisposable |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 判断是否已释放。 |
|
||||||
/// </summary> |
|
||||||
private volatile bool m_disposedValue; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 标识该对象是否已被释放 |
|
||||||
/// </summary> |
|
||||||
public bool DisposedValue { get => m_disposedValue; } |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 调用释放,切换释放状态。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="disposing"></param> |
|
||||||
protected virtual void Dispose(bool disposing) |
|
||||||
{ |
|
||||||
m_disposedValue = true; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 释放资源 |
|
||||||
/// </summary> |
|
||||||
public void Dispose() |
|
||||||
{ |
|
||||||
Dispose(disposing: true); |
|
||||||
GC.SuppressFinalize(this); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 098bd4ca8caafe4438d1d84848efb2e7 |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,8 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 14e59c4a77808be46beceda3f004a031 |
|
||||||
folderAsset: yes |
|
||||||
DefaultImporter: |
|
||||||
externalObjects: {} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,31 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 大小端类型 |
|
||||||
/// </summary> |
|
||||||
public enum EndianType |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 小端模式 |
|
||||||
/// </summary> |
|
||||||
Little, |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 大端模式 |
|
||||||
/// </summary> |
|
||||||
Big |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 5b45121987fff984cba719258e7e1456 |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,56 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 结果类型 |
|
||||||
/// </summary> |
|
||||||
public enum ResultCode |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 默认 |
|
||||||
/// </summary> |
|
||||||
Default, |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 错误 |
|
||||||
/// </summary> |
|
||||||
Error, |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 异常 |
|
||||||
/// </summary> |
|
||||||
Exception, |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 成功 |
|
||||||
/// </summary> |
|
||||||
Success, |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 失败 |
|
||||||
/// </summary> |
|
||||||
Fail, |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 操作超时 |
|
||||||
/// </summary> |
|
||||||
Overtime, |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 操作取消 |
|
||||||
/// </summary> |
|
||||||
Canceled |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 19e1a3a617d052143868cbedcb3e4187 |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,112 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
using System; |
|
||||||
using System.Diagnostics; |
|
||||||
using System.Threading; |
|
||||||
using System.Threading.Tasks; |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 流量控制 |
|
||||||
/// </summary> |
|
||||||
public class FlowGate |
|
||||||
{ |
|
||||||
private readonly Stopwatch m_stopwatch; |
|
||||||
|
|
||||||
private long m_timeTick; |
|
||||||
|
|
||||||
private long m_transferLength; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 构造函数 |
|
||||||
/// </summary> |
|
||||||
public FlowGate() |
|
||||||
{ |
|
||||||
m_stopwatch = new Stopwatch(); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 最大值 |
|
||||||
/// </summary> |
|
||||||
public long Maximum { get; set; } = long.MaxValue; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 最长休眠周期。默认为5*1000ms. |
|
||||||
/// <para>当设置为5000时,假如设置的<see cref="Maximum"/>=10,而一次递增了100,则理应会休眠10s,但是会休眠5s。反之,如果设置1,则每秒周期都会清空。</para> |
|
||||||
/// </summary> |
|
||||||
public int MaximumPeriod { get; set; } = 5000; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 检测等待 |
|
||||||
/// </summary> |
|
||||||
public void AddCheckWait(int increment) |
|
||||||
{ |
|
||||||
if (GetNowTick() - m_timeTick > 0) |
|
||||||
{ |
|
||||||
//时间过了一秒 |
|
||||||
m_timeTick = FlowGate.GetNowTick(); |
|
||||||
m_transferLength = 0; |
|
||||||
m_stopwatch.Restart(); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
//在这一秒中 |
|
||||||
if (Interlocked.Add(ref m_transferLength, increment) > Maximum) |
|
||||||
{ |
|
||||||
//上传饱和 |
|
||||||
m_stopwatch.Stop(); |
|
||||||
int sleepTime = 1000 - (int)m_stopwatch.ElapsedMilliseconds <= 0 ? 0 : GetBaseNum() - (int)m_stopwatch.ElapsedMilliseconds; |
|
||||||
Thread.Sleep(sleepTime); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 检测等待 |
|
||||||
/// </summary> |
|
||||||
/// <param name="increment"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public async Task AddCheckWaitAsync(int increment) |
|
||||||
{ |
|
||||||
if (GetNowTick() - m_timeTick > 0) |
|
||||||
{ |
|
||||||
//时间过了一秒 |
|
||||||
m_timeTick = FlowGate.GetNowTick(); |
|
||||||
m_transferLength = 0; |
|
||||||
m_stopwatch.Restart(); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
//在这一秒中 |
|
||||||
if (Interlocked.Add(ref m_transferLength, increment) > Maximum) |
|
||||||
{ |
|
||||||
//上传饱和 |
|
||||||
m_stopwatch.Stop(); |
|
||||||
int sleepTime = 1000 - (int)m_stopwatch.ElapsedMilliseconds <= 0 ? 0 : GetBaseNum() - (int)m_stopwatch.ElapsedMilliseconds; |
|
||||||
await Task.Delay(sleepTime); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private static long GetNowTick() |
|
||||||
{ |
|
||||||
return DateTime.Now.Ticks / 10000000; |
|
||||||
} |
|
||||||
|
|
||||||
private int GetBaseNum() |
|
||||||
{ |
|
||||||
return Math.Min((int)((double)m_transferLength / Maximum * 1000), MaximumPeriod); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: d4689ab5bc6521f46a2d68803ca37c5e |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 80ef6598836450a4f9113b6a296273d8 |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,30 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 返回通知接口 |
|
||||||
/// </summary> |
|
||||||
public interface IResult |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 是否成功 |
|
||||||
/// </summary> |
|
||||||
ResultCode ResultCode { get; } |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 消息 |
|
||||||
/// </summary> |
|
||||||
string Message { get; } |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 48b972e26ce8863458619f3663b6d53e |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,35 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 规范写端口,提供更多扩展 |
|
||||||
/// </summary> |
|
||||||
public interface IWrite |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 写入 |
|
||||||
/// </summary> |
|
||||||
/// <param name="buffer"></param> |
|
||||||
/// <param name="offset"></param> |
|
||||||
/// <param name="length"></param> |
|
||||||
void Write(byte[] buffer, int offset, int length); |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 写入 |
|
||||||
/// </summary> |
|
||||||
/// <param name="buffer"></param> |
|
||||||
void Write(byte[] buffer); |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 0bae72788654fb64f806e8bac94906dc |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,69 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
using System; |
|
||||||
using System.Threading; |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 读取锁 |
|
||||||
/// </summary> |
|
||||||
public struct ReadLock : IDisposable |
|
||||||
{ |
|
||||||
private readonly ReaderWriterLockSlim m_locks; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 构造函数 |
|
||||||
/// </summary> |
|
||||||
/// <param name="locks"></param> |
|
||||||
public ReadLock(ReaderWriterLockSlim locks) |
|
||||||
{ |
|
||||||
m_locks = locks; |
|
||||||
m_locks.EnterReadLock(); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 释放 |
|
||||||
/// </summary> |
|
||||||
public void Dispose() |
|
||||||
{ |
|
||||||
m_locks.ExitReadLock(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 写入锁 |
|
||||||
/// </summary> |
|
||||||
public struct WriteLock : IDisposable |
|
||||||
{ |
|
||||||
private readonly ReaderWriterLockSlim m_locks; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 构造函数 |
|
||||||
/// </summary> |
|
||||||
/// <param name="locks"></param> |
|
||||||
public WriteLock(ReaderWriterLockSlim locks) |
|
||||||
{ |
|
||||||
m_locks = locks; |
|
||||||
m_locks.EnterWriteLock(); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 释放 |
|
||||||
/// </summary> |
|
||||||
public void Dispose() |
|
||||||
{ |
|
||||||
m_locks.ExitWriteLock(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 4bbeafbb054eb83459ecdf79e7201b4c |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,70 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
using System.Collections.Specialized; |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 元数据键值对。 |
|
||||||
/// </summary> |
|
||||||
[FastConverter(typeof(MetadataFastBinaryConverter))] |
|
||||||
public class Metadata : NameValueCollection, IPackage |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 元数据键值对。 |
|
||||||
/// </summary> |
|
||||||
public Metadata() |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 添加。如果键存在,将被覆盖。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="name"></param> |
|
||||||
/// <param name="value"></param> |
|
||||||
public new Metadata Add(string name, string value) |
|
||||||
{ |
|
||||||
base.Add(name, value); |
|
||||||
return this; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 打包 |
|
||||||
/// </summary> |
|
||||||
/// <param name="byteBlock"></param> |
|
||||||
public void Package(ByteBlock byteBlock) |
|
||||||
{ |
|
||||||
byteBlock.Write(Count); |
|
||||||
foreach (var item in AllKeys) |
|
||||||
{ |
|
||||||
byteBlock.Write(item); |
|
||||||
byteBlock.Write(this[item]); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 解包 |
|
||||||
/// </summary> |
|
||||||
/// <param name="byteBlock"></param> |
|
||||||
public void Unpackage(ByteBlock byteBlock) |
|
||||||
{ |
|
||||||
int count = byteBlock.ReadInt32(); |
|
||||||
for (int i = 0; i < count; i++) |
|
||||||
{ |
|
||||||
string key = byteBlock.ReadString(); |
|
||||||
string value = byteBlock.ReadString(); |
|
||||||
Add(key, value); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 0789c6c3fa93cbb4da810452431d0acc |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,43 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// MetadataFastBinaryConverter |
|
||||||
/// </summary> |
|
||||||
internal sealed class MetadataFastBinaryConverter : FastBinaryConverter<Metadata> |
|
||||||
{ |
|
||||||
protected override Metadata Read(byte[] buffer, int offset, int len) |
|
||||||
{ |
|
||||||
ByteBlock byteBlock = new ByteBlock(buffer); |
|
||||||
byteBlock.Pos = offset; |
|
||||||
Metadata metadata = new Metadata(); |
|
||||||
while (byteBlock.Pos < offset + len) |
|
||||||
{ |
|
||||||
metadata.Add(byteBlock.ReadString(), byteBlock.ReadString()); |
|
||||||
} |
|
||||||
return metadata; |
|
||||||
} |
|
||||||
|
|
||||||
protected override int Write(ByteBlock byteBlock, Metadata obj) |
|
||||||
{ |
|
||||||
int pos = byteBlock.Pos; |
|
||||||
foreach (var item in obj.AllKeys) |
|
||||||
{ |
|
||||||
byteBlock.Write(item); |
|
||||||
byteBlock.Write(obj[item]); |
|
||||||
} |
|
||||||
return byteBlock.Pos - pos; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: cb1c84fb8e237ae4eba0e332013c3d85 |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: acd6e3804c9a0494cb6e825c390087c9 |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,268 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
|
|
||||||
using System; |
|
||||||
using TouchSocket.Resources; |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 结果返回 |
|
||||||
/// </summary> |
|
||||||
public struct Result : IResult |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 成功 |
|
||||||
/// </summary> |
|
||||||
public static readonly Result Success = new Result(ResultCode.Success, "Success"); |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 初始状态 |
|
||||||
/// </summary> |
|
||||||
public static readonly Result Default = new Result(ResultCode.Default, "Default"); |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 未知失败 |
|
||||||
/// </summary> |
|
||||||
public static readonly Result UnknownFail = new Result(ResultCode.Fail, TouchSocketStatus.UnknownError.GetDescription()); |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 超时 |
|
||||||
/// </summary> |
|
||||||
public static readonly Result Overtime = new Result(ResultCode.Overtime, TouchSocketStatus.Overtime.GetDescription()); |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 取消 |
|
||||||
/// </summary> |
|
||||||
public static readonly Result Canceled = new Result(ResultCode.Canceled, TouchSocketStatus.Canceled.GetDescription()); |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 构造函数 |
|
||||||
/// </summary> |
|
||||||
/// <param name="resultCode"></param> |
|
||||||
/// <param name="message"></param> |
|
||||||
public Result(ResultCode resultCode, string message) |
|
||||||
{ |
|
||||||
ResultCode = resultCode; |
|
||||||
Message = message; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 构造函数 |
|
||||||
/// </summary> |
|
||||||
/// <param name="result"></param> |
|
||||||
public Result(IResult result) |
|
||||||
{ |
|
||||||
ResultCode = result.ResultCode; |
|
||||||
Message = result.Message; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 构造函数 |
|
||||||
/// </summary> |
|
||||||
/// <param name="exception"></param> |
|
||||||
public Result(Exception exception) |
|
||||||
{ |
|
||||||
ResultCode = ResultCode.Exception; |
|
||||||
Message = exception.Message; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 构造函数 |
|
||||||
/// </summary> |
|
||||||
/// <param name="resultCode"></param> |
|
||||||
public Result(ResultCode resultCode) |
|
||||||
{ |
|
||||||
ResultCode = resultCode; |
|
||||||
Message = resultCode.GetDescription(); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc/> |
|
||||||
/// </summary> |
|
||||||
public ResultCode ResultCode { get; private set; } |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc/> |
|
||||||
/// </summary> |
|
||||||
public string Message { get; private set; } |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 创建来自<see cref="ResultCode.Canceled"/>的<see cref="Result"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="msg"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public static Result FromCanceled(string msg) |
|
||||||
{ |
|
||||||
return new Result(ResultCode.Canceled, msg); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 创建来自<see cref="ResultCode.Error"/>的<see cref="Result"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="msg"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public static Result FromError(string msg) |
|
||||||
{ |
|
||||||
return new Result(ResultCode.Error, msg); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 创建来自<see cref="ResultCode.Exception"/>的<see cref="Result"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="msg"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public static Result FromException(string msg) |
|
||||||
{ |
|
||||||
return new Result(ResultCode.Exception, msg); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 创建来自<see cref="ResultCode.Overtime"/>的<see cref="Result"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="msg"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public static Result FromFail(string msg) |
|
||||||
{ |
|
||||||
return new Result(ResultCode.Fail, msg); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 创建来自<see cref="ResultCode.Overtime"/>的<see cref="Result"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="msg"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public static Result FromOvertime(string msg) |
|
||||||
{ |
|
||||||
return new Result(ResultCode.Overtime, msg); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 创建来自<see cref="ResultCode.Success"/>的<see cref="Result"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="msg"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public static Result FromSuccess(string msg) |
|
||||||
{ |
|
||||||
return new Result(ResultCode.Success, msg); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// ToString |
|
||||||
/// </summary> |
|
||||||
/// <returns></returns> |
|
||||||
public override string ToString() |
|
||||||
{ |
|
||||||
return $"类型:{ResultCode},信息:{Message}"; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 结果返回 |
|
||||||
/// </summary> |
|
||||||
public class ResultBase : IResult |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 构造函数 |
|
||||||
/// </summary> |
|
||||||
/// <param name="resultCode"></param> |
|
||||||
/// <param name="message"></param> |
|
||||||
public ResultBase(ResultCode resultCode, string message) |
|
||||||
{ |
|
||||||
ResultCode = resultCode; |
|
||||||
Message = message; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 构造函数 |
|
||||||
/// </summary> |
|
||||||
/// <param name="resultCode"></param> |
|
||||||
public ResultBase(ResultCode resultCode) |
|
||||||
{ |
|
||||||
ResultCode = resultCode; |
|
||||||
Message = resultCode.GetDescription(); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 构造函数 |
|
||||||
/// </summary> |
|
||||||
/// <param name="result"></param> |
|
||||||
public ResultBase(Result result) |
|
||||||
{ |
|
||||||
ResultCode = result.ResultCode; |
|
||||||
Message = result.Message; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 构造函数 |
|
||||||
/// </summary> |
|
||||||
public ResultBase() |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc/> |
|
||||||
/// </summary> |
|
||||||
public ResultCode ResultCode { get; protected set; } |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc/> |
|
||||||
/// </summary> |
|
||||||
public string Message { get; protected set; } |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// ToString |
|
||||||
/// </summary> |
|
||||||
/// <returns></returns> |
|
||||||
public override string ToString() |
|
||||||
{ |
|
||||||
return $"类型:{ResultCode},信息:{Message}"; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// ResultExtensions |
|
||||||
/// </summary> |
|
||||||
public static class ResultExtensions |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 是否成功。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="result"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public static bool IsSuccess(this IResult result) |
|
||||||
{ |
|
||||||
return result.ResultCode == ResultCode.Success; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 是否没有成功。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="result"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public static bool NotSuccess(this IResult result) |
|
||||||
{ |
|
||||||
return result.ResultCode != ResultCode.Success; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 转换为<see cref="Result"/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="result"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public static Result ToResult(this IResult result) |
|
||||||
{ |
|
||||||
return new Result(result); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 63d460dc347671f4a87ad1340148ef21 |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,129 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
using System; |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 雪花ID生成器(该代码来自网络) |
|
||||||
/// </summary> |
|
||||||
public class SnowflakeIDGenerator |
|
||||||
{ |
|
||||||
private const int SequenceBits = 10; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 一微秒内可以产生计数,如果达到该值则等到下一微妙在进行生成 |
|
||||||
/// </summary> |
|
||||||
private const long SequenceMask = -1L ^ -1L << SequenceBits; |
|
||||||
|
|
||||||
private const int TimestampLeftShift = SequenceBits + WorkerIdBits; |
|
||||||
|
|
||||||
private const int WorkerIdBits = 4; |
|
||||||
|
|
||||||
//计数器字节数,10个字节用来保存计数码 |
|
||||||
private const int WorkerIdShift = SequenceBits; |
|
||||||
|
|
||||||
private static long Sequence = 0L; |
|
||||||
|
|
||||||
//机器ID |
|
||||||
private static long WorkerId; |
|
||||||
|
|
||||||
private readonly long Twepoch = 687888001020L; |
|
||||||
|
|
||||||
private long m_lastTimestamp = -1L; |
|
||||||
|
|
||||||
static SnowflakeIDGenerator() |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
//一微秒内可以产生计数,如果达到该值则等到下一微妙在进行生成 |
|
||||||
/// <summary> |
|
||||||
/// 机器码 |
|
||||||
/// </summary> |
|
||||||
/// <param name="workerId"></param> |
|
||||||
public SnowflakeIDGenerator(long workerId) |
|
||||||
{ |
|
||||||
if (workerId > MaxWorkerId || workerId < 0) |
|
||||||
throw new Exception(string.Format("worker Id can't be greater than {0} or less than 0 ", MaxWorkerId)); |
|
||||||
SnowflakeIDGenerator.WorkerId = workerId; |
|
||||||
Twepoch = DateTime.Now.Ticks - 10000; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 最大机器ID |
|
||||||
/// </summary> |
|
||||||
public static long MaxWorkerId { get; private set; } = -1L ^ (-1L << WorkerIdBits); //最大机器ID |
|
||||||
|
|
||||||
//唯一时间,这是一个避免重复的随机量,自行设定不要大于当前时间戳 |
|
||||||
//机器码字节数。4个字节用来保存机器码(定义为Long类型会出现,最大偏移64位,所以左移64位没有意义) |
|
||||||
|
|
||||||
//机器码数据左移位数,就是后面计数器占用的位数 |
|
||||||
//时间戳左移动位数就是机器码和计数器总字节数 |
|
||||||
/// <summary> |
|
||||||
/// 获取ID |
|
||||||
/// </summary> |
|
||||||
/// <returns></returns> |
|
||||||
public long NextID() |
|
||||||
{ |
|
||||||
lock (this) |
|
||||||
{ |
|
||||||
long timestamp = timeGen(); |
|
||||||
if (m_lastTimestamp == timestamp) |
|
||||||
{ //同一微妙中生成ID |
|
||||||
Sequence = (Sequence + 1) & SequenceMask; //用&运算计算该微秒内产生的计数是否已经到达上限 |
|
||||||
if (Sequence == 0) |
|
||||||
{ |
|
||||||
//一微妙内产生的ID计数已达上限,等待下一微妙 |
|
||||||
timestamp = tillNextMillis(m_lastTimestamp); |
|
||||||
} |
|
||||||
} |
|
||||||
else |
|
||||||
{ //不同微秒生成ID |
|
||||||
Sequence = 0; //计数清0 |
|
||||||
} |
|
||||||
if (timestamp < m_lastTimestamp) |
|
||||||
{ //如果当前时间戳比上一次生成ID时时间戳还小,抛出异常,因为不能保证现在生成的ID之前没有生成过 |
|
||||||
throw new Exception(string.Format("Clock moved backwards. Refusing to generate id for {0} milliseconds", |
|
||||||
m_lastTimestamp - timestamp)); |
|
||||||
} |
|
||||||
m_lastTimestamp = timestamp; //把当前时间戳保存为最后生成ID的时间戳 |
|
||||||
long nextId = (timestamp - Twepoch << TimestampLeftShift) | WorkerId << WorkerIdShift | Sequence; |
|
||||||
return nextId; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 获取下一微秒时间戳 |
|
||||||
/// </summary> |
|
||||||
/// <param name="lastTimestamp"></param> |
|
||||||
/// <returns></returns> |
|
||||||
private long tillNextMillis(long lastTimestamp) |
|
||||||
{ |
|
||||||
long timestamp = timeGen(); |
|
||||||
while (timestamp <= lastTimestamp) |
|
||||||
{ |
|
||||||
timestamp = timeGen(); |
|
||||||
} |
|
||||||
return timestamp; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 生成当前时间戳 |
|
||||||
/// </summary> |
|
||||||
/// <returns></returns> |
|
||||||
private long timeGen() |
|
||||||
{ |
|
||||||
return Environment.TickCount; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 9e135284191009d4899cf9a10724ed4c |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,65 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
using System; |
|
||||||
using System.Collections.Concurrent; |
|
||||||
using System.ComponentModel; |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 字符串资源字典 |
|
||||||
/// </summary> |
|
||||||
public static class StringResStore |
|
||||||
{ |
|
||||||
private static readonly ConcurrentDictionary<Enum, string> m_cache = new ConcurrentDictionary<Enum, string>(); |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 获取资源字符 |
|
||||||
/// </summary> |
|
||||||
/// <param name="enum"></param> |
|
||||||
/// <param name="objs"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public static string GetDescription(this Enum @enum, params object[] objs) |
|
||||||
{ |
|
||||||
if (m_cache.TryGetValue(@enum, out string str)) |
|
||||||
{ |
|
||||||
if (string.IsNullOrEmpty(str)) |
|
||||||
{ |
|
||||||
return @enum.ToString(); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
return str.Format(objs); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if (@enum.GetAttribute<DescriptionAttribute>() is DescriptionAttribute description) |
|
||||||
{ |
|
||||||
string res = description.Description; |
|
||||||
m_cache.TryAdd(@enum, res); |
|
||||||
if (!string.IsNullOrEmpty(res)) |
|
||||||
{ |
|
||||||
if (objs.Length > 0) |
|
||||||
{ |
|
||||||
return res.Format(objs); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
return res; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return @enum.ToString(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: b106c282625b7d944a2649deeca72572 |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,56 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//using System; |
|
||||||
//using System.Collections.Concurrent; |
|
||||||
//using System.Collections.Generic; |
|
||||||
//using System.Linq; |
|
||||||
//using System.Text; |
|
||||||
//using System.Threading.Tasks; |
|
||||||
|
|
||||||
//namespace TouchSocket.Core |
|
||||||
//{ |
|
||||||
// /// <summary> |
|
||||||
// /// 异常助手 |
|
||||||
// /// </summary> |
|
||||||
// public static class ThrowHelper |
|
||||||
// { |
|
||||||
// private static readonly ConcurrentDictionary<Enum, Func<string, Exception, Exception>> m_pairs = |
|
||||||
// new ConcurrentDictionary<Enum, Func<string, Exception, Exception>>(); |
|
||||||
|
|
||||||
// /// <summary> |
|
||||||
// /// 添加抛出规则。 |
|
||||||
// /// </summary> |
|
||||||
// /// <param name="enum"></param> |
|
||||||
// /// <param name="func"></param> |
|
||||||
// public static void Add(Enum @enum,Func<string,Exception,Exception> func) |
|
||||||
// { |
|
||||||
// if (@enum is null) |
|
||||||
// { |
|
||||||
// throw new ArgumentNullException(nameof(@enum)); |
|
||||||
// } |
|
||||||
|
|
||||||
// if (func is null) |
|
||||||
// { |
|
||||||
// throw new ArgumentNullException(nameof(func)); |
|
||||||
// } |
|
||||||
|
|
||||||
// m_pairs.TryRemove(@enum,out _); |
|
||||||
// m_pairs.TryAdd(@enum,func); |
|
||||||
// } |
|
||||||
|
|
||||||
// public static Exception Throw(Enum @enum,string msg,Exception exception) |
|
||||||
// { |
|
||||||
// } |
|
||||||
|
|
||||||
// } |
|
||||||
//} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 1c0339e4483e66449b1fc78aff0e39e6 |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,498 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
using System; |
|
||||||
using System.Runtime.CompilerServices; |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 将基数据类型转换为指定端的一个字节数组, |
|
||||||
/// 或将一个字节数组转换为指定端基数据类型。 |
|
||||||
/// </summary> |
|
||||||
public class TouchSocketBitConverter |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 以大端 |
|
||||||
/// </summary> |
|
||||||
public static TouchSocketBitConverter BigEndian; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 以小端 |
|
||||||
/// </summary> |
|
||||||
public static TouchSocketBitConverter LittleEndian; |
|
||||||
|
|
||||||
static TouchSocketBitConverter() |
|
||||||
{ |
|
||||||
BigEndian = new TouchSocketBitConverter(EndianType.Big); |
|
||||||
LittleEndian = new TouchSocketBitConverter(EndianType.Little); |
|
||||||
DefaultEndianType = EndianType.Little; |
|
||||||
} |
|
||||||
|
|
||||||
private static TouchSocketBitConverter m_default; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 以默认小端,可通过<see cref="TouchSocketBitConverter.DefaultEndianType"/>重新指定默认端。 |
|
||||||
/// </summary> |
|
||||||
public static TouchSocketBitConverter Default => m_default; |
|
||||||
|
|
||||||
private static EndianType m_defaultEndianType; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 默认大小端切换。 |
|
||||||
/// </summary> |
|
||||||
public static EndianType DefaultEndianType |
|
||||||
{ |
|
||||||
get => m_defaultEndianType; |
|
||||||
set |
|
||||||
{ |
|
||||||
m_defaultEndianType = value; |
|
||||||
switch (value) |
|
||||||
{ |
|
||||||
case EndianType.Little: |
|
||||||
m_default = LittleEndian; |
|
||||||
break; |
|
||||||
|
|
||||||
case EndianType.Big: |
|
||||||
m_default = BigEndian; |
|
||||||
break; |
|
||||||
|
|
||||||
default: |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private readonly EndianType endianType; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 构造函数 |
|
||||||
/// </summary> |
|
||||||
/// <param name="endianType"></param> |
|
||||||
public TouchSocketBitConverter(EndianType endianType) |
|
||||||
{ |
|
||||||
this.endianType = endianType; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 指定大小端。 |
|
||||||
/// </summary> |
|
||||||
public EndianType EndianType => endianType; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 判断当前系统是否为设置的大小端 |
|
||||||
/// </summary> |
|
||||||
/// <returns></returns> |
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|
||||||
public bool IsSameOfSet() |
|
||||||
{ |
|
||||||
return !(BitConverter.IsLittleEndian ^ (endianType == EndianType.Little)); |
|
||||||
//return true; |
|
||||||
} |
|
||||||
|
|
||||||
#region ushort |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 转换为指定端2字节 |
|
||||||
/// </summary> |
|
||||||
/// <param name="value"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public byte[] GetBytes(ushort value) |
|
||||||
{ |
|
||||||
byte[] bytes = BitConverter.GetBytes(value); |
|
||||||
if (!IsSameOfSet()) |
|
||||||
{ |
|
||||||
Array.Reverse(bytes); |
|
||||||
} |
|
||||||
return bytes; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 转换为指定端模式的2字节转换为UInt16数据。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="buffer"></param> |
|
||||||
/// <param name="offset"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public ushort ToUInt16(byte[] buffer, int offset) |
|
||||||
{ |
|
||||||
if (IsSameOfSet()) |
|
||||||
{ |
|
||||||
return BitConverter.ToUInt16(buffer, offset); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
byte[] bytes = new byte[2]; |
|
||||||
Array.Copy(buffer, offset, bytes, 0, 2); |
|
||||||
Array.Reverse(bytes); |
|
||||||
return BitConverter.ToUInt16(bytes, 0); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
#endregion ushort |
|
||||||
|
|
||||||
#region ulong |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 转换为指定端8字节 |
|
||||||
/// </summary> |
|
||||||
/// <param name="value"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public byte[] GetBytes(ulong value) |
|
||||||
{ |
|
||||||
byte[] bytes = BitConverter.GetBytes(value); |
|
||||||
if (!IsSameOfSet()) |
|
||||||
{ |
|
||||||
Array.Reverse(bytes); |
|
||||||
} |
|
||||||
|
|
||||||
return bytes; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 转换为指定端模式的Ulong数据。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="buffer"></param> |
|
||||||
/// <param name="offset"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public ulong ToUInt64(byte[] buffer, int offset) |
|
||||||
{ |
|
||||||
if (IsSameOfSet()) |
|
||||||
{ |
|
||||||
return BitConverter.ToUInt64(buffer, offset); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
byte[] bytes = new byte[8]; |
|
||||||
Array.Copy(buffer, offset, bytes, 0, 8); |
|
||||||
Array.Reverse(bytes); |
|
||||||
return BitConverter.ToUInt64(bytes,0); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
#endregion ulong |
|
||||||
|
|
||||||
#region bool |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 转换为指定端1字节 |
|
||||||
/// </summary> |
|
||||||
/// <param name="value"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public byte[] GetBytes(bool value) |
|
||||||
{ |
|
||||||
return BitConverter.GetBytes(value); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 转换为指定端模式的bool数据。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="buffer"></param> |
|
||||||
/// <param name="offset"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public bool ToBoolean(byte[] buffer, int offset) |
|
||||||
{ |
|
||||||
return BitConverter.ToBoolean(buffer, offset); |
|
||||||
} |
|
||||||
|
|
||||||
#endregion bool |
|
||||||
|
|
||||||
#region char |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 转换为指定端2字节 |
|
||||||
/// </summary> |
|
||||||
/// <param name="value"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public byte[] GetBytes(char value) |
|
||||||
{ |
|
||||||
byte[] bytes = BitConverter.GetBytes(value); |
|
||||||
if (!IsSameOfSet()) |
|
||||||
{ |
|
||||||
Array.Reverse(bytes); |
|
||||||
} |
|
||||||
|
|
||||||
return bytes; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 转换为指定端模式的Char数据。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="buffer"></param> |
|
||||||
/// <param name="offset"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public char ToChar(byte[] buffer, int offset) |
|
||||||
{ |
|
||||||
if (IsSameOfSet()) |
|
||||||
{ |
|
||||||
return BitConverter.ToChar(buffer, offset); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
byte[] bytes = new byte[2]; |
|
||||||
Array.Copy(buffer, offset, bytes, 0, bytes.Length); |
|
||||||
Array.Reverse(bytes); |
|
||||||
return BitConverter.ToChar(bytes, 0); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
#endregion char |
|
||||||
|
|
||||||
#region short |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 转换为指定端2字节 |
|
||||||
/// </summary> |
|
||||||
/// <param name="value"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public byte[] GetBytes(short value) |
|
||||||
{ |
|
||||||
byte[] bytes = BitConverter.GetBytes(value); |
|
||||||
if (!IsSameOfSet()) |
|
||||||
{ |
|
||||||
Array.Reverse(bytes); |
|
||||||
} |
|
||||||
|
|
||||||
return bytes; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 转换为指定端模式的Short数据。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="buffer"></param> |
|
||||||
/// <param name="offset"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public short ToInt16(byte[] buffer, int offset) |
|
||||||
{ |
|
||||||
if (IsSameOfSet()) |
|
||||||
{ |
|
||||||
return BitConverter.ToInt16(buffer, offset); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
byte[] bytes = new byte[2]; |
|
||||||
Array.Copy(buffer, offset, bytes, 0, bytes.Length); |
|
||||||
Array.Reverse(bytes); |
|
||||||
return BitConverter.ToInt16(bytes, 0); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
#endregion short |
|
||||||
|
|
||||||
#region int |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 转换为指定端4字节 |
|
||||||
/// </summary> |
|
||||||
/// <param name="value"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public byte[] GetBytes(int value) |
|
||||||
{ |
|
||||||
byte[] bytes = BitConverter.GetBytes(value); |
|
||||||
if (!IsSameOfSet()) |
|
||||||
{ |
|
||||||
Array.Reverse(bytes); |
|
||||||
} |
|
||||||
|
|
||||||
return bytes; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 转换为指定端模式的int数据。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="buffer"></param> |
|
||||||
/// <param name="offset"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public int ToInt32(byte[] buffer, int offset) |
|
||||||
{ |
|
||||||
if (IsSameOfSet()) |
|
||||||
{ |
|
||||||
return BitConverter.ToInt32(buffer, offset); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
byte[] bytes = new byte[4]; |
|
||||||
Array.Copy(buffer, offset, bytes, 0, bytes.Length); |
|
||||||
Array.Reverse(bytes); |
|
||||||
return BitConverter.ToInt32(bytes, 0); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
#endregion int |
|
||||||
|
|
||||||
#region long |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 转换为指定端8字节 |
|
||||||
/// </summary> |
|
||||||
/// <param name="value"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public byte[] GetBytes(long value) |
|
||||||
{ |
|
||||||
byte[] bytes = BitConverter.GetBytes(value); |
|
||||||
if (!IsSameOfSet()) |
|
||||||
{ |
|
||||||
Array.Reverse(bytes); |
|
||||||
} |
|
||||||
|
|
||||||
return bytes; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 转换为指定端模式的long数据。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="buffer"></param> |
|
||||||
/// <param name="offset"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public long ToInt64(byte[] buffer, int offset) |
|
||||||
{ |
|
||||||
if (IsSameOfSet()) |
|
||||||
{ |
|
||||||
return BitConverter.ToInt64(buffer, offset); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
byte[] bytes = new byte[8]; |
|
||||||
Array.Copy(buffer, offset, bytes, 0, bytes.Length); |
|
||||||
Array.Reverse(bytes); |
|
||||||
return BitConverter.ToInt64(bytes, 0); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
#endregion long |
|
||||||
|
|
||||||
#region uint |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 转换为指定端4字节 |
|
||||||
/// </summary> |
|
||||||
/// <param name="value"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public byte[] GetBytes(uint value) |
|
||||||
{ |
|
||||||
byte[] bytes = BitConverter.GetBytes(value); |
|
||||||
if (!IsSameOfSet()) |
|
||||||
{ |
|
||||||
Array.Reverse(bytes); |
|
||||||
} |
|
||||||
|
|
||||||
return bytes; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 转换为指定端模式的Uint数据。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="buffer"></param> |
|
||||||
/// <param name="offset"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public uint ToUInt32(byte[] buffer, int offset) |
|
||||||
{ |
|
||||||
if (IsSameOfSet()) |
|
||||||
{ |
|
||||||
return BitConverter.ToUInt32(buffer, offset); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
byte[] bytes = new byte[4]; |
|
||||||
Array.Copy(buffer, offset, bytes, 0, bytes.Length); |
|
||||||
Array.Reverse(bytes); |
|
||||||
return BitConverter.ToUInt32(bytes, 0); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
#endregion uint |
|
||||||
|
|
||||||
#region float |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 转换为指定端4字节 |
|
||||||
/// </summary> |
|
||||||
/// <param name="value"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public byte[] GetBytes(float value) |
|
||||||
{ |
|
||||||
byte[] bytes = BitConverter.GetBytes(value); |
|
||||||
if (!IsSameOfSet()) |
|
||||||
{ |
|
||||||
Array.Reverse(bytes); |
|
||||||
} |
|
||||||
|
|
||||||
return bytes; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 转换为指定端模式的float数据。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="buffer"></param> |
|
||||||
/// <param name="offset"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public float ToSingle(byte[] buffer, int offset) |
|
||||||
{ |
|
||||||
if (IsSameOfSet()) |
|
||||||
{ |
|
||||||
return BitConverter.ToSingle(buffer, offset); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
byte[] bytes = new byte[4]; |
|
||||||
Array.Copy(buffer, offset, bytes, 0, bytes.Length); |
|
||||||
Array.Reverse(bytes); |
|
||||||
return BitConverter.ToSingle(bytes, 0); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
#endregion float |
|
||||||
|
|
||||||
#region long |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 转换为指定端8字节 |
|
||||||
/// </summary> |
|
||||||
/// <param name="value"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public byte[] GetBytes(double value) |
|
||||||
{ |
|
||||||
byte[] bytes = BitConverter.GetBytes(value); |
|
||||||
if (!IsSameOfSet()) |
|
||||||
{ |
|
||||||
Array.Reverse(bytes); |
|
||||||
} |
|
||||||
|
|
||||||
return bytes; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 转换为指定端模式的double数据。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="buffer"></param> |
|
||||||
/// <param name="offset"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public double ToDouble(byte[] buffer, int offset) |
|
||||||
{ |
|
||||||
if (IsSameOfSet()) |
|
||||||
{ |
|
||||||
return BitConverter.ToDouble(buffer, offset); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
byte[] bytes = new byte[8]; |
|
||||||
Array.Copy(buffer, offset, bytes, 0, bytes.Length); |
|
||||||
Array.Reverse(bytes); |
|
||||||
return BitConverter.ToDouble(bytes, 0); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
#endregion long |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: bea05cf50d8689d479961b412b0a5137 |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,50 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
using System; |
|
||||||
using System.Collections; |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 常量 |
|
||||||
/// </summary> |
|
||||||
public class TouchSocketCoreUtility |
|
||||||
{ |
|
||||||
#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释 |
|
||||||
public static readonly Type stringType = typeof(string); |
|
||||||
public static readonly Type byteType = typeof(byte); |
|
||||||
public static readonly Type sbyteType = typeof(sbyte); |
|
||||||
public static readonly Type shortType = typeof(short); |
|
||||||
public static readonly Type objType = typeof(object); |
|
||||||
public static readonly Type ushortType = typeof(ushort); |
|
||||||
public static readonly Type intType = typeof(int); |
|
||||||
public static readonly Type uintType = typeof(uint); |
|
||||||
public static readonly Type boolType = typeof(bool); |
|
||||||
public static readonly Type charType = typeof(char); |
|
||||||
public static readonly Type longType = typeof(long); |
|
||||||
public static readonly Type ulongType = typeof(ulong); |
|
||||||
public static readonly Type floatType = typeof(float); |
|
||||||
public static readonly Type doubleType = typeof(double); |
|
||||||
public static readonly Type decimalType = typeof(decimal); |
|
||||||
public static readonly Type dateTimeType = typeof(DateTime); |
|
||||||
public static readonly Type bytesType = typeof(byte[]); |
|
||||||
public static readonly Type dicType = typeof(IDictionary); |
|
||||||
public static readonly Type iEnumerableType = typeof(IEnumerable); |
|
||||||
public static readonly Type arrayType = typeof(Array); |
|
||||||
public static readonly Type listType = typeof(IList); |
|
||||||
public static readonly Type nullableType = typeof(Nullable<>); |
|
||||||
|
|
||||||
public static readonly byte[] ZeroBytes = new byte[0]; |
|
||||||
#pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释 |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: ecf953fa94ffec741931af4e78e51aa9 |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,8 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: a90b867395e0ee04bba859a9d1e1bf21 |
|
||||||
folderAsset: yes |
|
||||||
DefaultImporter: |
|
||||||
externalObjects: {} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,114 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 配置文件基类 |
|
||||||
/// </summary> |
|
||||||
public class TouchSocketConfig : DependencyObject |
|
||||||
{ |
|
||||||
//private bool built; |
|
||||||
private IContainer m_container; |
|
||||||
|
|
||||||
private IPluginsManager m_pluginsManager; |
|
||||||
|
|
||||||
//ConcurrentQueue<Tuple<Delegate, object[]>> actions = new ConcurrentQueue<Tuple<Delegate, object[]>>(); |
|
||||||
|
|
||||||
///// <summary> |
|
||||||
///// 添加构建委托,该委托会在<see cref="Build"/>时调用。 |
|
||||||
///// </summary> |
|
||||||
///// <param name="action"></param> |
|
||||||
///// <param name="ps"></param> |
|
||||||
//public void AddBuildAction(Delegate action,params object[] ps) |
|
||||||
//{ |
|
||||||
// actions.Enqueue(Tuple.Create(action,ps)) ; |
|
||||||
//} |
|
||||||
|
|
||||||
///// <summary> |
|
||||||
///// 构建配置 |
|
||||||
///// </summary> |
|
||||||
//public void Build() |
|
||||||
//{ |
|
||||||
// if (!built) |
|
||||||
// { |
|
||||||
// built = true; |
|
||||||
// while (actions.TryDequeue(out var action)) |
|
||||||
// { |
|
||||||
// action.Item1.DynamicInvoke(action.Item2); |
|
||||||
// } |
|
||||||
// } |
|
||||||
//} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 构造函数 |
|
||||||
/// </summary> |
|
||||||
public TouchSocketConfig() |
|
||||||
{ |
|
||||||
SetContainer(new Container()); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// IOC容器。 |
|
||||||
/// </summary> |
|
||||||
public IContainer Container => m_container; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 使用插件 |
|
||||||
/// </summary> |
|
||||||
public bool IsUsePlugin { get; set; } |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 插件管理器 |
|
||||||
/// </summary> |
|
||||||
public IPluginsManager PluginsManager => m_pluginsManager; |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 设置注入容器。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="value"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public TouchSocketConfig SetContainer(IContainer value) |
|
||||||
{ |
|
||||||
m_container = value; |
|
||||||
if (!value.IsRegistered(typeof(ILog))) |
|
||||||
{ |
|
||||||
m_container.RegisterSingleton<ILog, LoggerGroup>(); |
|
||||||
} |
|
||||||
SetPluginsManager(new PluginsManager(m_container)); |
|
||||||
return this; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 设置PluginsManager |
|
||||||
/// </summary> |
|
||||||
/// <param name="value"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public TouchSocketConfig SetPluginsManager(IPluginsManager value) |
|
||||||
{ |
|
||||||
m_pluginsManager = value; |
|
||||||
m_container.RegisterSingleton<IPluginsManager>(value); |
|
||||||
return this; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 启用插件 |
|
||||||
/// </summary> |
|
||||||
/// <returns></returns> |
|
||||||
public TouchSocketConfig UsePlugin() |
|
||||||
{ |
|
||||||
IsUsePlugin = true; |
|
||||||
return this; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 9d745c7bb315fa44ea5f11136c4a0993 |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,54 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
using System; |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// TouchSocketCoreConfigExtension |
|
||||||
/// </summary> |
|
||||||
public static class TouchSocketCoreConfigExtension |
|
||||||
{ |
|
||||||
#region 插件 |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 配置插件。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="config"></param> |
|
||||||
/// <param name="action"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public static TouchSocketConfig ConfigurePlugins(this TouchSocketConfig config, Action<IPluginsManager> action) |
|
||||||
{ |
|
||||||
action?.Invoke(config.PluginsManager); |
|
||||||
return config; |
|
||||||
} |
|
||||||
|
|
||||||
#endregion 插件 |
|
||||||
|
|
||||||
#region 容器 |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// 配置容器注入。 |
|
||||||
/// </summary> |
|
||||||
/// <param name="config"></param> |
|
||||||
/// <param name="action"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public static TouchSocketConfig ConfigureContainer(this TouchSocketConfig config, Action<IContainer> action) |
|
||||||
{ |
|
||||||
action?.Invoke(config.Container); |
|
||||||
return config; |
|
||||||
} |
|
||||||
|
|
||||||
#endregion 容器 |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 62feb3bbf0c32a84688d1e05cd4fb36b |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,8 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 4c5e981e4651cd34faddbe786967c0df |
|
||||||
folderAsset: yes |
|
||||||
DefaultImporter: |
|
||||||
externalObjects: {} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
@ -1,83 +0,0 @@ |
|||||||
//------------------------------------------------------------------------------ |
|
||||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
||||||
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
||||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
||||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
||||||
// Github源代码仓库:https://github.com/RRQM |
|
||||||
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
||||||
// 交流QQ群:234762506 |
|
||||||
// 感谢您的下载和使用 |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
//------------------------------------------------------------------------------ |
|
||||||
|
|
||||||
using System; |
|
||||||
|
|
||||||
namespace TouchSocket.Core |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 字节类转换器 |
|
||||||
/// </summary> |
|
||||||
public class BytesConverter : TouchSocketConverter<byte[]> |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 字节类转换器 |
|
||||||
/// </summary> |
|
||||||
public BytesConverter() |
|
||||||
{ |
|
||||||
Add(new JsonBytesToClassConverter()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// Json字节转到对应类 |
|
||||||
/// </summary> |
|
||||||
public class JsonBytesToClassConverter : IConverter<byte[]> |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc/> |
|
||||||
/// </summary> |
|
||||||
public int Order { get; set; } |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="source"></param> |
|
||||||
/// <param name="targetType"></param> |
|
||||||
/// <param name="target"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public bool TryConvertFrom(byte[] source, Type targetType, out object target) |
|
||||||
{ |
|
||||||
try |
|
||||||
{ |
|
||||||
target = SerializeConvert.JsonDeserializeFromBytes(source, targetType); |
|
||||||
return true; |
|
||||||
} |
|
||||||
catch |
|
||||||
{ |
|
||||||
target = default; |
|
||||||
return false; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary> |
|
||||||
/// <inheritdoc/> |
|
||||||
/// </summary> |
|
||||||
/// <param name="target"></param> |
|
||||||
/// <param name="source"></param> |
|
||||||
/// <returns></returns> |
|
||||||
public bool TryConvertTo(object target, out byte[] source) |
|
||||||
{ |
|
||||||
try |
|
||||||
{ |
|
||||||
source = SerializeConvert.JsonSerializeToBytes(target); |
|
||||||
return true; |
|
||||||
} |
|
||||||
catch (Exception) |
|
||||||
{ |
|
||||||
source = null; |
|
||||||
return false; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 16262141474d2ba43a5af513cc358d38 |
|
||||||
MonoImporter: |
|
||||||
externalObjects: {} |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue