提交 118808ee 编写于 作者: 若汝棋茗

0.7.0基本编译过

上级 edf721fb
......@@ -21,7 +21,7 @@ namespace TouchSocket.Core.ByteManager
/// <summary>
/// 字节块流
/// </summary>
[System.Diagnostics.DebuggerDisplay("Len={Len}")]
[System.Diagnostics.DebuggerDisplay("Len={Len},Pos={Pos},Capacity={Capacity}")]
public sealed class ByteBlock : Stream, IByteBlock
{
internal long m_length;
......@@ -46,7 +46,7 @@ namespace TouchSocket.Core.ByteManager
}
/// <summary>
/// 构造函数
/// 实例化一个已知内存的对象。且该内存不会被回收。
/// </summary>
/// <param name="bytes"></param>
public ByteBlock(byte[] bytes)
......
......@@ -24,23 +24,18 @@ namespace TouchSocket.Core.ByteManager
public static class BytePool
{
private static readonly ConcurrentDictionary<long, BytesQueue> bytesDictionary = new ConcurrentDictionary<long, BytesQueue>();
private static bool m_autoZero;
private static readonly Timer m_timer;
private static long m_fullSize;
private static int m_keyCapacity;
private static int m_maxBlockSize;
private static long m_maxSize;
private static int m_minBlockSize;
private static readonly Timer m_timer;
static BytePool()
{
m_timer = new Timer((o) =>
{
BytePool.Clear();
Clear();
}, null, 1000 * 60 * 60, 1000 * 60 * 60);
m_keyCapacity = 100;
m_autoZero = false;
KeyCapacity = 100;
AutoZero = false;
m_maxSize = 1024 * 1024 * 512;
SetBlockSize(1024, 1024 * 1024 * 20);
AddSizeKey(10240);
......@@ -49,25 +44,17 @@ namespace TouchSocket.Core.ByteManager
/// <summary>
/// 回收内存时,自动归零
/// </summary>
public static bool AutoZero
{
get => m_autoZero;
set => m_autoZero = value;
}
public static bool AutoZero { get; set; }
/// <summary>
/// 键容量
/// </summary>
public static int KeyCapacity
{
get => m_keyCapacity;
set => m_keyCapacity = value;
}
public static int KeyCapacity { get; set; }
/// <summary>
/// 单个块最大值
/// </summary>
public static int MaxBlockSize => m_maxBlockSize;
public static int MaxBlockSize { get; private set; }
/// <summary>
/// 允许的内存池最大值
......@@ -88,7 +75,7 @@ namespace TouchSocket.Core.ByteManager
/// <summary>
/// 单个块最小值
/// </summary>
public static int MinBlockSize => m_minBlockSize;
public static int MinBlockSize { get; private set; }
/// <summary>
/// 添加尺寸键
......@@ -151,54 +138,13 @@ namespace TouchSocket.Core.ByteManager
/// <returns></returns>
public static ByteBlock GetByteBlock(int byteSize)
{
if (byteSize < m_minBlockSize)
if (byteSize < MinBlockSize)
{
byteSize = m_minBlockSize;
byteSize = MinBlockSize;
}
return GetByteBlock(byteSize, false);
}
/// <summary>
/// 获取内存池容量
/// </summary>
/// <returns></returns>
public static long GetPoolSize()
{
long size = 0;
foreach (var item in bytesDictionary.Values)
{
size += item.FullSize;
}
return size;
}
/// <summary>
/// 移除尺寸键
/// </summary>
/// <param name="byteSize"></param>
/// <returns></returns>
public static 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 static void SetBlockSize(int minBlockSize, int maxBlockSize)
{
BytePool.m_maxBlockSize = maxBlockSize;
BytePool.m_minBlockSize = minBlockSize;
bytesDictionary.Clear();
}
/// <summary>
/// 获取内存核心。获取的核心可以不用归还。
/// 如果要调用<see cref="Recycle(byte[])"/>归还,切记不要有持久性引用。
......@@ -246,13 +192,27 @@ namespace TouchSocket.Core.ByteManager
}
}
/// <summary>
/// 获取内存池容量
/// </summary>
/// <returns></returns>
public static long GetPoolSize()
{
long size = 0;
foreach (var item in bytesDictionary.Values)
{
size += item.FullSize;
}
return size;
}
/// <summary>
/// 回收内存核心
/// </summary>
/// <param name="bytes"></param>
public static void Recycle(byte[] bytes)
{
if (bytes == null)
if (bytes == null || bytes.Length > MaxBlockSize || bytes.Length < MinBlockSize)
{
return;
}
......@@ -260,7 +220,7 @@ namespace TouchSocket.Core.ByteManager
{
if (bytesDictionary.TryGetValue(bytes.Length, out BytesQueue bytesQueue))
{
if (m_autoZero)
if (AutoZero)
{
Array.Clear(bytes, 0, bytes.Length);
}
......@@ -279,13 +239,40 @@ namespace TouchSocket.Core.ByteManager
}
}
/// <summary>
/// 移除尺寸键
/// </summary>
/// <param name="byteSize"></param>
/// <returns></returns>
public static 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 static void SetBlockSize(int minBlockSize, int maxBlockSize)
{
BytePool.MaxBlockSize = maxBlockSize;
BytePool.MinBlockSize = minBlockSize;
bytesDictionary.Clear();
}
private static void CheckKeyCapacity(int byteSize)
{
if (byteSize < m_minBlockSize || byteSize > m_maxBlockSize)
if (byteSize < MinBlockSize || byteSize > MaxBlockSize)
{
return;
}
if (bytesDictionary.Count < m_keyCapacity)
if (bytesDictionary.Count < KeyCapacity)
{
bytesDictionary.TryAdd(byteSize, new BytesQueue(byteSize));
}
......
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TouchSocket.Core.Collections
{
/// <summary>
/// IgnoreCaseNameValueCollection
/// </summary>
[DebuggerTypeProxy(typeof(NameValueCollectionDebugView))]
public class IgnoreCaseNameValueCollection:NameValueCollection
{
/// <summary>
/// IgnoreCaseNameValueCollection
/// </summary>
public IgnoreCaseNameValueCollection():base(StringComparer.OrdinalIgnoreCase)
{
}
}
}
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TouchSocket.Core.Extensions;
namespace TouchSocket.Core.Collections
{
/// <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)
{
this.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;
}
}
}
}
......@@ -19,7 +19,7 @@ namespace TouchSocket.Core
public enum ResultCode
{
/// <summary>
/// 未执行的
/// 默认
/// </summary>
Default,
......@@ -28,11 +28,21 @@ namespace TouchSocket.Core
/// </summary>
Error,
/// <summary>
/// 异常
/// </summary>
Exception,
/// <summary>
/// 成功
/// </summary>
Success,
/// <summary>
/// 失败
/// </summary>
Fail,
/// <summary>
/// 操作超时
/// </summary>
......
......@@ -34,7 +34,7 @@ namespace TouchSocket.Core
/// </summary>
public FlowGate()
{
this.m_stopwatch = new Stopwatch();
this.m_stopwatch = new Stopwatch();
}
/// <summary>
......
......@@ -10,30 +10,34 @@
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using TouchSocket.Core.Serialization;
namespace TouchSocket.Core
{
/// <summary>
/// 可传输的元数据
/// 元数据键值对。
/// </summary>
public class Metadata : Dictionary<string, string>
[FastConverter(typeof(MetadataFastBinaryConverter))]
public class Metadata : NameValueCollection
{
/// <summary>
/// 添加或更新
/// 元数据键值对。
/// </summary>
/// <param name="key"></param>
public Metadata()
{
}
/// <summary>
/// 添加。如果键存在,将被覆盖。
/// </summary>
/// <param name="name"></param>
/// <param name="value"></param>
public Metadata AddOrUpdate(string key, string value)
public new Metadata Add(string name, string value)
{
if (this.ContainsKey(key))
{
this[key] = value;
}
else
{
this.Add(key, value);
}
base.Add(name, value);
return this;
}
}
......
using TouchSocket.Core;
using TouchSocket.Core.ByteManager;
using TouchSocket.Core.Serialization;
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;
}
}
}
......@@ -22,7 +22,7 @@ namespace TouchSocket.Core.Dependency
/// </summary>
public class Container : IContainer
{
private readonly ConcurrentDictionary<string, DependencyDescriptor> registrations = new ConcurrentDictionary<string, DependencyDescriptor>();
private readonly ConcurrentDictionary<string, DependencyDescriptor> m_registrations = new ConcurrentDictionary<string, DependencyDescriptor>();
/// <summary>
/// 初始化一个IOC容器
......@@ -40,7 +40,7 @@ namespace TouchSocket.Core.Dependency
/// <returns></returns>
public bool IsRegistered(Type fromType, string key = "")
{
return this.registrations.ContainsKey($"{fromType.FullName}{key}");
return this.m_registrations.ContainsKey($"{fromType.FullName}{key}");
}
/// <summary>
......@@ -51,7 +51,7 @@ namespace TouchSocket.Core.Dependency
public void Register(DependencyDescriptor descriptor, string key = "")
{
string k = $"{descriptor.FromType.FullName}{key}";
this.registrations.AddOrUpdate(k, descriptor, (k, v) => { return descriptor; });
this.m_registrations.AddOrUpdate(k, descriptor, (k, v) => { return descriptor; });
}
/// <summary>
......@@ -63,7 +63,7 @@ namespace TouchSocket.Core.Dependency
/// <returns></returns>
public object Resolve(Type fromType, object[] ps = null, string key = "")
{
if (fromType == typeof(IScopedContainer))
if (fromType == typeof(IContainerProvider))
{
return this.GetScopedContainer();
}
......@@ -73,8 +73,12 @@ namespace TouchSocket.Core.Dependency
{
Type type = fromType.GetGenericTypeDefinition();
k = $"{type.FullName}{key}";
if (this.registrations.TryGetValue(k, out descriptor))
if (this.m_registrations.TryGetValue(k, out descriptor))
{
if (descriptor.ImplementationFactory!=null)
{
return descriptor.ImplementationFactory.Invoke(this);
}
if (descriptor.Lifetime == Lifetime.Singleton)
{
if (descriptor.ToInstance != null)
......@@ -108,8 +112,12 @@ namespace TouchSocket.Core.Dependency
}
}
k = $"{fromType.FullName}{key}";
if (this.registrations.TryGetValue(k, out descriptor))
if (this.m_registrations.TryGetValue(k, out descriptor))
{
if (descriptor.ImplementationFactory != null)
{
return descriptor.ImplementationFactory.Invoke(this);
}
if (descriptor.Lifetime == Lifetime.Singleton)
{
if (descriptor.ToInstance != null)
......@@ -156,7 +164,7 @@ namespace TouchSocket.Core.Dependency
public void Unregister(DependencyDescriptor descriptor, string key = "")
{
string k = $"{descriptor.FromType.FullName}{key}";
this.registrations.TryRemove(k, out _);
this.m_registrations.TryRemove(k, out _);
}
/// <summary>
......@@ -327,21 +335,21 @@ namespace TouchSocket.Core.Dependency
return instance;
}
private IScopedContainer GetScopedContainer()
private IContainerProvider GetScopedContainer()
{
Container container = new Container();
foreach (var item in this.registrations)
foreach (var item in this.m_registrations)
{
if (item.Value.Lifetime == Lifetime.Scoped)
{
container.registrations.AddOrUpdate(item.Key, new DependencyDescriptor(item.Value.FromType, item.Value.ToType, Lifetime.Singleton), (k, v) => { return v; });
container.m_registrations.AddOrUpdate(item.Key, new DependencyDescriptor(item.Value.FromType, item.Value.ToType, Lifetime.Singleton), (k, v) => { return v; });
}
else
{
container.registrations.AddOrUpdate(item.Key, item.Value, (k, v) => { return v; });
container.m_registrations.AddOrUpdate(item.Key, item.Value, (k, v) => { return v; });
}
}
return new ScopedContainer(container);
return new ContainerProvider(container);
}
}
}
\ No newline at end of file
......@@ -35,6 +35,23 @@ namespace TouchSocket.Core.Dependency
return container;
}
/// <summary>
/// 注册单例
/// </summary>
/// <param name="container"></param>
/// <param name="instance"></param>
/// <returns></returns>
public static IContainer RegisterSingleton(this IContainer container, object instance)
{
if (instance is null)
{
throw new ArgumentNullException(nameof(instance));
}
RegisterSingleton(container, instance.GetType(), instance);
return container;
}
/// <summary>
/// 注册单例
/// </summary>
......@@ -155,6 +172,19 @@ namespace TouchSocket.Core.Dependency
return container;
}
/// <summary>
/// 注册临时映射
/// </summary>
/// <typeparam name="TFrom"></typeparam>
/// <param name="container"></param>
/// <returns></returns>
public static IContainer RegisterTransient<TFrom>(this IContainer container)
where TFrom : class
{
RegisterTransient(container, typeof(TFrom), typeof(TFrom));
return container;
}
/// <summary>
/// 注册临时映射
/// </summary>
......@@ -204,6 +234,19 @@ namespace TouchSocket.Core.Dependency
return container;
}
/// <summary>
/// 注册区域映射
/// </summary>
/// <typeparam name="TFrom"></typeparam>
/// <param name="container"></param>
/// <returns></returns>
public static IContainer RegisterScoped<TFrom>(this IContainer container)
where TFrom : class
{
RegisterScoped(container, typeof(TFrom), typeof(TFrom));
return container;
}
/// <summary>
/// 注册区域映射
/// </summary>
......@@ -244,7 +287,7 @@ namespace TouchSocket.Core.Dependency
/// <param name="ps"></param>
/// <param name="key"></param>
/// <returns></returns>
public static T Resolve<T>(this IScopedContainer container, object[] ps, string key = "")
public static T Resolve<T>(this IContainerProvider container, object[] ps, string key = "")
{
return (T)container.Resolve(typeof(T), ps, key);
}
......@@ -255,7 +298,7 @@ namespace TouchSocket.Core.Dependency
/// <typeparam name="T"></typeparam>
/// <param name="container"></param>
/// <returns></returns>
public static T Resolve<T>(this IScopedContainer container)
public static T Resolve<T>(this IContainerProvider container)
{
return Resolve<T>(container, null);
}
......@@ -267,7 +310,7 @@ namespace TouchSocket.Core.Dependency
/// <param name="container"></param>
/// <param name="key"></param>
/// <returns></returns>
public static T Resolve<T>(this IScopedContainer container, string key)
public static T Resolve<T>(this IContainerProvider container, string key)
{
return Resolve<T>(container, null, key);
}
......
......@@ -14,11 +14,11 @@ using System;
namespace TouchSocket.Core.Dependency
{
internal class ScopedContainer : IScopedContainer
internal class ContainerProvider : IContainerProvider
{
private readonly Container m_container;
public ScopedContainer(Container container)
public ContainerProvider(Container container)
{
this.m_container = container;
}
......
......@@ -54,6 +54,11 @@ namespace TouchSocket.Core.Dependency
this.FromType = fromType;
}
/// <summary>
/// 实例化工厂委托
/// </summary>
public Func<IContainer,object> ImplementationFactory { get; set; }
/// <summary>
/// 实例类型
/// </summary>
......
......@@ -16,7 +16,7 @@ namespace TouchSocket.Core.Dependency
/// <summary>
/// 注入容器接口
/// </summary>
public interface IContainer : IScopedContainer
public interface IContainer : IContainerProvider
{
/// <summary>
/// 添加类型描述符。
......
......@@ -17,7 +17,7 @@ namespace TouchSocket.Core.Dependency
/// <summary>
/// 具有区域效应的容器。
/// </summary>
public interface IScopedContainer
public interface IContainerProvider
{
/// <summary>
/// 创建目标类型的对应实例。
......
......@@ -24,7 +24,7 @@ namespace TouchSocket.Core.Dependency
Singleton,
/// <summary>
/// 以<see cref="IScopedContainer"/>接口为区域实例单例。
/// 以<see cref="IContainerProvider"/>接口为区域实例单例。
/// </summary>
Scoped,
......
......@@ -46,6 +46,18 @@ namespace TouchSocket.Core.IO
/// </summary>
public int ReadTimeout { get; set; }
/// <summary>
/// 阻塞读取,但不会移动游标。
/// </summary>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="count"></param>
/// <returns></returns>
public virtual int PeekRead(byte[] buffer, int offset, int count)
{
return this.PrivateRead(true, buffer, offset, count);
}
/// <summary>
/// 阻塞读取。
/// </summary>
......@@ -54,6 +66,11 @@ namespace TouchSocket.Core.IO
/// <param name="count"></param>
/// <returns></returns>
public virtual int Read(byte[] buffer, int offset, int count)
{
return this.PrivateRead(false,buffer,offset,count);
}
private int PrivateRead(bool peek,byte[] buffer, int offset, int count)
{
if (!this.CanRead)
{
......@@ -66,8 +83,11 @@ namespace TouchSocket.Core.IO
{
//按count读取
Array.Copy(this.m_buffer, this.m_offset, buffer, offset, count);
this.m_surLength -= count;
this.m_offset += count;
if (!peek)
{
this.m_surLength -= count;
this.m_offset += count;
}
r = count;
}
else
......@@ -75,7 +95,11 @@ namespace TouchSocket.Core.IO
//会读完本次
Array.Copy(this.m_buffer, this.m_offset, buffer, offset, this.m_surLength);
r = this.m_surLength;
this.Reset();
if (!peek)
{
this.Reset();
}
}
}
else
......@@ -92,8 +116,11 @@ namespace TouchSocket.Core.IO
{
//按count读取
Array.Copy(this.m_buffer, this.m_offset, buffer, offset, count);
this.m_surLength -= count;
this.m_offset += count;
if (!peek)
{
this.m_surLength -= count;
this.m_offset += count;
}
r = count;
}
else
......@@ -101,7 +128,11 @@ namespace TouchSocket.Core.IO
//会读完本次
Array.Copy(this.m_buffer, this.m_offset, buffer, offset, this.m_surLength);
r = this.m_surLength;
this.Reset();
if (!peek)
{
this.Reset();
}
}
}
else
......
......@@ -47,6 +47,30 @@ namespace TouchSocket.Core.IO
}
}
/// <summary>
/// 获取不重复文件夹名称
/// </summary>
/// <param name="dirName"></param>
/// <returns></returns>
public static string GetDuplicateDirectoryName(string dirName)
{
if (!Directory.Exists(dirName))
{
return dirName;
}
int index = 0;
while (true)
{
index++;
string newPath = Path.Combine(Path.GetDirectoryName(dirName), $"{Path.GetFileNameWithoutExtension(dirName)}({index})");
if (!System.IO.Directory.Exists(newPath))
{
return newPath;
}
}
}
/// <summary>
/// 转化为文件大小的字符串,类似10B,10Kb,10Mb,10Gb。
/// </summary>
......
......@@ -67,6 +67,7 @@ namespace TouchSocket.Core.Log
if (exception != null)
{
Console.Write(" | ");
Console.Write($"【异常消息】:{exception.Message}");
Console.Write($"【堆栈】:{(exception == null ? "未知" : exception.StackTrace)}");
}
Console.WriteLine();
......
......@@ -70,6 +70,7 @@ namespace TouchSocket.Core.Log
if (exception != null)
{
stringBuilder.Append(" | ");
stringBuilder.Append($"【异常消息】:{exception.Message}");
stringBuilder.Append($"【堆栈】:{(exception == null ? "未知" : exception.StackTrace)}");
}
stringBuilder.AppendLine();
......
......@@ -65,6 +65,7 @@ namespace TouchSocket.Core.Log
if (exception != null)
{
stringBuilder.Append(" | ");
stringBuilder.Append($"【异常消息】:{exception.Message}");
stringBuilder.Append($"【堆栈】:{(exception == null ? "未知" : exception.StackTrace)}");
}
stringBuilder.AppendLine();
......
......@@ -118,6 +118,7 @@ namespace TouchSocket.Core.Log
loggerGroup.Log<TLog>(logType, source, message, exception);
}
}
/// <summary>
/// 指定在<see cref="LoggerGroup"/>中的特定日志类型中输出详细日志
/// </summary>
......
......@@ -11,6 +11,8 @@
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using TouchSocket.Core.Collections.Concurrent;
namespace TouchSocket.Core.Log
{
......@@ -19,7 +21,7 @@ namespace TouchSocket.Core.Log
/// </summary>
public class LoggerGroup : LoggerBase
{
private readonly ILog[] m_logs;
private readonly List<ILog> m_logs;
/// <summary>
......@@ -28,13 +30,37 @@ namespace TouchSocket.Core.Log
/// <param name="logs"></param>
public LoggerGroup(params ILog[] logs)
{
this.m_logs = logs ?? throw new ArgumentNullException(nameof(logs));
if (logs is null)
{
throw new ArgumentNullException(nameof(logs));
}
this.m_logs = new List<ILog>();
this.m_logs.AddRange(logs);
}
/// <summary>
/// 组内的日志记录器
/// </summary>
public ILog[] Logs => this.m_logs;
public ILog[] Logs => this.m_logs.ToArray();
/// <summary>
/// 添加日志组件
/// </summary>
/// <param name="logger"></param>
public void AddLogger(ILog logger)
{
this.m_logs.Add(logger);
}
/// <summary>
/// 移除日志
/// </summary>
/// <param name="logger"></param>
public void RemoveLogger(ILog logger)
{
this.m_logs.Remove(logger);
}
/// <summary>
/// 指定输出<see cref="LoggerGroup"/>中的特定类型的日志
......@@ -45,7 +71,7 @@ namespace TouchSocket.Core.Log
/// <param name="exception"></param>
public void Log<TLog>(LogType logType, object source, string message, Exception exception) where TLog : ILog
{
for (int i = 0; i < this.Logs.Length; i++)
for (int i = 0; i < this.m_logs.Count; i++)
{
ILog log = this.Logs[i];
if (log.GetType() == typeof(TLog))
......@@ -64,7 +90,7 @@ namespace TouchSocket.Core.Log
/// <param name="exception"></param>
protected override void WriteLog(LogType logType, object source, string message, Exception exception)
{
for (int i = 0; i < this.Logs.Length; i++)
for (int i = 0; i < this.m_logs.Count; i++)
{
this.Logs[i].Log(logType, source, message, exception);
}
......
......@@ -120,6 +120,8 @@ namespace TouchSocket.Core.Plugins
else if (x.Plugin.Order < y.Plugin.Order) return 1;
else return -1;
});
this.Container.RegisterSingleton(plugin);
}
/// <summary>
......
......@@ -10,7 +10,9 @@
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using System;
using System.Threading;
using System.Threading.Tasks;
namespace TouchSocket.Core.Run
{
......@@ -20,10 +22,8 @@ namespace TouchSocket.Core.Run
/// <typeparam name="T"></typeparam>
public class WaitData<T> : DisposableObject
{
private WaitDataStatus m_status;
private readonly AutoResetEvent m_waitHandle;
private WaitDataStatus m_status;
private T m_waitResult;
/// <summary>
......@@ -34,6 +34,11 @@ namespace TouchSocket.Core.Run
this.m_waitHandle = new AutoResetEvent(false);
}
/// <summary>
/// 延迟模式
/// </summary>
public bool DelayModel { get; set; }
/// <summary>
/// 状态
/// </summary>
......@@ -50,19 +55,10 @@ namespace TouchSocket.Core.Run
public void Cancel()
{
this.m_status = WaitDataStatus.Canceled;
this.m_waitHandle.Set();
}
/// <summary>
/// 释放
/// </summary>
/// <param name="disposing"></param>
protected override void Dispose(bool disposing)
{
this.m_status = WaitDataStatus.Disposed;
this.m_waitResult = default;
this.m_waitHandle.Dispose();
base.Dispose(disposing);
if (!this.DelayModel)
{
this.m_waitHandle.Set();
}
}
/// <summary>
......@@ -73,7 +69,11 @@ namespace TouchSocket.Core.Run
{
this.m_status = WaitDataStatus.Default;
this.m_waitResult = default;
return this.m_waitHandle.Reset();
if (!this.DelayModel)
{
return this.m_waitHandle.Reset();
}
return true;
}
/// <summary>
......@@ -82,7 +82,11 @@ namespace TouchSocket.Core.Run
public bool Set()
{
this.m_status = WaitDataStatus.SetRunning;
return this.m_waitHandle.Set();
if (!this.DelayModel)
{
return this.m_waitHandle.Set();
}
return true;
}
/// <summary>
......@@ -93,7 +97,11 @@ namespace TouchSocket.Core.Run
{
this.m_waitResult = waitResult;
this.m_status = WaitDataStatus.SetRunning;
return this.m_waitHandle.Set();
if (!this.DelayModel)
{
return this.m_waitHandle.Set();
}
return true;
}
/// <summary>
......@@ -122,11 +130,39 @@ namespace TouchSocket.Core.Run
/// <param name="millisecond"></param>
public WaitDataStatus Wait(int millisecond)
{
if (!this.m_waitHandle.WaitOne(millisecond))
if (this.DelayModel)
{
for (int i = 0; i < millisecond / 10.0; i++)
{
if (this.m_status != WaitDataStatus.Default)
{
return this.m_status;
}
Task.Delay(10).GetAwaiter().GetResult();
}
this.m_status = WaitDataStatus.Overtime;
return this.m_status;
}
else
{
if (!this.m_waitHandle.WaitOne(millisecond))
{
this.m_status = WaitDataStatus.Overtime;
}
return this.m_status;
}
return this.m_status;
}
/// <summary>
/// 释放
/// </summary>
/// <param name="disposing"></param>
protected override void Dispose(bool disposing)
{
this.m_status = WaitDataStatus.Disposed;
this.m_waitResult = default;
this.m_waitHandle.SafeDispose();
base.Dispose(disposing);
}
}
}
\ No newline at end of file
......@@ -82,6 +82,11 @@ namespace TouchSocket.Core.Run
}
}
/// <summary>
/// 延迟模式
/// </summary>
public bool DelayModel { get; set; } = false;
/// <summary>
/// 获取一个可等待对象
/// </summary>
......@@ -102,6 +107,7 @@ namespace TouchSocket.Core.Run
}
waitData = new WaitData<T>();
waitData.DelayModel = this.DelayModel;
if (autoSign)
{
result.Sign = this.m_idGenerator.NextID();
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TouchSocket.Core.Serialization
{
/// <summary>
/// FastConverterAttribute
/// </summary>
public class FastConverterAttribute:Attribute
{
/// <summary>
/// FastConverterAttribute
/// </summary>
/// <param name="type"></param>
public FastConverterAttribute(Type type)
{
this.Type = type;
}
/// <summary>
/// 转化器类型。
/// </summary>
public Type Type { get;private set; }
}
}
......@@ -27,27 +27,108 @@ namespace TouchSocket.Core.Serialization
/// </summary>
public class FastBinaryFormatter
{
private static readonly ConcurrentDictionary<string, SerializObject> m_instanceCache = new ConcurrentDictionary<string, SerializObject>();
private static readonly ConcurrentDictionary<Type, IFastBinaryConverter> m_typeToConverter = new ConcurrentDictionary<Type, IFastBinaryConverter>();
/// <summary>
/// 添加转换器。
/// </summary>
public static void AddFastBinaryConverter<TType, TConverter>() where TConverter : IFastBinaryConverter, new()
{
AddFastBinaryConverter(typeof(TType), (IFastBinaryConverter)Activator.CreateInstance(typeof(TConverter)));
}
/// <summary>
/// 添加转换器。
/// </summary>
/// <typeparam name="TType"></typeparam>
/// <param name="converter"></param>
public static void AddFastBinaryConverter<TType>(IFastBinaryConverter converter)
{
AddFastBinaryConverter(typeof(TType), converter);
}
/// <summary>
/// 添加转换器。
/// </summary>
/// <param name="type"></param>
/// <param name="converter"></param>
public static void AddFastBinaryConverter(Type type, IFastBinaryConverter converter)
{
m_typeToConverter.AddOrUpdate(type, converter, (k, v) => converter);
}
#region Serialize
/// <summary>
/// 序列化对象
/// </summary>
/// <param name="stream">流</param>
/// <param name="byteBlock">流</param>
/// <param name="graph">对象</param>
public void Serialize(ByteBlock stream, object graph)
public void Serialize(ByteBlock byteBlock, object graph)
{
stream.Position = 1;
this.SerializeObject(stream, graph);
stream.Buffer[0] = 1;
stream.SetLength(stream.Position);
byteBlock.Position = 1;
this.SerializeObject(byteBlock, graph);
byteBlock.Buffer[0] = 1;
byteBlock.SetLength(byteBlock.Position);
}
private int SerializeObject(ByteBlock stream, object graph)
private int SerializeClass(ByteBlock stream, object obj, Type type)
{
int len = 0;
if (obj != null)
{
PropertyInfo[] propertyInfos = GetProperties(type);
foreach (PropertyInfo property in propertyInfos)
{
if (property.GetCustomAttribute<FastNonSerializedAttribute>() != null)
{
continue;
}
byte[] propertyBytes = Encoding.UTF8.GetBytes(property.Name);
if (propertyBytes.Length > byte.MaxValue)
{
throw new Exception($"属性名:{property.Name}超长");
}
byte lenBytes = (byte)propertyBytes.Length;
stream.Write(lenBytes);
stream.Write(propertyBytes, 0, propertyBytes.Length);
len += propertyBytes.Length + 1;
len += this.SerializeObject(stream, property.GetValue(obj, null));
}
}
return len;
}
private int SerializeIEnumerable(ByteBlock stream, IEnumerable param)
{
int len = 0;
if (param != null)
{
long oldPosition = stream.Position;
stream.Position += 4;
len += 4;
uint paramLen = 0;
foreach (object item in param)
{
paramLen++;
len += this.SerializeObject(stream, item);
}
long newPosition = stream.Position;
stream.Position = oldPosition;
stream.Write(TouchSocketBitConverter.Default.GetBytes(paramLen));
stream.Position = newPosition;
}
return len;
}
private int SerializeObject(ByteBlock byteBlock, object graph)
{
int len = 0;
byte[] data = null;
long startPosition = stream.Position;
long startPosition = byteBlock.Position;
long endPosition;
if (graph != null)
{
......@@ -134,16 +215,28 @@ namespace TouchSocket.Core.Serialization
}
else
{
stream.Position += 4;
byteBlock.Position += 4;
Type type = graph.GetType();
if (typeof(IEnumerable).IsAssignableFrom(type))
if (m_typeToConverter.TryGetValue(type, out IFastBinaryConverter converter))
{
len += this.SerializeIEnumerable(stream, (IEnumerable)graph);
len += converter.Write(byteBlock, graph);
}
else
{
len += this.SerializeClass(stream, graph, type);
if (type.GetCustomAttribute<FastConverterAttribute>() is FastConverterAttribute attribute)
{
IFastBinaryConverter binaryConverter = (IFastBinaryConverter)Activator.CreateInstance(attribute.Type);
AddFastBinaryConverter(type, binaryConverter);
len += binaryConverter.Write(byteBlock, graph);
}
else if (typeof(IEnumerable).IsAssignableFrom(type))
{
len += this.SerializeIEnumerable(byteBlock, (IEnumerable)graph);
}
else
{
len += this.SerializeClass(byteBlock, graph, type);
}
}
}
......@@ -154,7 +247,7 @@ namespace TouchSocket.Core.Serialization
}
else
{
endPosition = stream.Position;
endPosition = byteBlock.Position;
}
}
else
......@@ -163,67 +256,17 @@ namespace TouchSocket.Core.Serialization
}
byte[] lenBuffer = TouchSocketBitConverter.Default.GetBytes(len);
stream.Position = startPosition;
stream.Write(lenBuffer, 0, lenBuffer.Length);
byteBlock.Position = startPosition;
byteBlock.Write(lenBuffer, 0, lenBuffer.Length);
if (data != null)
{
stream.Write(data, 0, data.Length);
byteBlock.Write(data, 0, data.Length);
}
stream.Position = endPosition;
byteBlock.Position = endPosition;
return len + 4;
}
private int SerializeClass(ByteBlock stream, object obj, Type type)
{
int len = 0;
if (obj != null)
{
PropertyInfo[] propertyInfos = GetProperties(type);
foreach (PropertyInfo property in propertyInfos)
{
if (property.GetCustomAttribute<FastNonSerializedAttribute>() != null)
{
continue;
}
byte[] propertyBytes = Encoding.UTF8.GetBytes(property.Name);
if (propertyBytes.Length > byte.MaxValue)
{
throw new Exception($"属性名:{property.Name}超长");
}
byte lenBytes = (byte)propertyBytes.Length;
stream.Write(lenBytes);
stream.Write(propertyBytes, 0, propertyBytes.Length);
len += propertyBytes.Length + 1;
len += this.SerializeObject(stream, property.GetValue(obj, null));
}
}
return len;
}
private int SerializeIEnumerable(ByteBlock stream, IEnumerable param)
{
int len = 0;
if (param != null)
{
long oldPosition = stream.Position;
stream.Position += 4;
len += 4;
uint paramLen = 0;
foreach (object item in param)
{
paramLen++;
len += this.SerializeObject(stream, item);
}
long newPosition = stream.Position;
stream.Position = oldPosition;
stream.Write(TouchSocketBitConverter.Default.GetBytes(paramLen));
stream.Position = newPosition;
}
return len;
}
#endregion Serialize
#region Deserialize
......@@ -346,7 +389,24 @@ namespace TouchSocket.Core.Serialization
}
else if (type.IsClass || type.IsStruct())
{
obj = this.DeserializeClass(type, datas, offset, len);
if (m_typeToConverter.TryGetValue(type, out IFastBinaryConverter converter))
{
obj = converter.Read(datas, offset, len);
}
else
{
if (type.GetCustomAttribute<FastConverterAttribute>() is FastConverterAttribute attribute)
{
IFastBinaryConverter binaryConverter = (IFastBinaryConverter)Activator.CreateInstance(attribute.Type);
AddFastBinaryConverter(type, binaryConverter);
obj = binaryConverter.Read(datas, offset, len);
}
else
{
obj = this.DeserializeClass(type, datas, offset, len);
}
}
}
else
{
......@@ -477,22 +537,15 @@ namespace TouchSocket.Core.Serialization
#endregion Deserialize
private static PropertyInfo[] GetProperties(Type type)
{
return type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
}
private static readonly ConcurrentDictionary<string, SerializObject> InstanceCache = new ConcurrentDictionary<string, SerializObject>();
private static SerializObject GetOrAddInstance(Type type)
{
if (InstanceCache.TryGetValue(type.FullName, out SerializObject instance))
if (m_instanceCache.TryGetValue(type.FullName, out SerializObject instance))
{
return instance;
}
if (type.IsArray)//数组
{
SerializObject typeInfo = InstanceCache.GetOrAdd(type.FullName, (v) =>
SerializObject typeInfo = m_instanceCache.GetOrAdd(type.FullName, (v) =>
{
SerializObject instanceObject = new SerializObject();
instanceObject.Type = type;
......@@ -509,7 +562,7 @@ namespace TouchSocket.Core.Serialization
type = type.GetGenericArguments()[0];
}
SerializObject serializObject = InstanceCache.GetOrAdd(type.FullName, (v) =>
SerializObject serializObject = m_instanceCache.GetOrAdd(type.FullName, (v) =>
{
SerializObject instanceObject = new SerializObject();
instanceObject.Type = type;
......@@ -537,7 +590,7 @@ namespace TouchSocket.Core.Serialization
}
instanceObject.ArgTypes = baseType.GetGenericArguments();
instanceObject.AddMethod = new Reflection.Method(type.GetMethod("Add"));
instanceObject.AddMethod = new Method(type.GetMethod("Add"));
instanceObject.instanceType = InstanceType.List;
}
else if (TouchSocketCoreUtility.dicType.IsAssignableFrom(type))
......@@ -562,5 +615,10 @@ namespace TouchSocket.Core.Serialization
}
return null;
}
private static PropertyInfo[] GetProperties(Type type)
{
return type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
}
}
}
\ No newline at end of file
using TouchSocket.Core.ByteManager;
namespace TouchSocket.Core.Serialization
{
/// <summary>
/// FastBinary转换器
/// </summary>
public interface IFastBinaryConverter
{
/// <summary>
/// 读取
/// </summary>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="len"></param>
/// <returns></returns>
public object Read(byte[] buffer, int offset, int len);
/// <summary>
/// 写入
/// </summary>
/// <param name="byteBlock"></param>
/// <param name="obj"></param>
public int Write(ByteBlock byteBlock, object obj);
}
/// <summary>
/// FastBinary转换器
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class FastBinaryConverter<T> : IFastBinaryConverter
{
int IFastBinaryConverter.Write(ByteBlock byteBlock, object obj)
{
return this.Write(byteBlock, (T)obj);
}
object IFastBinaryConverter.Read(byte[] buffer, int offset, int len)
{
return this.Read(buffer, offset, len);
}
/// <summary>
/// 写入
/// </summary>
/// <param name="byteBlock"></param>
/// <param name="obj"></param>
protected abstract int Write(ByteBlock byteBlock, T obj);
/// <summary>
/// 读取
/// </summary>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="len"></param>
/// <returns></returns>
protected abstract T Read(byte[] buffer, int offset, int len);
}
}
\ No newline at end of file
......@@ -13,10 +13,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using TouchSocket.Core;
using TouchSocket.Core.ByteManager;
using TouchSocket.Core.Collections;
using TouchSocket.Core.Extensions;
using TouchSocket.Core.IO;
using TouchSocket.Sockets;
......@@ -31,7 +33,7 @@ namespace TouchSocket.Http
/// <summary>
/// 服务器版本
/// </summary>
public static readonly string ServerVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
public static readonly string ServerVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
/// <summary>
/// 内容长度
......@@ -40,8 +42,8 @@ namespace TouchSocket.Http
private static readonly byte[] m_rnrnCode = Encoding.UTF8.GetBytes("\r\n\r\n");
private readonly Dictionary<string, string> m_headers;
private Encoding encoding = Encoding.UTF8;
private IgnoreCaseNameValueCollection m_headers;
private long m_readLen;
private string m_requestLine;
/// <summary>
......@@ -49,15 +51,24 @@ namespace TouchSocket.Http
/// </summary>
public HttpBase()
{
this.m_headers = new Dictionary<string, string>();
this.ReadTimeout = 1000 * 60;
}
/// <summary>
/// 能否写入。
/// </summary>
public abstract bool CanWrite { get; }
/// <summary>
/// 客户端
/// </summary>
public abstract ITcpClientBase Client { get; }
/// <summary>
/// 内容填充完成
/// </summary>
public bool? ContentComplated { get; protected set; }
/// <summary>
/// int类型,内容长度
/// </summary>
......@@ -67,11 +78,6 @@ namespace TouchSocket.Http
set => this.m_contentLength = value;
}
/// <summary>
/// 能否写入。
/// </summary>
public abstract bool CanWrite { get; }
/// <summary>
/// 内容长度
/// </summary>
......@@ -89,11 +95,7 @@ namespace TouchSocket.Http
/// <summary>
/// 编码方式
/// </summary>
public Encoding Encoding
{
get => this.encoding;
set => this.encoding = value;
}
public Encoding Encoding { get; set; } = Encoding.UTF8;
/// <summary>
/// 传递标识
......@@ -103,7 +105,14 @@ namespace TouchSocket.Http
/// <summary>
/// 请求头集合
/// </summary>
public Dictionary<string, string> Headers => this.m_headers;
public IgnoreCaseNameValueCollection Headers
{
get
{
this.m_headers ??= new IgnoreCaseNameValueCollection();
return this.m_headers;
}
}
/// <summary>
/// 协议名称,默认HTTP
......@@ -139,9 +148,7 @@ namespace TouchSocket.Http
{
var fieldName = header.GetDescription();
if (fieldName == null) return null;
var hasKey = this.Headers.ContainsKey(fieldName);
if (!hasKey) return null;
return this.Headers[fieldName];
return this.Headers.Get(fieldName);
}
/// <summary>
......@@ -167,7 +174,7 @@ namespace TouchSocket.Http
}
/// <summary>
/// <inheritdoc/>
/// 从Request中持续读取数据。
/// </summary>
/// <param name="buffer"></param>
/// <param name="offset"></param>
......@@ -175,11 +182,29 @@ namespace TouchSocket.Http
/// <returns></returns>
public override int Read(byte[] buffer, int offset, int count)
{
if (!this.CanRead)
if (this.ContentLength > 0)
{
throw new NotSupportedException("该对象不支持持续读取内容。");
if (!this.ContentComplated.HasValue)
{
int r = base.Read(buffer, offset, count);
if (r == 0)
{
if (this.ContentLength == this.m_readLen)
{
this.ContentComplated = true;
}
else
{
this.ContentComplated = false;
}
}
m_readLen += r;
return r;
}
}
return base.Read(buffer, offset, count);
return 0;
}
/// <summary>
......@@ -217,9 +242,7 @@ namespace TouchSocket.Http
public void SetHeaderByKey(string fieldName, string value)
{
if (string.IsNullOrEmpty(fieldName)) return;
var hasKey = this.Headers.ContainsKey(fieldName);
if (!hasKey) this.Headers.Add(fieldName, value);
this.Headers[fieldName] = value;
this.Headers.Add(fieldName, value);
}
/// <summary>
......@@ -263,14 +286,11 @@ namespace TouchSocket.Http
private string GetHeaderByKey(string fieldName)
{
if (string.IsNullOrEmpty(fieldName)) return null;
var hasKey = this.Headers.ContainsKey(fieldName);
if (!hasKey) return null;
return this.Headers[fieldName];
return this.Headers.Get(fieldName);
}
private void GetRequestHeaders(IEnumerable<string> rows)
{
this.m_headers.Clear();
if (rows == null || rows.Count() <= 0)
{
return;
......@@ -282,12 +302,11 @@ namespace TouchSocket.Http
if (kv.Length == 2)
{
string key = kv[0].ToLower();
if (!this.m_headers.ContainsKey(key))
{
this.m_headers.Add(key, kv[1]);
}
this.Headers.Add(key, kv[1]);
}
}
this.ContentType = this.GetHeader(HttpHeaders.ContentType);
}
}
}
\ No newline at end of file
......@@ -11,7 +11,8 @@
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
......@@ -30,9 +31,9 @@ namespace TouchSocket.Http
private bool m_canRead;
private ITcpClientBase m_client;
private byte[] m_content;
private GetContentResult m_getContentResult;
private Dictionary<string, string> m_params;
private Dictionary<string, string> m_query;
private NameValueCollection m_forms;
private NameValueCollection m_params;
private NameValueCollection m_query;
private string m_relativeURL;
private bool m_sentHeader;
private int m_sentLength;
......@@ -82,10 +83,47 @@ namespace TouchSocket.Http
/// </summary>
public override ITcpClientBase Client => this.m_client;
/// <summary>
/// 表单数据
/// </summary>
public NameValueCollection Forms
{
get
{
if (this.ContentType == @"application/x-www-form-urlencoded")
{
this.m_forms ??= this.GetParameters(this.GetBody());
return this.m_forms;
}
return this.m_forms ??= new NameValueCollection();
}
}
/// <summary>
/// 获取时候保持连接
/// </summary>
public bool KeepAlive { get; set; }
public bool KeepAlive
{
get
{
if (this.ProtocolVersion == "1.0")
{
return false;
}
else
{
if (this.GetHeader(HttpHeaders.Connection) == "keep-alive")
{
return true;
}
else
{
return false;
}
}
}
}
/// <summary>
/// HTTP请求方式。
......@@ -95,14 +133,11 @@ namespace TouchSocket.Http
/// <summary>
/// Body参数
/// </summary>
public Dictionary<string, string> Params
public NameValueCollection Params
{
get
{
if (this.m_params == null)
{
this.m_params = new Dictionary<string, string>();
}
this.m_params ??= new NameValueCollection();
return this.m_params;
}
}
......@@ -110,14 +145,11 @@ namespace TouchSocket.Http
/// <summary>
/// url参数
/// </summary>
public Dictionary<string, string> Query
public NameValueCollection Query
{
get
{
if (this.m_query == null)
{
this.m_query = new Dictionary<string, string>();
}
this.m_query ??= new NameValueCollection();
return this.m_query;
}
}
......@@ -149,11 +181,9 @@ namespace TouchSocket.Http
/// <returns></returns>
public byte[] BuildAsBytes()
{
using (ByteBlock byteBlock = new ByteBlock())
{
this.Build(byteBlock);
return byteBlock.ToArray();
}
using ByteBlock byteBlock = new ByteBlock();
this.Build(byteBlock);
return byteBlock.ToArray();
}
/// <summary>
......@@ -164,7 +194,7 @@ namespace TouchSocket.Http
{
this.m_content = content;
this.ContentLength = content.Length;
this.m_getContentResult = GetContentResult.Success;
this.ContentComplated = true;
}
/// <summary>
......@@ -187,65 +217,71 @@ namespace TouchSocket.Http
return this;
}
/// <summary>
/// 输出
/// </summary>
public override string ToString()
{
using (ByteBlock byteBlock = new ByteBlock())
{
this.Build(byteBlock);
return byteBlock.ToString();
}
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <returns></returns>
public override bool TryGetContent(out byte[] content)
{
switch (this.m_getContentResult)
if (!this.ContentComplated.HasValue)
{
case GetContentResult.Default:
if (this.m_contentLength == 0)
{
this.m_content = new byte[0];
content = this.m_content;
this.ContentComplated = true;
return true;
}
try
{
using MemoryStream block1 = new MemoryStream();
using ByteBlock block2 = new ByteBlock();
byte[] buffer = block2.Buffer;
while (true)
{
if (this.m_contentLength == 0)
{
this.m_content = new byte[0];
content = this.m_content;
this.m_getContentResult = GetContentResult.Success;
return true;
}
try
{
using (ByteBlock block1 = new ByteBlock(1024 * 1024))
{
using (ByteBlock block2 = new ByteBlock())
{
byte[] buffer = block2.Buffer;
while (true)
{
int r = this.Read(buffer, 0, buffer.Length);
if (r == 0)
{
break;
}
block1.Write(buffer, 0, r);
}
this.m_content = block1.ToArray();
content = this.m_content;
this.m_getContentResult = GetContentResult.Success;
return true;
}
}
}
catch
int r = this.Read(buffer, 0, buffer.Length);
if (r == 0)
{
this.m_getContentResult = GetContentResult.Fail;
content = null;
return false;
}
finally
{
this.m_canRead = false;
break;
}
block1.Write(buffer, 0, r);
}
case GetContentResult.Success:
this.m_content = block1.ToArray();
content = this.m_content;
return true;
case GetContentResult.Fail:
default:
}
catch
{
this.ContentComplated = false;
content = null;
return false;
}
finally
{
this.m_canRead = false;
}
}
else if (this.ContentComplated == true)
{
content = this.m_content;
return true;
}
else
{
content = null;
return false;
}
}
......@@ -307,31 +343,6 @@ namespace TouchSocket.Http
this.ProtocolVersion = ps[1];
}
}
if (this.ProtocolVersion == "1.1")
{
if (this.GetHeader(HttpHeaders.Connection) == "keep-alive")
{
this.KeepAlive = true;
}
else
{
this.KeepAlive = false;
}
}
else
{
this.KeepAlive = false;
}
if (this.Method == "POST")
{
this.ContentType = this.GetHeader(HttpHeaders.ContentType);
if (this.ContentType == @"application/x-www-form-urlencoded")
{
this.m_params = this.GetParameters(this.GetBody());
}
}
}
private void BuildContent(ByteBlock byteBlock)
......@@ -363,9 +374,9 @@ namespace TouchSocket.Http
urlBuilder.Append(this.m_relativeURL);
urlBuilder.Append("?");
int i = 0;
foreach (var item in this.m_query)
foreach (var item in this.m_query.AllKeys)
{
urlBuilder.Append($"{item.Key}={item.Value}");
urlBuilder.Append($"{item}={this.m_query[item]}");
if (++i < this.m_query.Count)
{
urlBuilder.Append("&");
......@@ -387,7 +398,7 @@ namespace TouchSocket.Http
{
this.SetHeader(HttpHeaders.ContentLength, this.ContentLength.ToString());
}
foreach (var headerkey in this.Headers.Keys)
foreach (var headerkey in this.Headers.AllKeys)
{
stringBuilder.Append($"{headerkey}: ");
stringBuilder.Append(this.Headers[headerkey] + "\r\n");
......@@ -397,7 +408,7 @@ namespace TouchSocket.Http
byteBlock.Write(this.Encoding.GetBytes(stringBuilder.ToString()));
}
private Dictionary<string, string> GetParameters(string row)
private NameValueCollection GetParameters(string row)
{
if (string.IsNullOrEmpty(row))
{
......@@ -409,7 +420,7 @@ namespace TouchSocket.Http
return null;
}
Dictionary<string, string> pairs = new Dictionary<string, string>();
NameValueCollection pairs = new NameValueCollection();
foreach (var item in kvs)
{
string[] kv = item.SplitFirst('=');
......@@ -421,18 +432,6 @@ namespace TouchSocket.Http
return pairs;
}
/// <summary>
/// 输出
/// </summary>
public override string ToString()
{
using (ByteBlock byteBlock = new ByteBlock())
{
this.Build(byteBlock);
return byteBlock.ToString();
}
}
private void ParseUrl()
{
......
......@@ -29,7 +29,6 @@ namespace TouchSocket.Http
private bool m_canWrite;
private ITcpClientBase m_client;
private byte[] m_content;
private GetContentResult m_getContentResult;
private bool m_responsed;
private bool m_sentHeader;
private long m_sentLength;
......@@ -88,6 +87,7 @@ namespace TouchSocket.Http
return this.GetHeader(HttpHeaders.Connection).Equals("close", StringComparison.CurrentCultureIgnoreCase);
}
}
/// <summary>
/// 是否分块
/// </summary>
......@@ -114,6 +114,7 @@ namespace TouchSocket.Http
return this.StatusCode == "301" || this.StatusCode == "302";
}
}
/// <summary>
/// 是否已经响应数据。
/// </summary>
......@@ -200,7 +201,7 @@ namespace TouchSocket.Http
{
this.m_content = content;
this.ContentLength = content.Length;
this.m_getContentResult = GetContentResult.Success;
this.ContentComplated = true;
}
/// <summary>
......@@ -209,59 +210,57 @@ namespace TouchSocket.Http
/// <returns></returns>
public override bool TryGetContent(out byte[] content)
{
switch (this.m_getContentResult)
if (!this.ContentComplated.HasValue)
{
case GetContentResult.Default:
{
if (!this.IsChunk && this.m_contentLength == 0)
{
this.m_content = new byte[0];
content = this.m_content;
return true;
}
if (!this.IsChunk && this.m_contentLength == 0)
{
this.m_content = new byte[0];
content = this.m_content;
return true;
}
try
try
{
using (ByteBlock block1 = new ByteBlock(1024 * 1024))
{
using (ByteBlock block2 = new ByteBlock())
{
using (ByteBlock block1 = new ByteBlock(1024 * 1024))
byte[] buffer = block2.Buffer;
while (true)
{
using (ByteBlock block2 = new ByteBlock())
int r = this.Read(buffer, 0, buffer.Length);
if (r == 0)
{
byte[] buffer = block2.Buffer;
while (true)
{
int r = this.Read(buffer, 0, buffer.Length);
if (r == 0)
{
break;
}
block1.Write(buffer, 0, r);
}
this.m_content = block1.ToArray();
content = this.m_content;
this.m_getContentResult = GetContentResult.Success;
return true;
break;
}
block1.Write(buffer, 0, r);
}
}
catch
{
this.m_getContentResult = GetContentResult.Fail;
content = null;
return false;
}
finally
{
this.m_canRead = false;
this.m_content = block1.ToArray();
content = this.m_content;
return true;
}
}
case GetContentResult.Success:
content = this.m_content;
return true;
case GetContentResult.Fail:
default:
}
catch
{
this.ContentComplated = false;
content = null;
return false;
}
finally
{
this.m_canRead = false;
}
}
else if (this.ContentComplated == true)
{
content = this.m_content;
return true;
}
else
{
content = null;
return false;
}
}
......@@ -386,7 +385,7 @@ namespace TouchSocket.Http
{
this.SetHeader(HttpHeaders.TransferEncoding, "chunked");
}
foreach (var headerkey in this.Headers.Keys)
foreach (var headerkey in this.Headers.AllKeys)
{
stringBuilder.Append($"{headerkey}: ");
stringBuilder.Append(this.Headers[headerkey] + "\r\n");
......
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using TouchSocket.Core.Extensions;
namespace TouchSocket.Http
{
/// <summary>
/// 多文件集合
/// </summary>
public class MultifileCollection : IEnumerable<IFormFile>
{
private readonly HttpRequest m_httpRequest;
/// <summary>
/// 多文件集合
/// </summary>
/// <param name="httpRequest"></param>
public MultifileCollection(HttpRequest httpRequest)
{
this.m_httpRequest = httpRequest;
}
/// <summary>
/// 获取一个迭代器。
/// </summary>
/// <returns></returns>
public IEnumerator<IFormFile> GetEnumerator()
{
if (this.m_httpRequest.ContentComplated == null || this.m_httpRequest.ContentComplated == true)
{
if (this.m_httpRequest.TryGetContent(out byte[] context))
{
byte[] boundary = $"--{this.m_httpRequest.GetBoundary()}".ToUTF8Bytes();
var indexs = context.IndexOfInclude(0, context.Length, boundary);
if (indexs.Count <= 0)
{
throw new Exception("没有发现由Boundary包裹的数据。");
}
List<IFormFile> files = new List<IFormFile>();
for (int i = 0; i < indexs.Count; i++)
{
if (i + 1 < indexs.Count)
{
InternalFormFile internalFormFile = new InternalFormFile();
files.Add(internalFormFile);
int index = context.IndexOfFirst(indexs[i] + 3, indexs[i + 1], Encoding.UTF8.GetBytes("\r\n\r\n"));
string line = Encoding.UTF8.GetString(context, indexs[i] + 3, index - indexs[i] - 6);
string[] lines = line.Split(new string[] { ";", "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
internalFormFile.DataPair = new NameValueCollection();
foreach (var item in lines)
{
string[] kv = item.Split(new char[] { ':', '=' });
if (kv.Length == 2)
{
internalFormFile.DataPair.Add(kv[0].Trim(), kv[1].Replace("\"",String.Empty).Trim());
}
}
int length = indexs[i + 1] - (index + 2) - boundary.Length;
byte[] data = new byte[length];
Array.Copy(context, index + 1, data, 0, length);
//string ssss = Encoding.UTF8.GetString(data);
internalFormFile.Data = data;
}
}
return files.GetEnumerator();
}
throw new Exception("管道状态异常");
}
else
{
throw new Exception("管道状态异常");
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
}
\ No newline at end of file
//------------------------------------------------------------------------------
// 此代码版权(除特别声明或在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.Http
{
internal enum GetContentResult
{
Default,
Success,
Fail
}
}
\ No newline at end of file
......@@ -97,6 +97,30 @@ namespace TouchSocket.Http
throw new Exception("获取数据体错误。");
}
/// <summary>
/// 当数据类型为multipart/form-data时,获取boundary
/// </summary>
/// <param name="httpBase"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public static string GetBoundary(this HttpBase httpBase)
{
if (httpBase.ContentType.IsNullOrEmpty())
{
return string.Empty;
}
string[] strs = httpBase.ContentType.Split(';');
if (strs.Length==2)
{
strs= strs[1].Split('=');
if (strs.Length==2)
{
return strs[1].Trim();
}
}
return string.Empty;
}
/// <summary>
/// 设置内容
/// </summary>
......@@ -179,6 +203,24 @@ namespace TouchSocket.Http
#region HttpRequest
/// <summary>
/// 获取多文件集合。如果不存在,则返回null。
/// </summary>
/// <typeparam name="TRequest"></typeparam>
/// <param name="request"></param>
/// <returns></returns>
public static MultifileCollection GetMultifileCollection<TRequest>(this TRequest request) where TRequest : HttpRequest
{
if (request.GetBoundary().IsNullOrEmpty())
{
return null;
}
else
{
return new MultifileCollection(request);
}
}
/// <summary>
/// 初始化常规的请求头。
/// <para>包含:</para>
......@@ -214,42 +256,6 @@ namespace TouchSocket.Http
return request;
}
/// <summary>
/// 获取指定参数
/// </summary>
/// <param name="httpRequest"></param>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public static bool TryGetParam<TRequest>(this TRequest httpRequest, string key, out string value) where TRequest : HttpRequest
{
if (httpRequest.Params.ContainsKey(key))
{
value = httpRequest.Params[key];
return true;
}
value = null;
return false;
}
/// <summary>
/// 获取指定url的查询参数
/// </summary>
/// <param name="httpRequest"></param>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public static bool TryGetQuery<TRequest>(this TRequest httpRequest, string key, out string value) where TRequest : HttpRequest
{
if (httpRequest.Query.ContainsKey(key))
{
value = httpRequest.Query[key];
return true;
}
value = null;
return false;
}
/// <summary>
/// 对比不包含参数的Url。其中有任意一方为null,则均返回False。
/// </summary>
......
using System.Collections.Specialized;
namespace TouchSocket.Http
{
/// <summary>
/// 表单文件
/// </summary>
public interface IFormFile
{
/// <summary>
/// 获取Content-Disposition
/// </summary>
string ContentDisposition { get; }
/// <summary>
/// 获取Content-Type
/// </summary>
string ContentType { get; }
/// <summary>
/// 实际的数据
/// </summary>
public byte[] Data { get; }
/// <summary>
/// 数据对
/// </summary>
public NameValueCollection DataPair { get; }
/// <summary>
/// 获取file name
/// </summary>
string FileName { get; }
/// <summary>
/// 文件长度。在数据接收完成之前,该值为-1;
/// </summary>
long Length { get; }
/// <summary>
/// 获取name字段
/// </summary>
string Name { get; }
///// <summary>
///// 读取文件数据 //太麻烦先不实现
///// </summary>
//public int Read(byte[] buffer, int offset, int count);
}
internal class InternalFormFile : IFormFile
{
public string ContentDisposition => this.DataPair["Content-Disposition"];
public string ContentType => this.DataPair["Content-Type"];
public byte[] Data { get; set; }
public NameValueCollection DataPair { get; set; }
public string FileName => this.DataPair["filename"];
public long Length => Data == null ? 0 : Data.Length;
public string Name => this.DataPair["name"];
//public int Read(byte[] buffer, int offset, int count)
//{
// return this.ReadAction(buffer, offset, count);
//}
//public Func<byte[], int, int, int> ReadAction { get; set; }
}
}
\ No newline at end of file
......@@ -40,7 +40,7 @@ namespace TouchSocket.Http.WebSockets
{
IsPermitOperation = true
};
client.PluginsManager?.Raise<IWebSocketPlugin>("OnHandshaking", client, args);
client.PluginsManager?.Raise<IWebSocketPlugin>(nameof(IWebSocketPlugin.OnHandshaking), client, args);
if (args.IsPermitOperation)
{
......@@ -53,7 +53,7 @@ namespace TouchSocket.Http.WebSockets
args.Context.Response.Build(byteBlock);
client.DefaultSend(byteBlock);
}
client.PluginsManager?.Raise<IWebSocketPlugin>("OnHandshaked", client, new HttpContextEventArgs(httpContext));
client.PluginsManager?.Raise<IWebSocketPlugin>(nameof(IWebSocketPlugin.OnHandshaked), client, new HttpContextEventArgs(httpContext));
return true;
}
else
......
......@@ -21,6 +21,21 @@ namespace TouchSocket.Http.WebSockets
/// </summary>
public interface IWebSocketPlugin : IPlugin
{
/// <summary>
/// 表示收到断开连接报文。如果对方直接断开连接,此方法则不会触发。
/// </summary>
/// <param name="client"></param>
/// <param name="e"></param>
[AsyncRaiser]
void OnClosing(ITcpClientBase client, MsgEventArgs e);
/// <summary>
/// 表示收到断开连接报文。如果对方直接断开连接,此方法则不会触发。
/// </summary>
/// <param name="client"></param>
/// <param name="e"></param>
Task OnClosingAsync(ITcpClientBase client, MsgEventArgs e);
/// <summary>
/// 当收到WS数据时。
/// </summary>
......
......@@ -30,6 +30,26 @@ namespace TouchSocket.Http.WebSockets.Plugins
{
#region 虚函数
/// <summary>
/// 表示收到断开连接报文。如果对方直接断开连接,此方法则不会触发。
/// </summary>
/// <param name="client"></param>
/// <param name="e"></param>
protected virtual void OnClosing(ITcpClientBase client, MsgEventArgs e)
{
}
/// <summary>
/// 表示收到断开连接报文。如果对方直接断开连接,此方法则不会触发。
/// </summary>
/// <param name="client"></param>
/// <param name="e"></param>
/// <returns></returns>
protected virtual Task OnClosingAsync(ITcpClientBase client, MsgEventArgs e)
{
return Task.FromResult(0);
}
/// <summary>
/// 处理WS数据帧。
/// </summary>
......@@ -94,6 +114,16 @@ namespace TouchSocket.Http.WebSockets.Plugins
#endregion 虚函数
void IWebSocketPlugin.OnClosing(ITcpClientBase client, MsgEventArgs e)
{
this.OnClosing(client, e);
}
Task IWebSocketPlugin.OnClosingAsync(ITcpClientBase client, MsgEventArgs e)
{
return this.OnClosingAsync(client, e);
}
void IWebSocketPlugin.OnHandleWSDataFrame(ITcpClientBase client, WSDataFrameEventArgs e)
{
this.OnHandleWSDataFrame((TClient)client, e);
......
......@@ -37,7 +37,12 @@ namespace TouchSocket.Http.WebSockets
public static readonly DependencyProperty WebSocketVersionProperty =
DependencyProperty.Register("WebSocketVersion", typeof(string), typeof(WebSocketServerPlugin), "13");
private string wSUrl = "/ws";
private string m_wSUrl = "/ws";
/// <summary>
/// 是否默认处理Close报文。
/// </summary>
public bool AutoClose { get; set; } = true;
/// <summary>
/// 处理WS数据的回调
......@@ -50,8 +55,18 @@ namespace TouchSocket.Http.WebSockets
/// </summary>
public string WSUrl
{
get => this.wSUrl;
set => this.wSUrl = string.IsNullOrEmpty(value) ? "/" : value;
get => this.m_wSUrl;
set => this.m_wSUrl = string.IsNullOrEmpty(value) ? "/" : value;
}
/// <summary>
/// 不处理Close报文。
/// </summary>
/// <returns></returns>
public WebSocketServerPlugin NoAutoClose()
{
this.AutoClose = false;
return this;
}
/// <summary>
......@@ -104,8 +119,15 @@ namespace TouchSocket.Http.WebSockets
/// <param name="e"></param>
protected virtual void OnHandleWSDataFrame(ITcpClientBase client, WSDataFrameEventArgs e)
{
this.PluginsManager.Raise<IWebSocketPlugin>("OnHandleWSDataFrame", client, e);
if (e.Handled)
if (e.DataFrame.Opcode == WSDataType.Close && this.AutoClose)
{
string msg = e.DataFrame.PayloadData?.ToString();
this.PluginsManager.Raise<IWebSocketPlugin>(nameof(IWebSocketPlugin.OnClosing), client, new MsgEventArgs() { Message = msg });
client.Close(msg);
return;
}
if (this.PluginsManager.Raise<IWebSocketPlugin>(nameof(IWebSocketPlugin.OnHandleWSDataFrame), client, e))
{
return;
}
......
......@@ -20,7 +20,6 @@ namespace TouchSocket.Rpc
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum)]
public class RpcProxyAttribute : Attribute
{
private string className;
/// <summary>
/// 构造函数
......@@ -33,7 +32,7 @@ namespace TouchSocket.Rpc
throw new ArgumentException($"“{nameof(className)}”不能为 null 或空。", nameof(className));
}
this.className = className;
this.ClassName = className;
}
/// <summary>
......@@ -46,10 +45,6 @@ namespace TouchSocket.Rpc
/// <summary>
/// 代理类名
/// </summary>
public string ClassName
{
get => this.className;
set => this.className = value;
}
public string ClassName { get; set; }
}
}
\ No newline at end of file
......@@ -11,6 +11,7 @@
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
......@@ -28,25 +29,24 @@ namespace TouchSocket.Rpc
{
private static readonly string[] m_dicType = { "Dictionary`2", "IDictionary`2" };
private static readonly string[] m_listType = { "List`1", "HashSet`1", "IList`1", "ISet`1", "ICollection`1", "IEnumerable`1" };
private readonly Assembly m_assembly;
private readonly Dictionary<Type, string> m_genericTypeDic;
private readonly Dictionary<Type, ClassCellCode> m_propertyDic;
private readonly Assembly[] m_assembly;
private readonly ConcurrentDictionary<Type, string> m_genericTypeDic;
private readonly ConcurrentDictionary<Type, ClassCellCode> m_propertyDic;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="assembly"></param>
public ClassCodeGenerator(Assembly assembly)
public ClassCodeGenerator(Assembly[] assembly)
{
this.m_assembly = assembly;
this.m_propertyDic = new Dictionary<Type, ClassCellCode>();
this.m_genericTypeDic = new Dictionary<Type, string>();
this.m_propertyDic = new ConcurrentDictionary<Type, ClassCellCode>();
this.m_genericTypeDic = new ConcurrentDictionary<Type, string>();
}
/// <summary>
/// 程序集
/// </summary>
public Assembly Assembly => this.m_assembly;
public Assembly[] Assembly => this.m_assembly;
/// <summary>
/// 获取类单元参数
......@@ -93,8 +93,8 @@ namespace TouchSocket.Rpc
{
Type[] elementType = type.GetGenericArguments();
var strs = elementType.Select(e=> this.GetTypeFullName(e));
return $"({string.Join(",",strs)})";
var strs = elementType.Select(e => this.GetTypeFullName(e));
return $"({string.Join(",", strs)})";
}
else if (type.IsByRef)
{
......@@ -118,8 +118,56 @@ namespace TouchSocket.Rpc
}
}
internal void AddTypeString(Type type)
internal void CheckDeep()
{
foreach (var strItem in this.m_genericTypeDic)
{
bool goon = true;
string strItemNew= strItem.Value;
while (goon)
{
goon = false;
foreach (var item in this.m_genericTypeDic.Keys)
{
if (strItemNew.Contains(item.FullName))
{
strItemNew = strItemNew.Replace(item.FullName, item.Name);
goon = true;
}
}
}
this.m_genericTypeDic[strItem.Key] = strItemNew;
}
foreach (var strItem in this.m_propertyDic)
{
bool goon = true;
string strItemNew = strItem.Value.Code;
while (goon)
{
goon = false;
foreach (var item in this.m_propertyDic.Keys)
{
if (strItemNew.Contains(item.FullName))
{
strItemNew = strItemNew.Replace(item.FullName, item.Name);
goon = true;
}
}
}
this.m_propertyDic[strItem.Key].Code = strItemNew;
}
}
internal void AddTypeString(Type type,ref int deep)
{
deep++;
if (deep>50)
{
return;
}
if (type.IsByRef)
{
type = type.GetRefOutType();
......@@ -129,14 +177,14 @@ namespace TouchSocket.Rpc
{
if (type.IsArray)
{
this.AddTypeString(type.GetElementType());
this.AddTypeString(type.GetElementType(),ref deep);
}
else if (type.IsGenericType)
{
Type[] types = type.GetGenericArguments();
foreach (Type itemType in types)
{
this.AddTypeString(itemType);
this.AddTypeString(itemType, ref deep);
}
if (m_listType.Contains(type.Name))
......@@ -145,7 +193,7 @@ namespace TouchSocket.Rpc
string typeString = $"System.Collections.Generic.{type.Name.Replace("`1", string.Empty)}<{typeInnerString}>";
if (!this.m_genericTypeDic.ContainsKey(type))
{
this.m_genericTypeDic.Add(type, typeString);
this.m_genericTypeDic.TryAdd(type, typeString);
}
}
else if (m_dicType.Contains(type.Name))
......@@ -155,7 +203,7 @@ namespace TouchSocket.Rpc
string typeString = $"System.Collections.Generic.{type.Name.Replace("`2", string.Empty)}<{keyString},{valueString}>";
if (!this.m_genericTypeDic.ContainsKey(type))
{
this.m_genericTypeDic.Add(type, typeString);
this.m_genericTypeDic.TryAdd(type, typeString);
}
}
}
......@@ -218,12 +266,12 @@ namespace TouchSocket.Rpc
string className;
if (type.GetCustomAttribute<RpcProxyAttribute>() is RpcProxyAttribute attribute)
{
className = attribute.ClassName?? type.Name;
className = attribute.ClassName ?? type.Name;
}
else if (CodeGenerator.TryGetProxyTypeName(type, out className))
{
}
else if (type.Assembly == this.m_assembly)
else if (this.AllowGen(type.Assembly))
{
className = type.Name;
}
......@@ -231,7 +279,7 @@ namespace TouchSocket.Rpc
{
return;
}
this.m_propertyDic.Add(type, new ClassCellCode() { Name = className, Code = stringBuilder.ToString() });
this.m_propertyDic.TryAdd(type, new ClassCellCode() { Name = className, Code = stringBuilder.ToString() });
}
}
else
......@@ -244,7 +292,7 @@ namespace TouchSocket.Rpc
else if (CodeGenerator.TryGetProxyTypeName(type, out className))
{
}
else if (type.Assembly == this.m_assembly)
else if (this.AllowGen(type.Assembly))
{
className = type.Name;
}
......@@ -266,13 +314,13 @@ namespace TouchSocket.Rpc
if (!type.IsStruct() && type.BaseType != typeof(object))
{
this.AddTypeString(type.BaseType);
this.AddTypeString(type.BaseType, ref deep);
if (type.BaseType.IsGenericType)
{
Type[] types = type.BaseType.GetGenericArguments();
foreach (Type itemType in types)
{
this.AddTypeString(itemType);
this.AddTypeString(itemType,ref deep);
}
if (m_listType.Contains(type.BaseType.Name))
{
......@@ -297,7 +345,7 @@ namespace TouchSocket.Rpc
foreach (PropertyInfo itemProperty in propertyInfos)
{
this.AddTypeString(itemProperty.PropertyType);
this.AddTypeString(itemProperty.PropertyType, ref deep);
if (this.m_propertyDic.ContainsKey(itemProperty.PropertyType))
{
stringBuilder.Append($"public {itemProperty.PropertyType.Name} {itemProperty.Name}");
......@@ -307,7 +355,7 @@ namespace TouchSocket.Rpc
Type[] types = itemProperty.PropertyType.GetGenericArguments();
foreach (Type itemType in types)
{
this.AddTypeString(itemType);
this.AddTypeString(itemType, ref deep);
}
if (m_listType.Contains(itemProperty.PropertyType.Name))
......@@ -324,8 +372,8 @@ namespace TouchSocket.Rpc
}
else
{
this.AddTypeString(itemProperty.PropertyType);
stringBuilder.Append($"public {itemProperty.PropertyType.FullName} {itemProperty.Name}");
this.AddTypeString(itemProperty.PropertyType, ref deep);
stringBuilder.Append($"public {this.GetTypeFullName(itemProperty.PropertyType)} {itemProperty.Name}");
}
stringBuilder.AppendLine("{get;set;}");
......@@ -335,10 +383,22 @@ namespace TouchSocket.Rpc
if (!this.m_propertyDic.ContainsKey(type))
{
this.m_propertyDic.Add(type, new ClassCellCode() { Name = className, Code = stringBuilder.ToString() });
this.m_propertyDic.TryAdd(type, new ClassCellCode() { Name = className, Code = stringBuilder.ToString() });
}
}
}
}
private bool AllowGen(Assembly assembly)
{
foreach (var item in this.m_assembly)
{
if (assembly == item)
{
return true;
}
}
return false;
}
}
}
\ No newline at end of file
......@@ -25,8 +25,8 @@ namespace TouchSocket.Rpc
/// </summary>
public static class CodeGenerator
{
private static readonly Dictionary<Type, string> proxyType = new Dictionary<Type, string>();
private static readonly Dictionary<Type, string> m_proxyType = new Dictionary<Type, string>();
private static readonly List<Assembly> m_assemblies = new List<Assembly>();
/// <summary>
/// 生成回调。
/// </summary>
......@@ -36,6 +36,15 @@ namespace TouchSocket.Rpc
/// <returns></returns>
public delegate bool GeneratorCallback<T>(MethodInstance methodInstance, MethodCellCode methodCellCode) where T : RpcAttribute;
/// <summary>
/// 添加需要代理的程序集
/// </summary>
/// <param name="assembly"></param>
public static void AddProxyAssembly(Assembly assembly)
{
m_assemblies.Add(assembly);
}
/// <summary>
/// 添加代理类型
/// </summary>
......@@ -47,10 +56,10 @@ namespace TouchSocket.Rpc
{
return;
}
if (!proxyType.ContainsKey(type))
if (!m_proxyType.ContainsKey(type))
{
RpcProxyAttribute attribute = type.GetCustomAttribute<RpcProxyAttribute>();
proxyType.Add(type, attribute == null ? type.Name : attribute.ClassName);
m_proxyType.Add(type, attribute == null ? type.Name : attribute.ClassName);
if (deepSearch)
{
PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.SetProperty);
......@@ -79,7 +88,7 @@ namespace TouchSocket.Rpc
/// <returns></returns>
public static bool ContainsType(Type type)
{
return proxyType.ContainsKey(type);
return m_proxyType.ContainsKey(type);
}
/// <summary>
......@@ -236,15 +245,18 @@ namespace TouchSocket.Rpc
ServerCellCode serverCellCode = new ServerCellCode();
MethodInstance[] methodInstances = GetMethodInstances(serverType);
ClassCodeGenerator classCodeGenerator = new ClassCodeGenerator(serverType.Assembly);
List<Assembly> assemblies=new List<Assembly>(m_assemblies);
assemblies.Add(serverType.Assembly);
ClassCodeGenerator classCodeGenerator = new ClassCodeGenerator(assemblies.ToArray());
serverCellCode.Name = serverType.IsInterface ?
(serverType.Name.StartsWith("I") ? serverType.Name.Remove(0, 1) : serverType.Name) : serverType.Name;
List<MethodInstance> instances = new List<MethodInstance>();
foreach (var item in proxyType.Keys)
foreach (var item in m_proxyType.Keys)
{
classCodeGenerator.AddTypeString(item);
int deep = 0;
classCodeGenerator.AddTypeString(item,ref deep);
}
foreach (MethodInstance methodInstance in methodInstances)
......@@ -255,7 +267,8 @@ namespace TouchSocket.Rpc
{
if (methodInstance.ReturnType != null)
{
classCodeGenerator.AddTypeString(methodInstance.ReturnType);
int deep = 0;
classCodeGenerator.AddTypeString(methodInstance.ReturnType,ref deep);
}
int i = 0;
......@@ -265,7 +278,8 @@ namespace TouchSocket.Rpc
}
for (; i < methodInstance.ParameterTypes.Length; i++)
{
classCodeGenerator.AddTypeString(methodInstance.ParameterTypes[i]);
int deep = 0;
classCodeGenerator.AddTypeString(methodInstance.ParameterTypes[i],ref deep);
}
instances.Add(methodInstance);
......@@ -273,19 +287,25 @@ namespace TouchSocket.Rpc
}
}
}
classCodeGenerator.CheckDeep();
foreach (var item in classCodeGenerator.GetClassCellCodes())
{
serverCellCode.ClassCellCodes.Add(item.Name, item);
}
ServerCodeGenerator serverCodeGenerator = new ServerCodeGenerator(classCodeGenerator);
//ServerCodeGenerator serverCodeGenerator = new ServerCodeGenerator(classCodeGenerator);
bool first = true;
foreach (var item in instances)
{
MethodCellCode methodCellCode = new MethodCellCode();
RpcAttribute rpcAttribute = (RpcAttribute)item.GetAttribute(attributeType);
if (rpcAttribute==null)
{
continue;
}
rpcAttribute.SetClassCodeGenerator(classCodeGenerator);
if (first)
{
if (rpcAttribute.GeneratorFlag.HasFlag(CodeGeneratorFlag.IncludeInterface))
......@@ -303,9 +323,9 @@ namespace TouchSocket.Rpc
first = false;
}
methodCellCode.InterfaceTemple = serverCodeGenerator.GetInterfaceProxy(item, rpcAttribute);
methodCellCode.CodeTemple = serverCodeGenerator.GetMethodProxy(item, rpcAttribute);
methodCellCode.ExtensionsTemple = serverCodeGenerator.GetExtensionsMethodProxy(item, rpcAttribute);
methodCellCode.InterfaceTemple = rpcAttribute.GetInterfaceProxyCode(item);
methodCellCode.CodeTemple = rpcAttribute.GetInstanceProxyCode(item);
methodCellCode.ExtensionsTemple = rpcAttribute.GetExtensionsMethodProxyCode(item);
methodCellCode.Name = ((RpcAttribute)item.GetAttribute(attributeType)).GetMethodName(item, false);
serverCellCode.Methods.Add(methodCellCode.Name, methodCellCode);
}
......@@ -406,7 +426,7 @@ namespace TouchSocket.Rpc
/// <returns></returns>
public static bool TryGetProxyTypeName(Type type, out string className)
{
return proxyType.TryGetValue(type, out className);
return m_proxyType.TryGetValue(type, out className);
}
}
}
\ No newline at end of file
......@@ -666,41 +666,39 @@ namespace TouchSocket.Rpc
}
return;
}
if (e.Context.Request.TryGetQuery(RpcStore.ProxyKey, out string value))
{
List<Type> types = new List<Type>();
string value = e.Context.Request.Query[RpcStore.ProxyKey];
List<Type> types = new List<Type>();
if (value.Equals("all", StringComparison.CurrentCultureIgnoreCase))
{
types = RpcStore.ProxyAttributeMap.Values.ToList();
}
else
if (value.Equals("all", StringComparison.CurrentCultureIgnoreCase))
{
types = RpcStore.ProxyAttributeMap.Values.ToList();
}
else
{
string[] vs = value.Split(',');
foreach (var item in vs)
{
string[] vs = value.Split(',');
foreach (var item in vs)
if (RpcStore.ProxyAttributeMap.TryGetValue(item, out Type type))
{
if (RpcStore.ProxyAttributeMap.TryGetValue(item, out Type type))
{
types.Add(type);
}
types.Add(type);
}
}
}
e.Context.Request.TryGetQuery(RpcStore.Namespace, out string names);
string names = e.Context.Request.Query[RpcStore.Namespace];
names = string.IsNullOrEmpty(names) ? "RRQMProxy" : names;
names = string.IsNullOrEmpty(names) ? "RRQMProxy" : names;
string code = CodeGenerator.ConvertToCode(names, this.m_rpcStore.GetProxyInfo(types.ToArray()));
string code = CodeGenerator.ConvertToCode(names, this.m_rpcStore.GetProxyInfo(types.ToArray()));
using (ByteBlock byteBlock = new ByteBlock())
{
e.Context.Response
.SetStatus()
.SetContent(code)
.SetContentTypeFromFileName($"{names}.cs")
.Build(byteBlock);
client.DefaultSend(byteBlock);
}
using (ByteBlock byteBlock = new ByteBlock())
{
e.Context.Response
.SetStatus()
.SetContent(code)
.SetContentTypeFromFileName($"{names}.cs")
.Build(byteBlock);
client.DefaultSend(byteBlock);
}
}
base.OnGet(client, e);
......
......@@ -808,7 +808,6 @@ namespace TouchSocket.Rpc.TouchRpc
long position = waitTransfer.Position;
reader.Position = position;
fileOperator.SetFileCompletedLength(waitTransfer.Position);
while (true)
{
if (fileOperator.Token.IsCancellationRequested)
......@@ -1007,7 +1006,6 @@ namespace TouchSocket.Rpc.TouchRpc
{
channel = this.CreateChannel(waitTransfer.ClientID);
}
waitTransfer.ChannelID = channel.ID;
waitTransfer.Position = fileInfo.Position;
waitTransfer.Status = 1;
......
......@@ -632,43 +632,6 @@ namespace TouchSocket.Rpc.TouchRpc
#endregion 200-299
#region 300-399
case TouchRpcUtility.P_300_GetAllEvents_Request:
{
break;
}
case TouchRpcUtility.P_301_PublishEvent_Request:
{
break;
}
case TouchRpcUtility.P_302_UnpublishEvent_Request:
{
break;
}
case TouchRpcUtility.P_303_SubscribeEvent_Request:
{
break;
}
case TouchRpcUtility.P_305_RaiseEvent_Request:
{
break;
}
case TouchRpcUtility.P_306_TriggerEvent://触发事件
{
break;
}
case TouchRpcUtility.P_1300_GetAllEvents_Response:
case TouchRpcUtility.P_1301_PublishEvent_Response:
case TouchRpcUtility.P_1302_UnpublishEvent_Response:
case TouchRpcUtility.P_1303_SubscribeEvent_Response:
case TouchRpcUtility.P_1305_RaiseEvent_Response:
{
break;
}
#endregion 300-399
#region 400-499
case TouchRpcUtility.P_400_SendStreamToSocketClient_Request://StreamStatusToThis
......@@ -711,6 +674,7 @@ namespace TouchSocket.Rpc.TouchRpc
}
break;
}
#endregion 400-499
#region 500-599
......@@ -1046,15 +1010,6 @@ namespace TouchSocket.Rpc.TouchRpc
}
break;
}
case TouchRpcUtility.P_510_RemoteAccess_Request:
{
break;
}
case TouchRpcUtility.P_1510_RemoteAccess_Response:
{
break;
}
#endregion 500-599
default:
......
......@@ -277,6 +277,7 @@ namespace TouchSocket.Rpc.TouchRpc
/// 向客户端发送流
/// </summary>
public const short P_401_SendStreamToClient = -401;
#endregion Stream协议 400-499
#region FileTransfer协议 500-599
......
......@@ -31,8 +31,8 @@ namespace TouchSocket.Rpc.TouchRpc
public class HttpTouchRpcClient : HttpClientBase, IHttpTouchRpcClient
{
private readonly ActionMap m_actionMap;
private int m_failCount = 0;
private readonly RpcActor m_rpcActor;
private int m_failCount = 0;
private RpcStore m_rpcStore;
private Timer m_timer;
......@@ -680,6 +680,7 @@ namespace TouchSocket.Rpc.TouchRpc
}
#region 内部委托绑定
private MethodInstance GetInvokeMethod(string arg)
{
return this.ActionMap.GetMethodInstance(arg);
......@@ -705,6 +706,30 @@ namespace TouchSocket.Rpc.TouchRpc
private void OnRpcActorHandshaked(RpcActor actor, VerifyOptionEventArgs e)
{
this.m_timer.SafeDispose();
if (this.Config.GetValue<HeartbeatValue>(TouchRpcConfigExtensions.HeartbeatFrequencyProperty) is HeartbeatValue heartbeat)
{
this.m_timer = new Timer((obj) =>
{
if (DateTime.Now.TimeOfDay-this.GetLastActiveTime().TimeOfDay<TimeSpan.FromMilliseconds(heartbeat.Interval))
{
return;
}
if (this.Ping())
{
Interlocked.Exchange(ref this.m_failCount, 0);
}
else
{
if (Interlocked.Increment(ref this.m_failCount) > heartbeat.MaxFailCount)
{
this.Close("自动心跳失败次数达到最大,已清理连接。");
this.m_timer.SafeDispose();
}
}
}, null, heartbeat.Interval, heartbeat.Interval);
}
if (this.UsePlugin && this.PluginsManager.Raise<ITouchRpcPlugin>(nameof(ITouchRpcPlugin.OnHandshaked), this, e))
{
return;
......@@ -760,13 +785,13 @@ namespace TouchSocket.Rpc.TouchRpc
#endregion 内部委托绑定
#region 事件触发
/// <summary>
/// 当文件传输结束之后。并不意味着完成传输,请通过<see cref="FileTransferStatusEventArgs.Result"/>属性值进行判断。
/// </summary>
/// <param name="e"></param>
protected virtual void OnFileTransfered(FileTransferStatusEventArgs e)
{
}
/// <summary>
......@@ -775,7 +800,6 @@ namespace TouchSocket.Rpc.TouchRpc
/// <param name="e"></param>
protected virtual void OnFileTransfering(FileOperationEventArgs e)
{
}
/// <summary>
......@@ -784,26 +808,7 @@ namespace TouchSocket.Rpc.TouchRpc
/// <param name="e"></param>
protected virtual void OnHandshaked(MsgEventArgs e)
{
this.m_timer.SafeDispose();
if (this.Config.GetValue<HeartbeatValue>(TouchRpcConfigExtensions.HeartbeatFrequencyProperty) is HeartbeatValue heartbeat)
{
this.m_timer = new Timer((obj) =>
{
if (this.Ping())
{
Interlocked.Exchange(ref this.m_failCount, 0);
}
else
{
if (Interlocked.Increment(ref this.m_failCount) > heartbeat.MaxFailCount)
{
this.Close("自动心跳失败次数达到最大,已清理连接。");
this.m_timer.SafeDispose();
}
}
}, null, heartbeat.Interval, heartbeat.Interval);
}
}
/// <summary>
......@@ -829,7 +834,6 @@ namespace TouchSocket.Rpc.TouchRpc
/// <param name="e"></param>
protected virtual void OnStreamTransfering(StreamOperationEventArgs e)
{
}
#endregion 事件触发
......@@ -863,6 +867,7 @@ namespace TouchSocket.Rpc.TouchRpc
this.m_rpcActor.RpcStore = rpcStore;
this.m_rpcStore = rpcStore;
}
#endregion RPC解析器
}
}
\ No newline at end of file
namespace TouchSocket.Rpc.TouchRpc
{
class HttpTouchRpcClient_2
{
public HttpTouchRpcClient_2()
{
}
}
}
......@@ -97,7 +97,8 @@ namespace TouchSocket.Rpc.WebApi
{
for (; i < methodInstance.Parameters.Length; i++)
{
if (e.Context.Request.Query.TryGetValue(methodInstance.ParameterNames[i], out string value))
string value = e.Context.Request.Query.Get(methodInstance.ParameterNames[i]);
if (!value.IsNullOrEmpty())
{
ps[i] = this.m_converter.ConvertFrom(value, methodInstance.ParameterTypes[i]);
}
......@@ -218,7 +219,8 @@ namespace TouchSocket.Rpc.WebApi
{
for (; i < methodInstance.Parameters.Length - 1; i++)
{
if (e.Context.Request.Query.TryGetValue(methodInstance.ParameterNames[i], out string value))
string value = e.Context.Request.Query.Get(methodInstance.ParameterNames[i]);
if (!value.IsNullOrEmpty())
{
ps[i] = this.m_converter.ConvertFrom(value, methodInstance.ParameterTypes[i]);
}
......
......@@ -354,6 +354,7 @@ namespace TouchSocket.Sockets
{
this.PluginsManager.Raise<IConfigPlugin>(nameof(IConfigPlugin.OnLoadedConfig), this, new ConfigEventArgs(config));
}
this.Container.RegisterTransient<TClient>();
return this;
}
......
......@@ -25,6 +25,7 @@ namespace TouchSocket.Sockets
{
private ITcpClientBase m_client;
/// <summary>
/// 当插件在被第一次加载时调用。
/// </summary>
......
......@@ -18,7 +18,6 @@ namespace TouchSocket.Sockets
/// </summary>
public class ClientDisconnectedEventArgs : MsgEventArgs
{
private readonly bool manual;
/// <summary>
/// 构造函数
......@@ -27,13 +26,13 @@ namespace TouchSocket.Sockets
/// <param name="mes"></param>
public ClientDisconnectedEventArgs(bool manual, string mes) : base(mes)
{
this.manual = manual;
this.Manual = manual;
}
/// <summary>
/// 是否为主动行为。
/// </summary>
public bool Manual => this.manual;
public bool Manual { get; private set; }
}
}
......@@ -521,6 +521,7 @@ namespace TouchSocket.Sockets
{
responsedData = new ResponsedData(null, requestInfo);
}
return !this.m_waitData.Set(responsedData);
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册