Pārlūkot izejas kodu

修改bug和提交三菱协议

ltwork 1 gadu atpakaļ
vecāks
revīzija
a086fe5fb2

+ 7 - 1
BlankApp1/BlankApp1.sln

@@ -13,7 +13,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Common", "Common\Common.csp
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Model", "Model\Model.csproj", "{70C6DE58-70FF-453F-96DB-5F254129FE37}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OmronFinsTCP.Net", "OmronFinsTCP.Net\OmronFinsTCP.Net.csproj", "{C5497625-00CA-41EC-8428-021143D7EEA9}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OmronFinsTCP.Net", "OmronFinsTCP.Net\OmronFinsTCP.Net.csproj", "{C5497625-00CA-41EC-8428-021143D7EEA9}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TFT-MelsecMcNet", "TFT-MelsecMcNet\TFT-MelsecMcNet.csproj", "{69BFE15C-D9A8-4E31-B2F2-AA1BA828DBFD}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -45,6 +47,10 @@ Global
 		{C5497625-00CA-41EC-8428-021143D7EEA9}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{C5497625-00CA-41EC-8428-021143D7EEA9}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{C5497625-00CA-41EC-8428-021143D7EEA9}.Release|Any CPU.Build.0 = Release|Any CPU
+		{69BFE15C-D9A8-4E31-B2F2-AA1BA828DBFD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{69BFE15C-D9A8-4E31-B2F2-AA1BA828DBFD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{69BFE15C-D9A8-4E31-B2F2-AA1BA828DBFD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{69BFE15C-D9A8-4E31-B2F2-AA1BA828DBFD}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

+ 1 - 1
BlankApp1/BlankApp1/App.config

@@ -4,7 +4,7 @@
 		<!--连接字符串 SQL Server-->
 		<add key="MySql" value="Data Source=localhost;Database=plc_point_db2;User Id='root';Password='521125';port=3306;charset=utf8mb4;"/>
 		<add key="PLCIp" value="192.168.250.1"/>
-		<add key="PLCPort" value="9600"/>
+		<add key="PLCPort" value="5999"/>
 		<add key="DelayTime" value="20"/>
 		<add key="LongDelayTime" value="60"/>
 	</appSettings>

+ 25 - 2
BlankApp1/BlankApp1/Common/PLCCom.cs

@@ -68,6 +68,7 @@ namespace PLCTool.Common
             }
             catch (Exception e)
             {
+                ENT.Close();
                 return false;
             }
           
@@ -160,6 +161,7 @@ namespace PLCTool.Common
                 switch (valueType)
                 {
                     case VarType.Bit:
+                    
                         BitState bit = BitState.OFF;
                         if (writeValue.Trim() == "1")
                         {
@@ -173,7 +175,17 @@ namespace PLCTool.Common
                             }
 
                         }
-                        reSuc = ENT.SetBitState(PlcMemory.DM, address, bit);
+                        if (address.Contains("w") || address.Contains("W"))
+                        {
+                            string realAddr = address.Substring(1, address.Length - 1);
+                            reSuc = ENT.SetBitState(PlcMemory.WR, realAddr, bit);
+                           
+                        }
+                        else
+                        {
+                            reSuc = ENT.SetBitState(PlcMemory.CIO, address, bit);
+                        }
+                       
                         //写成功
                         if (reSuc == 0)
                         {
@@ -184,7 +196,18 @@ namespace PLCTool.Common
                         break;
                     case VarType.Word:
                         short wValue = Convert.ToInt16(writeValue);
-                        reSuc = ENT.WriteWord(PlcMemory.DM, short.Parse(address), wValue);
+                        if (address.Contains("w") || address.Contains("W"))
+                        {
+                            string realAddr = address.Substring(1, address.Length - 1);
+                            reSuc = ENT.WriteWord(PlcMemory.WR, short.Parse(realAddr), wValue);
+
+                        }
+                        else
+                        {
+                            reSuc = ENT.WriteWord(PlcMemory.DM, short.Parse(address), wValue);
+
+                        }
+                        
                         //写成功
                         if (reSuc == 0)
                         {

+ 1 - 0
BlankApp1/BlankApp1/PLCTool.csproj

@@ -42,6 +42,7 @@
     <ProjectReference Include="..\Common\Common.csproj" />
     <ProjectReference Include="..\Model\Model.csproj" />
     <ProjectReference Include="..\OmronFinsTCP.Net\OmronFinsTCP.Net.csproj" />
+    <ProjectReference Include="..\TFT-MelsecMcNet\TFT-MelsecMcNet.csproj" />
   </ItemGroup>
   <ItemGroup>
     <Resource Include="Assets\Fonts\iconfont.ttf">

+ 6 - 2
BlankApp1/OmronFinsTCP.Net/BasicClass.cs

@@ -29,7 +29,7 @@ namespace OmronFinsTCP.Net
         {
             try
             {
-                Stream.Write(sd, 0, sd.Length);
+                Stream?.Write(sd, 0, sd.Length);
                 return 0;
             }
             catch
@@ -56,7 +56,11 @@ namespace OmronFinsTCP.Net
                 int index = 0;
                 do
                 {
-                    int len = Stream.Read(rd, index, rd.Length - index);
+                    int len = 0;
+                    if(Stream!=null)
+                    {
+                        len = Stream.Read(rd, index, rd.Length - index);
+                    }
                     if (len == 0)
                         return -1;//这里控制读取不到数据时就跳出,网络异常断开,数据读取不完整。
                     else

+ 53 - 0
BlankApp1/TFT-MelsecMcNet/ByteTransformHelper.cs

@@ -0,0 +1,53 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TFT_MelsecMcNet
+{
+    /// <summary>
+    /// 所有数据转换类的静态辅助方法
+    /// Static helper method for all data conversion classes
+    /// </summary>
+    public static class ByteTransformHelper
+    {
+        /// <summary>
+        /// 结果转换操作的基础方法,需要支持类型,及转换的委托
+        /// </summary>
+        /// <typeparam name="TResult">结果类型</typeparam>
+        /// <param name="result">源</param>
+        /// <param name="translator">实际转换的委托</param>
+        /// <returns>转换结果</returns>
+        public static OperateResult<TResult> GetResultFromBytes<TResult>(OperateResult<byte[]> result, Func<byte[], TResult> translator)
+        {
+            try
+            {
+                if (result.IsSuccess)
+                {
+                    return OperateResult.CreateSuccessResult(translator(result.Content));
+                }
+                else
+                {
+                    return OperateResult.CreateFailedResult<TResult>(result);
+                }
+            }
+            catch (Exception ex)
+            {
+                return new OperateResult<TResult>() { Message = StringResources.Language.DataTransformError + SoftBasic.ByteToHexString(result.Content) + $" : Length({result.Content.Length}) " + ex.Message };
+            }
+        }
+
+        /// <summary>
+        /// 结果转换操作的基础方法,需要支持类型,及转换的委托
+        /// </summary>
+        /// <typeparam name="TResult">结果类型</typeparam>
+        /// <param name="result">源结果</param>
+        /// <returns>转换结果</returns>
+        public static OperateResult<TResult> GetResultFromArray<TResult>(OperateResult<TResult[]> result)
+        {
+            if (!result.IsSuccess) return OperateResult.CreateFailedResult<TResult>(result);
+
+            return OperateResult.CreateSuccessResult(result.Content[0]);
+        }
+
+    }
+}

+ 323 - 0
BlankApp1/TFT-MelsecMcNet/DefaultLanguage.cs

@@ -0,0 +1,323 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TFT_MelsecMcNet
+{
+    /// <summary>
+    /// 系统的语言基类,默认也即是中文版本
+    /// </summary>
+    public class DefaultLanguage
+    {
+        /***********************************************************************************
+         * 
+         *    一般的错误信息
+         * 
+         ************************************************************************************/
+
+        public virtual string AuthorizationFailed => "系统授权失败,需要使用激活码授权,谢谢支持。";
+        public virtual string ConnectedFailed => "连接失败:";
+        public virtual string ConnectedSuccess => "连接成功!";
+        public virtual string UnknownError => "未知错误";
+        public virtual string ErrorCode => "错误代号";
+        public virtual string TextDescription => "文本描述";
+        public virtual string ExceptionMessage => "错误信息:";
+        public virtual string ExceptionSourse => "错误源:";
+        public virtual string ExceptionType => "错误类型:";
+        public virtual string ExceptionStackTrace => "错误堆栈:";
+        public virtual string ExceptopnTargetSite => "错误方法:";
+        public virtual string ExceprionCustomer => "用户自定义方法出错:";
+        public virtual string SuccessText => "成功";
+        public virtual string TwoParametersLengthIsNotSame => "两个参数的个数不一致";
+        public virtual string NotSupportedDataType => "输入的类型不支持,请重新输入";
+        public virtual string NotSupportedFunction => "当前的功能逻辑不支持";
+        public virtual string DataLengthIsNotEnough => "接收的数据长度不足,应该值:{0},实际值:{1}";
+        public virtual string ReceiveDataTimeout => "接收数据超时:";
+        public virtual string ReceiveDataLengthTooShort => "接收的数据长度太短:";
+        public virtual string MessageTip => "消息提示:";
+        public virtual string Close => "关闭";
+        public virtual string Time => "时间:";
+        public virtual string SoftWare => "软件:";
+        public virtual string BugSubmit => "Bug提交";
+        public virtual string MailServerCenter => "邮件发送系统";
+        public virtual string MailSendTail => "邮件服务系统自动发出,请勿回复!";
+        public virtual string IpAddresError => "Ip地址输入异常,格式不正确";
+        public virtual string Send => "发送";
+        public virtual string Receive => "接收";
+
+        /***********************************************************************************
+         * 
+         *    系统相关的错误信息
+         * 
+         ************************************************************************************/
+
+        public virtual string SystemInstallOperater => "安装新系统:IP为";
+        public virtual string SystemUpdateOperater => "更新新系统:IP为";
+
+
+        /***********************************************************************************
+         * 
+         *    套接字相关的信息描述
+         * 
+         ************************************************************************************/
+
+        public virtual string SocketIOException => "套接字传送数据异常:";
+        public virtual string SocketSendException => "同步数据发送异常:";
+        public virtual string SocketHeadReceiveException => "指令头接收异常:";
+        public virtual string SocketContentReceiveException => "内容数据接收异常:";
+        public virtual string SocketContentRemoteReceiveException => "对方内容数据接收异常:";
+        public virtual string SocketAcceptCallbackException => "异步接受传入的连接尝试";
+        public virtual string SocketReAcceptCallbackException => "重新异步接受传入的连接尝试";
+        public virtual string SocketSendAsyncException => "异步数据发送出错:";
+        public virtual string SocketEndSendException => "异步数据结束挂起发送出错";
+        public virtual string SocketReceiveException => "异步数据发送出错:";
+        public virtual string SocketEndReceiveException => "异步数据结束接收指令头出错";
+        public virtual string SocketRemoteCloseException => "远程主机强迫关闭了一个现有的连接";
+
+
+        /***********************************************************************************
+         * 
+         *    文件相关的信息
+         * 
+         ************************************************************************************/
+
+
+        public virtual string FileDownloadSuccess => "文件下载成功";
+        public virtual string FileDownloadFailed => "文件下载异常";
+        public virtual string FileUploadFailed => "文件上传异常";
+        public virtual string FileUploadSuccess => "文件上传成功";
+        public virtual string FileDeleteFailed => "文件删除异常";
+        public virtual string FileDeleteSuccess => "文件删除成功";
+        public virtual string FileReceiveFailed => "确认文件接收异常";
+        public virtual string FileNotExist => "文件不存在";
+        public virtual string FileSaveFailed => "文件存储失败";
+        public virtual string FileLoadFailed => "文件加载失败";
+        public virtual string FileSendClientFailed => "文件发送的时候发生了异常";
+        public virtual string FileWriteToNetFailed => "文件写入网络异常";
+        public virtual string FileReadFromNetFailed => "从网络读取文件异常";
+        public virtual string FilePathCreateFailed => "文件夹路径创建失败:";
+        public virtual string FileRemoteNotExist => "对方文件不存在,无法接收!";
+
+        /***********************************************************************************
+         * 
+         *    服务器的引擎相关数据
+         * 
+         ************************************************************************************/
+
+        public virtual string TokenCheckFailed => "接收验证令牌不一致";
+        public virtual string TokenCheckTimeout => "接收验证超时:";
+        public virtual string CommandHeadCodeCheckFailed => "命令头校验失败";
+        public virtual string CommandLengthCheckFailed => "命令长度检查失败";
+        public virtual string NetClientAliasFailed => "客户端的别名接收失败:";
+        public virtual string NetClientAccountTimeout => "等待账户验证超时:";
+        public virtual string NetEngineStart => "启动引擎";
+        public virtual string NetEngineClose => "关闭引擎";
+        public virtual string NetClientOnline => "上线";
+        public virtual string NetClientOffline => "下线";
+        public virtual string NetClientBreak => "异常掉线";
+        public virtual string NetClientFull => "服务器承载上限,收到超出的请求连接。";
+        public virtual string NetClientLoginFailed => "客户端登录中错误:";
+        public virtual string NetHeartCheckFailed => "心跳验证异常:";
+        public virtual string NetHeartCheckTimeout => "心跳验证超时,强制下线:";
+        public virtual string DataSourseFormatError => "数据源格式不正确";
+        public virtual string ServerFileCheckFailed => "服务器确认文件失败,请重新上传";
+        public virtual string ClientOnlineInfo => "客户端 [ {0} ] 上线";
+        public virtual string ClientOfflineInfo => "客户端 [ {0} ] 下线";
+        public virtual string ClientDisableLogin => "客户端 [ {0} ] 不被信任,禁止登录";
+
+        /***********************************************************************************
+         * 
+         *    Client 相关
+         * 
+         ************************************************************************************/
+
+        public virtual string ReConnectServerSuccess => "重连服务器成功";
+        public virtual string ReConnectServerAfterTenSeconds => "在10秒后重新连接服务器";
+        public virtual string KeyIsNotAllowedNull => "关键字不允许为空";
+        public virtual string KeyIsExistAlready => "当前的关键字已经存在";
+        public virtual string KeyIsNotExist => "当前订阅的关键字不存在";
+        public virtual string ConnectingServer => "正在连接服务器...";
+        public virtual string ConnectFailedAndWait => "连接断开,等待{0}秒后重新连接";
+        public virtual string AttemptConnectServer => "正在尝试第{0}次连接服务器";
+        public virtual string ConnectServerSuccess => "连接服务器成功";
+        public virtual string GetClientIpaddressFailed => "客户端IP地址获取失败";
+        public virtual string ConnectionIsNotAvailable => "当前的连接不可用";
+        public virtual string DeviceCurrentIsLoginRepeat => "当前设备的id重复登录";
+        public virtual string DeviceCurrentIsLoginForbidden => "当前设备的id禁止登录";
+        public virtual string PasswordCheckFailed => "密码验证失败";
+        public virtual string DataTransformError => "数据转换失败,源数据:";
+        public virtual string RemoteClosedConnection => "远程关闭了连接";
+
+        /***********************************************************************************
+         * 
+         *    日志 相关
+         * 
+         ************************************************************************************/
+        public virtual string LogNetDebug => "调试";
+        public virtual string LogNetInfo => "信息";
+        public virtual string LogNetWarn => "警告";
+        public virtual string LogNetError => "错误";
+        public virtual string LogNetFatal => "致命";
+        public virtual string LogNetAbandon => "放弃";
+        public virtual string LogNetAll => "全部";
+
+        /***********************************************************************************
+         * 
+         *    Modbus相关
+         * 
+         ************************************************************************************/
+
+        public virtual string ModbusTcpFunctionCodeNotSupport => "不支持的功能码";
+        public virtual string ModbusTcpFunctionCodeOverBound => "读取的数据越界";
+        public virtual string ModbusTcpFunctionCodeQuantityOver => "读取长度超过最大值";
+        public virtual string ModbusTcpFunctionCodeReadWriteException => "读写异常";
+        public virtual string ModbusTcpReadCoilException => "读取线圈异常";
+        public virtual string ModbusTcpWriteCoilException => "写入线圈异常";
+        public virtual string ModbusTcpReadRegisterException => "读取寄存器异常";
+        public virtual string ModbusTcpWriteRegisterException => "写入寄存器异常";
+        public virtual string ModbusAddressMustMoreThanOne => "地址值在起始地址为1的情况下,必须大于1";
+        public virtual string ModbusAsciiFormatCheckFailed => "Modbus的ascii指令检查失败,不是modbus-ascii报文";
+        public virtual string ModbusCRCCheckFailed => "Modbus的CRC校验检查失败";
+        public virtual string ModbusLRCCheckFailed => "Modbus的LRC校验检查失败";
+        public virtual string ModbusMatchFailed => "不是标准的modbus协议";
+
+
+        /***********************************************************************************
+         * 
+         *    Melsec PLC 相关
+         * 
+         ************************************************************************************/
+        public virtual string MelsecPleaseReferToManulDocument => "请查看三菱的通讯手册来查看报警的具体信息";
+        public virtual string MelsecReadBitInfo => "读取位变量数组只能针对位软元件,如果读取字软元件,请调用Read方法";
+        public virtual string MelsecCurrentTypeNotSupportedWordOperate => "当前的类型不支持字读写";
+        public virtual string MelsecCurrentTypeNotSupportedBitOperate => "当前的类型不支持位读写";
+        public virtual string MelsecFxReceiveZore => "接收的数据长度为0";
+        public virtual string MelsecFxAckNagative => "PLC反馈的数据无效";
+        public virtual string MelsecFxAckWrong => "PLC反馈信号错误:";
+        public virtual string MelsecFxCrcCheckFailed => "PLC反馈报文的和校验失败!";
+
+        /***********************************************************************************
+         * 
+         *    Siemens PLC 相关
+         * 
+         ************************************************************************************/
+
+        public virtual string SiemensDBAddressNotAllowedLargerThan255 => "DB块数据无法大于255";
+        public virtual string SiemensReadLengthMustBeEvenNumber => "读取的数据长度必须为偶数";
+        public virtual string SiemensWriteError => "写入数据异常,代号为:";
+        public virtual string SiemensReadLengthCannotLargerThan19 => "读取的数组数量不允许大于19";
+        public virtual string SiemensDataLengthCheckFailed => "数据块长度校验失败,请检查是否开启put/get以及关闭db块优化";
+        public virtual string SiemensFWError => "发生了异常,具体信息查找Fetch/Write协议文档";
+        public virtual string SiemensReadLengthOverPlcAssign => "读取的数据范围超出了PLC的设定";
+
+        /***********************************************************************************
+         * 
+         *    Omron PLC 相关
+         * 
+         ************************************************************************************/
+
+        public virtual string OmronAddressMustBeZeroToFiveteen => "输入的位地址只能在0-15之间";
+        public virtual string OmronReceiveDataError => "数据接收异常";
+        public virtual string OmronStatus0 => "通讯正常";
+        public virtual string OmronStatus1 => "消息头不是FINS";
+        public virtual string OmronStatus2 => "数据长度太长";
+        public virtual string OmronStatus3 => "该命令不支持";
+        public virtual string OmronStatus20 => "超过连接上限";
+        public virtual string OmronStatus21 => "指定的节点已经处于连接中";
+        public virtual string OmronStatus22 => "尝试去连接一个受保护的网络节点,该节点还未配置到PLC中";
+        public virtual string OmronStatus23 => "当前客户端的网络节点超过正常范围";
+        public virtual string OmronStatus24 => "当前客户端的网络节点已经被使用";
+        public virtual string OmronStatus25 => "所有的网络节点已经被使用";
+
+
+
+        /***********************************************************************************
+         * 
+         *    AB PLC 相关
+         * 
+         ************************************************************************************/
+
+
+        public virtual string AllenBradley04 => "它没有正确生成或匹配标记不存在。";
+        public virtual string AllenBradley05 => "引用的特定项(通常是实例)无法找到。";
+        public virtual string AllenBradley06 => "请求的数据量不适合响应缓冲区。 发生了部分数据传输。";
+        public virtual string AllenBradley0A => "尝试处理其中一个属性时发生错误。";
+        public virtual string AllenBradley13 => "命令中没有提供足够的命令数据/参数来执行所请求的服务。";
+        public virtual string AllenBradley1C => "与属性计数相比,提供的属性数量不足。";
+        public virtual string AllenBradley1E => "此服务中的服务请求出错。";
+        public virtual string AllenBradley26 => "IOI字长与处理的IOI数量不匹配。";
+
+        public virtual string AllenBradleySessionStatus00 => "成功";
+        public virtual string AllenBradleySessionStatus01 => "发件人发出无效或不受支持的封装命令。";
+        public virtual string AllenBradleySessionStatus02 => "接收器中的内存资源不足以处理命令。 这不是一个应用程序错误。 相反,只有在封装层无法获得所需内存资源的情况下才会导致此问题。";
+        public virtual string AllenBradleySessionStatus03 => "封装消息的数据部分中的数据形成不良或不正确。";
+        public virtual string AllenBradleySessionStatus64 => "向目标发送封装消息时,始发者使用了无效的会话句柄。";
+        public virtual string AllenBradleySessionStatus65 => "目标收到一个无效长度的信息。";
+        public virtual string AllenBradleySessionStatus69 => "不支持的封装协议修订。";
+
+        /***********************************************************************************
+         * 
+         *    Panasonic PLC 相关
+         * 
+         ************************************************************************************/
+        public virtual string PanasonicReceiveLengthMustLargerThan9 => "接收数据长度必须大于9";
+        public virtual string PanasonicAddressParameterCannotBeNull => "地址参数不允许为空";
+        public virtual string PanasonicMewStatus20 => "错误未知";
+        public virtual string PanasonicMewStatus21 => "NACK错误,远程单元无法被正确识别,或者发生了数据错误。";
+        public virtual string PanasonicMewStatus22 => "WACK 错误:用于远程单元的接收缓冲区已满。";
+        public virtual string PanasonicMewStatus23 => "多重端口错误:远程单元编号(01 至 16)设置与本地单元重复。";
+        public virtual string PanasonicMewStatus24 => "传输格式错误:试图发送不符合传输格式的数据,或者某一帧数据溢出或发生了数据错误。";
+        public virtual string PanasonicMewStatus25 => "硬件错误:传输系统硬件停止操作。";
+        public virtual string PanasonicMewStatus26 => "单元号错误:远程单元的编号设置超出 01 至 63 的范围。";
+        public virtual string PanasonicMewStatus27 => "不支持错误:接收方数据帧溢出. 试图在不同的模块之间发送不同帧长度的数据。";
+        public virtual string PanasonicMewStatus28 => "无应答错误:远程单元不存在. (超时)。";
+        public virtual string PanasonicMewStatus29 => "缓冲区关闭错误:试图发送或接收处于关闭状态的缓冲区。";
+        public virtual string PanasonicMewStatus30 => "超时错误:持续处于传输禁止状态。";
+        public virtual string PanasonicMewStatus40 => "BCC 错误:在指令数据中发生传输错误。";
+        public virtual string PanasonicMewStatus41 => "格式错误:所发送的指令信息不符合传输格式。";
+        public virtual string PanasonicMewStatus42 => "不支持错误:发送了一个未被支持的指令。向未被支持的目标站发送了指令。";
+        public virtual string PanasonicMewStatus43 => "处理步骤错误:在处于传输请求信息挂起时,发送了其他指令。";
+        public virtual string PanasonicMewStatus50 => "链接设置错误:设置了实际不存在的链接编号。";
+        public virtual string PanasonicMewStatus51 => "同时操作错误:当向其他单元发出指令时,本地单元的传输缓冲区已满。";
+        public virtual string PanasonicMewStatus52 => "传输禁止错误:无法向其他单元传输。";
+        public virtual string PanasonicMewStatus53 => "忙错误:在接收到指令时,正在处理其他指令。";
+        public virtual string PanasonicMewStatus60 => "参数错误:在指令中包含有无法使用的代码,或者代码没有附带区域指定参数(X, Y, D), 等以外。";
+        public virtual string PanasonicMewStatus61 => "数据错误:触点编号,区域编号,数据代码格式(BCD,hex,等)上溢出, 下溢出以及区域指定错误。";
+        public virtual string PanasonicMewStatus62 => "寄存器错误:过多记录数据在未记录状态下的操作(监控记录、跟踪记录等。)。";
+        public virtual string PanasonicMewStatus63 => "PLC 模式错误:当一条指令发出时,运行模式不能够对指令进行处理。";
+        public virtual string PanasonicMewStatus65 => "保护错误:在存储保护状态下执行写操作到程序区域或系统寄存器。";
+        public virtual string PanasonicMewStatus66 => "地址错误:地址(程序地址、绝对地址等)数据编码形式(BCD、hex 等)、上溢、下溢或指定范围错误。";
+        public virtual string PanasonicMewStatus67 => "丢失数据错误:要读的数据不存在。(读取没有写入注释寄存区的数据。。";
+
+
+        /***********************************************************************************
+         * 
+         *   Fatek PLC 永宏PLC相关
+         * 
+         ************************************************************************************/
+        public virtual string FatekStatus02 => "不合法数值";
+        public virtual string FatekStatus03 => "禁止写入";
+        public virtual string FatekStatus04 => "不合法的命令码";
+        public virtual string FatekStatus05 => "不能激活(下RUN命令但Ladder Checksum不合)";
+        public virtual string FatekStatus06 => "不能激活(下RUN命令但PLC ID≠ Ladder ID)";
+        public virtual string FatekStatus07 => "不能激活(下RUN命令但程序语法错误)";
+        public virtual string FatekStatus09 => "不能激活(下RUN命令,但Ladder之程序指令PLC无法执行)";
+        public virtual string FatekStatus10 => "不合法的地址";
+
+
+        /***********************************************************************************
+         * 
+         *   Fuji PLC 富士PLC相关
+         * 
+         ************************************************************************************/
+        public virtual string FujiSpbStatus01 => "对ROM进行了写入";
+        public virtual string FujiSpbStatus02 => "接收了未定义的命令或无法处理的命令";
+        public virtual string FujiSpbStatus03 => "数据部分有矛盾(参数异常)";
+        public virtual string FujiSpbStatus04 => "由于收到了其他编程器的传送联锁,因此无法处理";
+        public virtual string FujiSpbStatus05 => "模块序号不正确";
+        public virtual string FujiSpbStatus06 => "检索项目未找到";
+        public virtual string FujiSpbStatus07 => "指定了超出模块范围的地址(写入时)";
+        public virtual string FujiSpbStatus09 => "由于故障程序无法执行(RUN)";
+        public virtual string FujiSpbStatus0C => "密码不一致";
+    }
+}

+ 32 - 0
BlankApp1/TFT-MelsecMcNet/DeviceAddressDataBase.cs

@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TFT_MelsecMcNet
+{
+    /// <summary>
+    /// 设备地址数据的信息,通常包含起始地址,数据类型,长度
+    /// </summary>
+    public class DeviceAddressDataBase
+    {
+        /// <summary>
+        /// 数字的起始地址,也就是偏移地址
+        /// </summary>
+        public int AddressStart { get; set; }
+
+        /// <summary>
+        /// 读取的数据长度
+        /// </summary>
+        public ushort Length { get; set; }
+
+        /// <summary>
+        /// 从指定的地址信息解析成真正的设备地址信息
+        /// </summary>
+        /// <param name="address">地址信息</param>
+        /// <param name="length">数据长度</param>
+        public virtual void Parse(string address, ushort length)
+        {
+
+        }
+    }
+}

+ 325 - 0
BlankApp1/TFT-MelsecMcNet/English.cs

@@ -0,0 +1,325 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TFT_MelsecMcNet
+{
+    /// <summary>
+    /// English Version Text
+    /// </summary>
+    public class English : DefaultLanguage
+    {
+        /***********************************************************************************
+         * 
+         *    Normal Info
+         * 
+         ************************************************************************************/
+
+        public override string AuthorizationFailed => "System authorization failed, need to use activation code authorization, thank you for your support.";
+        public override string ConnectedFailed => "Connected Failed: ";
+        public override string ConnectedSuccess => "Connect Success !";
+        public override string UnknownError => "Unknown Error";
+        public override string ErrorCode => "Error Code: ";
+        public override string TextDescription => "Description: ";
+        public override string ExceptionMessage => "Exception Info: ";
+        public override string ExceptionSourse => "Exception Sourse:";
+        public override string ExceptionType => "Exception Type:";
+        public override string ExceptionStackTrace => "Exception Stack: ";
+        public override string ExceptopnTargetSite => "Exception Method: ";
+        public override string ExceprionCustomer => "Error in user-defined method: ";
+        public override string SuccessText => "Success";
+        public override string TwoParametersLengthIsNotSame => "Two Parameter Length is not same";
+        public override string NotSupportedDataType => "Unsupported DataType, input again";
+        public override string NotSupportedFunction => "The current feature logic does not support";
+        public override string DataLengthIsNotEnough => "Receive length is not enough,Should:{0},Actual:{1}";
+        public override string ReceiveDataTimeout => "Receive timeout: ";
+        public override string ReceiveDataLengthTooShort => "Receive length is too short: ";
+        public override string MessageTip => "Message prompt:";
+        public override string Close => "Close";
+        public override string Time => "Time:";
+        public override string SoftWare => "Software:";
+        public override string BugSubmit => "Bug submit";
+        public override string MailServerCenter => "Mail Center System";
+        public override string MailSendTail => "Mail Service system issued automatically, do not reply";
+        public override string IpAddresError => "IP address input exception, format is incorrect";
+        public override string Send => "Send";
+        public override string Receive => "Receive";
+
+        /***********************************************************************************
+         * 
+         *    System about
+         * 
+         ************************************************************************************/
+
+        public override string SystemInstallOperater => "Install new software: ip address is";
+        public override string SystemUpdateOperater => "Update software: ip address is";
+
+
+        /***********************************************************************************
+         * 
+         *    Socket-related Information description
+         * 
+         ************************************************************************************/
+
+        public override string SocketIOException => "Socket transport error: ";
+        public override string SocketSendException => "Synchronous Data Send exception: ";
+        public override string SocketHeadReceiveException => "Command header receive exception: ";
+        public override string SocketContentReceiveException => "Content Data Receive exception: ";
+        public override string NetClientAccountTimeout => "Wait for account check timeout:";
+        public override string SocketContentRemoteReceiveException => "Recipient content Data Receive exception: ";
+        public override string SocketAcceptCallbackException => "Asynchronously accepts an incoming connection attempt: ";
+        public override string SocketReAcceptCallbackException => "To re-accept incoming connection attempts asynchronously";
+        public override string SocketSendAsyncException => "Asynchronous Data send Error: ";
+        public override string SocketEndSendException => "Asynchronous data end callback send Error";
+        public override string SocketReceiveException => "Asynchronous Data send Error: ";
+        public override string SocketEndReceiveException => "Asynchronous data end receive instruction header error";
+        public override string SocketRemoteCloseException => "An existing connection was forcibly closed by the remote host";
+
+
+        /***********************************************************************************
+         * 
+         *    File related information
+         * 
+         ************************************************************************************/
+
+
+        public override string FileDownloadSuccess => "File Download Successful";
+        public override string FileDownloadFailed => "File Download exception";
+        public override string FileUploadFailed => "File Upload exception";
+        public override string FileUploadSuccess => "File Upload Successful";
+        public override string FileDeleteFailed => "File Delete exception";
+        public override string FileDeleteSuccess => "File deletion succeeded";
+        public override string FileReceiveFailed => "Confirm File Receive exception";
+        public override string FileNotExist => "File does not exist";
+        public override string FileSaveFailed => "File Store failed";
+        public override string FileLoadFailed => "File load failed";
+        public override string FileSendClientFailed => "An exception occurred when the file was sent";
+        public override string FileWriteToNetFailed => "File Write Network exception";
+        public override string FileReadFromNetFailed => "Read file exceptions from the network";
+        public override string FilePathCreateFailed => "Folder path creation failed: ";
+        public override string FileRemoteNotExist => "The other file does not exist, cannot receive!";
+
+        /***********************************************************************************
+         * 
+         *    Engine-related data for the server
+         * 
+         ************************************************************************************/
+
+        public override string TokenCheckFailed => "Receive authentication token inconsistency";
+        public override string TokenCheckTimeout => "Receive authentication timeout: ";
+        public override string CommandHeadCodeCheckFailed => "Command header check failed";
+        public override string CommandLengthCheckFailed => "Command length check failed";
+        public override string NetClientAliasFailed => "Client's alias receive failed: ";
+        public override string NetEngineStart => "Start engine";
+        public override string NetEngineClose => "Shutting down the engine";
+        public override string NetClientOnline => "Online";
+        public override string NetClientOffline => "Offline";
+        public override string NetClientBreak => "Abnormal offline";
+        public override string NetClientFull => "The server hosts the upper limit and receives an exceeded request connection.";
+        public override string NetClientLoginFailed => "Error in Client logon: ";
+        public override string NetHeartCheckFailed => "Heartbeat Validation exception: ";
+        public override string NetHeartCheckTimeout => "Heartbeat verification timeout, force offline: ";
+        public override string DataSourseFormatError => "Data source format is incorrect";
+        public override string ServerFileCheckFailed => "Server confirmed file failed, please re-upload";
+        public override string ClientOnlineInfo => "Client [ {0} ] Online";
+        public override string ClientOfflineInfo => "Client [ {0} ] Offline";
+        public override string ClientDisableLogin => "Client [ {0} ] is not trusted, login forbidden";
+
+        /***********************************************************************************
+         * 
+         *    Client related
+         * 
+         ************************************************************************************/
+
+        public override string ReConnectServerSuccess => "Re-connect server succeeded";
+        public override string ReConnectServerAfterTenSeconds => "Reconnect the server after 10 seconds";
+        public override string KeyIsNotAllowedNull => "The keyword is not allowed to be empty";
+        public override string KeyIsExistAlready => "The current keyword already exists";
+        public override string KeyIsNotExist => "The keyword for the current subscription does not exist";
+        public override string ConnectingServer => "Connecting to Server...";
+        public override string ConnectFailedAndWait => "Connection disconnected, wait {0} seconds to reconnect";
+        public override string AttemptConnectServer => "Attempting to connect server {0} times";
+        public override string ConnectServerSuccess => "Connection Server succeeded";
+        public override string GetClientIpaddressFailed => "Client IP Address acquisition failed";
+        public override string ConnectionIsNotAvailable => "The current connection is not available";
+        public override string DeviceCurrentIsLoginRepeat => "ID of the current device duplicate login";
+        public override string DeviceCurrentIsLoginForbidden => "The ID of the current device prohibits login";
+        public override string PasswordCheckFailed => "Password validation failed";
+        public override string DataTransformError => "Data conversion failed, source data: ";
+        public override string RemoteClosedConnection => "Remote shutdown of connection";
+
+        /***********************************************************************************
+         * 
+         *    Log related
+         * 
+         ************************************************************************************/
+        public override string LogNetDebug => "Debug";
+        public override string LogNetInfo => "Info";
+        public override string LogNetWarn => "Warn";
+        public override string LogNetError => "Error";
+        public override string LogNetFatal => "Fatal";
+        public override string LogNetAbandon => "Abandon";
+        public override string LogNetAll => "All";
+
+
+        /***********************************************************************************
+         * 
+         *    Modbus related
+         * 
+         ************************************************************************************/
+
+        public override string ModbusTcpFunctionCodeNotSupport => "Unsupported function code";
+        public override string ModbusTcpFunctionCodeOverBound => "Data read out of bounds";
+        public override string ModbusTcpFunctionCodeQuantityOver => "Read length exceeds maximum value";
+        public override string ModbusTcpFunctionCodeReadWriteException => "Read and Write exceptions";
+        public override string ModbusTcpReadCoilException => "Read Coil anomalies";
+        public override string ModbusTcpWriteCoilException => "Write Coil exception";
+        public override string ModbusTcpReadRegisterException => "Read Register exception";
+        public override string ModbusTcpWriteRegisterException => "Write Register exception";
+        public override string ModbusAddressMustMoreThanOne => "The address value must be greater than 1 in the case where the start address is 1";
+        public override string ModbusAsciiFormatCheckFailed => "Modbus ASCII command check failed, not MODBUS-ASCII message";
+        public override string ModbusCRCCheckFailed => "The CRC checksum check failed for Modbus";
+        public override string ModbusLRCCheckFailed => "The LRC checksum check failed for Modbus";
+        public override string ModbusMatchFailed => "Not the standard Modbus protocol";
+
+
+        /***********************************************************************************
+         * 
+         *    Melsec PLC related
+         * 
+         ************************************************************************************/
+        public override string MelsecPleaseReferToManulDocument => "Please check Mitsubishi's communication manual for details of the alarm.";
+        public override string MelsecReadBitInfo => "The read bit variable array can only be used for bit soft elements, if you read the word soft component, call the Read method";
+        public override string MelsecCurrentTypeNotSupportedWordOperate => "The current type does not support word read and write";
+        public override string MelsecCurrentTypeNotSupportedBitOperate => "The current type does not support bit read and write";
+        public override string MelsecFxReceiveZore => "The received data length is 0";
+        public override string MelsecFxAckNagative => "Invalid data from PLC feedback";
+        public override string MelsecFxAckWrong => "PLC Feedback Signal Error: ";
+        public override string MelsecFxCrcCheckFailed => "PLC Feedback message and check failed!";
+
+        /***********************************************************************************
+         * 
+         *    Siemens PLC related
+         * 
+         ************************************************************************************/
+
+        public override string SiemensDBAddressNotAllowedLargerThan255 => "DB block data cannot be greater than 255";
+        public override string SiemensReadLengthMustBeEvenNumber => "The length of the data read must be an even number";
+        public override string SiemensWriteError => "Writes the data exception, the code name is: ";
+        public override string SiemensReadLengthCannotLargerThan19 => "The number of arrays read does not allow greater than 19";
+        public override string SiemensDataLengthCheckFailed => "Block length checksum failed, please check if Put/get is turned on and DB block optimization is turned off";
+        public override string SiemensFWError => "An exception occurred, the specific information to find the Fetch/write protocol document";
+        public override string SiemensReadLengthOverPlcAssign => "The range of data read exceeds the setting of the PLC";
+
+        /***********************************************************************************
+         * 
+         *    Omron PLC related
+         * 
+         ************************************************************************************/
+
+        public override string OmronAddressMustBeZeroToFiveteen => "The bit address entered can only be between 0-15";
+        public override string OmronReceiveDataError => "Data Receive exception";
+        public override string OmronStatus0 => "Communication is normal.";
+        public override string OmronStatus1 => "The message header is not fins";
+        public override string OmronStatus2 => "Data length too long";
+        public override string OmronStatus3 => "This command does not support";
+        public override string OmronStatus20 => "Exceeding connection limit";
+        public override string OmronStatus21 => "The specified node is already in the connection";
+        public override string OmronStatus22 => "Attempt to connect to a protected network node that is not yet configured in the PLC";
+        public override string OmronStatus23 => "The current client's network node exceeds the normal range";
+        public override string OmronStatus24 => "The current client's network node is already in use";
+        public override string OmronStatus25 => "All network nodes are already in use";
+
+
+
+        /***********************************************************************************
+         * 
+         *    AB PLC related
+         * 
+         ************************************************************************************/
+
+
+        public override string AllenBradley04 => "The IOI could not be deciphered. Either it was not formed correctly or the match tag does not exist.";
+        public override string AllenBradley05 => "The particular item referenced (usually instance) could not be found.";
+        public override string AllenBradley06 => "The amount of data requested would not fit into the response buffer. Partial data transfer has occurred.";
+        public override string AllenBradley0A => "An error has occurred trying to process one of the attributes.";
+        public override string AllenBradley13 => "Not enough command data / parameters were supplied in the command to execute the service requested.";
+        public override string AllenBradley1C => "An insufficient number of attributes were provided compared to the attribute count.";
+        public override string AllenBradley1E => "A service request in this service went wrong.";
+        public override string AllenBradley26 => "The IOI word length did not match the amount of IOI which was processed.";
+
+        public override string AllenBradleySessionStatus00 => "success";
+        public override string AllenBradleySessionStatus01 => "The sender issued an invalid or unsupported encapsulation command.";
+        public override string AllenBradleySessionStatus02 => "Insufficient memory resources in the receiver to handle the command. This is not an application error. Instead, it only results if the encapsulation layer cannot obtain memory resources that it need.";
+        public override string AllenBradleySessionStatus03 => "Poorly formed or incorrect data in the data portion of the encapsulation message.";
+        public override string AllenBradleySessionStatus64 => "An originator used an invalid session handle when sending an encapsulation message.";
+        public override string AllenBradleySessionStatus65 => "The target received a message of invalid length.";
+        public override string AllenBradleySessionStatus69 => "Unsupported encapsulation protocol revision.";
+
+        /***********************************************************************************
+         * 
+         *    Panasonic PLC related
+         * 
+         ************************************************************************************/
+        public override string PanasonicReceiveLengthMustLargerThan9 => "The received data length must be greater than 9";
+        public override string PanasonicAddressParameterCannotBeNull => "Address parameter is not allowed to be empty";
+        public override string PanasonicMewStatus20 => "Error unknown";
+        public override string PanasonicMewStatus21 => "Nack error, the remote unit could not be correctly identified, or a data error occurred.";
+        public override string PanasonicMewStatus22 => "WACK Error: The receive buffer for the remote unit is full.";
+        public override string PanasonicMewStatus23 => "Multiple port error: The remote unit number (01 to 16) is set to repeat with the local unit.";
+        public override string PanasonicMewStatus24 => "Transport format error: An attempt was made to send data that does not conform to the transport format, or a frame data overflow or a data error occurred.";
+        public override string PanasonicMewStatus25 => "Hardware error: Transport system hardware stopped operation.";
+        public override string PanasonicMewStatus26 => "Unit Number error: The remote unit's numbering setting exceeds the range of 01 to 63.";
+        public override string PanasonicMewStatus27 => "Error not supported: Receiver data frame overflow. An attempt was made to send data of different frame lengths between different modules.";
+        public override string PanasonicMewStatus28 => "No answer error: The remote unit does not exist. (timeout).";
+        public override string PanasonicMewStatus29 => "Buffer Close error: An attempt was made to send or receive a buffer that is in a closed state.";
+        public override string PanasonicMewStatus30 => "Timeout error: Persisted in transport forbidden State.";
+        public override string PanasonicMewStatus40 => "BCC Error: A transmission error occurred in the instruction data.";
+        public override string PanasonicMewStatus41 => "Malformed: The sent instruction information does not conform to the transmission format.";
+        public override string PanasonicMewStatus42 => "Error not supported: An unsupported instruction was sent. An instruction was sent to a target station that was not supported.";
+        public override string PanasonicMewStatus43 => "Processing Step Error: Additional instructions were sent when the transfer request information was suspended.";
+        public override string PanasonicMewStatus50 => "Link Settings Error: A link number that does not actually exist is set.";
+        public override string PanasonicMewStatus51 => "Simultaneous operation error: When issuing instructions to other units, the transmit buffer for the local unit is full.";
+        public override string PanasonicMewStatus52 => "Transport suppression Error: Unable to transfer to other units.";
+        public override string PanasonicMewStatus53 => "Busy error: Other instructions are being processed when the command is received.";
+        public override string PanasonicMewStatus60 => "Parameter error: Contains code that cannot be used in the directive, or the code does not have a zone specified parameter (X, Y, D), and so on.";
+        public override string PanasonicMewStatus61 => "Data error: Contact number, area number, Data code format (BCD,HEX, etc.) overflow, overflow, and area specified error.";
+        public override string PanasonicMewStatus62 => "Register ERROR: Excessive logging of data in an unregistered state of operations (Monitoring records, tracking records, etc.). )。";
+        public override string PanasonicMewStatus63 => "PLC mode error: When an instruction is issued, the run mode is not able to process the instruction.";
+        public override string PanasonicMewStatus65 => "Protection Error: Performs a write operation to the program area or system register in the storage protection state.";
+        public override string PanasonicMewStatus66 => "Address Error: Address (program address, absolute address, etc.) Data encoding form (BCD, hex, etc.), overflow, underflow, or specified range error.";
+        public override string PanasonicMewStatus67 => "Missing data error: The data to be read does not exist. (reads data that is not written to the comment register.)";
+
+
+        /***********************************************************************************
+         * 
+         *   Fatek PLC 永宏PLC相关
+         * 
+         ************************************************************************************/
+        public override string FatekStatus02 => "Illegal value";
+        public override string FatekStatus03 => "Write disabled";
+        public override string FatekStatus04 => "Invalid command code";
+        public override string FatekStatus05 => "Cannot be activated (down RUN command but Ladder Checksum does not match)";
+        public override string FatekStatus06 => "Cannot be activated (down RUN command but PLC ID ≠ Ladder ID)";
+        public override string FatekStatus07 => "Cannot be activated (down RUN command but program syntax error)";
+        public override string FatekStatus09 => "Cannot be activated (down RUN command, but the ladder program command PLC cannot be executed)";
+        public override string FatekStatus10 => "Illegal address";
+
+
+
+        /***********************************************************************************
+         * 
+         *   Fuji PLC 富士PLC相关
+         * 
+         ************************************************************************************/
+        public override string FujiSpbStatus01 => "Write to the ROM";
+        public override string FujiSpbStatus02 => "Received undefined commands or commands that could not be processed";
+        public override string FujiSpbStatus03 => "There is a contradiction in the data part (parameter exception)";
+        public override string FujiSpbStatus04 => "Unable to process due to transfer interlocks from other programmers";
+        public override string FujiSpbStatus05 => "The module number is incorrect";
+        public override string FujiSpbStatus06 => "Search item not found";
+        public override string FujiSpbStatus07 => "An address that exceeds the module range (when writing) is specified";
+        public override string FujiSpbStatus09 => "Unable to execute due to faulty program (RUN)";
+        public override string FujiSpbStatus0C => "Inconsistent password";
+    }
+}

+ 53 - 0
BlankApp1/TFT-MelsecMcNet/INetMessage.cs

@@ -0,0 +1,53 @@
+namespace TFT_MelsecMcNet
+{
+    /// <summary>
+    /// 本系统的消息类,包含了各种解析规则,数据信息提取规则
+    /// </summary>
+    public interface INetMessage
+    {
+        /// <summary>
+        /// 消息头的指令长度
+        /// </summary>
+        int ProtocolHeadBytesLength { get; }
+
+
+        /// <summary>
+        /// 从当前的头子节文件中提取出接下来需要接收的数据长度
+        /// </summary>
+        /// <returns>返回接下来的数据内容长度</returns>
+        int GetContentLengthByHeadBytes();
+
+
+        /// <summary>
+        /// 检查头子节的合法性
+        /// </summary>
+        /// <param name="token">特殊的令牌,有些特殊消息的验证</param>
+        /// <returns>是否成功的结果</returns>
+        bool CheckHeadBytesLegal(byte[] token);
+
+
+        /// <summary>
+        /// 获取头子节里的消息标识
+        /// </summary>
+        /// <returns>消息标识</returns>
+        int GetHeadBytesIdentity();
+
+
+        /// <summary>
+        /// 消息头字节
+        /// </summary>
+        byte[] HeadBytes { get; set; }
+
+
+        /// <summary>
+        /// 消息内容字节
+        /// </summary>
+        byte[] ContentBytes { get; set; }
+
+
+        /// <summary>
+        /// 发送的字节信息
+        /// </summary>
+        byte[] SendBytes { get; set; }
+    }
+}

+ 542 - 0
BlankApp1/TFT-MelsecMcNet/McAddressData.cs

@@ -0,0 +1,542 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TFT_MelsecMcNet
+{
+    /// <summary>
+    /// 三菱的数据地址表示形式
+    /// </summary>
+    public class McAddressData : DeviceAddressDataBase
+    {
+        #region Constructor
+
+        /// <summary>
+        /// 实例化一个默认的对象
+        /// </summary>
+        public McAddressData()
+        {
+            McDataType = MelsecMcDataType.D;
+        }
+
+        #endregion
+
+        /// <summary>
+        /// 三菱的数据地址信息
+        /// </summary>
+        public MelsecMcDataType McDataType { get; set; }
+
+        /// <summary>
+        /// 从指定的地址信息解析成真正的设备地址信息,默认是三菱的地址
+        /// </summary>
+        /// <param name="address">地址信息</param>
+        /// <param name="length">数据长度</param>
+        public override void Parse(string address, ushort length)
+        {
+            OperateResult<McAddressData> addressData = ParseMelsecFrom(address, length);
+            if (addressData.IsSuccess)
+            {
+                AddressStart = addressData.Content.AddressStart;
+                Length = addressData.Content.Length;
+                McDataType = addressData.Content.McDataType;
+            }
+        }
+
+        #region Static Method
+
+        /// <summary>
+        /// 从实际三菱的地址里面解析出
+        /// </summary>
+        /// <param name="address">三菱的地址数据信息</param>
+        /// <param name="length">读取的数据长度</param>
+        /// <returns>是否成功的结果对象</returns>
+        public static OperateResult<McAddressData> ParseMelsecFrom(string address, ushort length)
+        {
+            McAddressData addressData = new McAddressData
+            {
+                Length = length
+            };
+            try
+            {
+                switch (address[0])
+                {
+                    case 'M':
+                    case 'm':
+                        {
+                            addressData.McDataType = MelsecMcDataType.M;
+                            addressData.AddressStart = Convert.ToInt32(address.Substring(1), MelsecMcDataType.M.FromBase);
+                            break;
+                        }
+                    case 'X':
+                    case 'x':
+                        {
+                            addressData.McDataType = MelsecMcDataType.X;
+                            addressData.AddressStart = Convert.ToInt32(address.Substring(1), MelsecMcDataType.X.FromBase);
+                            break;
+                        }
+                    case 'Y':
+                    case 'y':
+                        {
+                            addressData.McDataType = MelsecMcDataType.Y;
+                            addressData.AddressStart = Convert.ToInt32(address.Substring(1), MelsecMcDataType.Y.FromBase);
+                            break;
+                        }
+                    case 'D':
+                    case 'd':
+                        {
+                            addressData.McDataType = MelsecMcDataType.D;
+                            addressData.AddressStart = Convert.ToInt32(address.Substring(1), MelsecMcDataType.D.FromBase);
+                            break;
+                        }
+                    case 'W':
+                    case 'w':
+                        {
+                            addressData.McDataType = MelsecMcDataType.W;
+                            addressData.AddressStart = Convert.ToInt32(address.Substring(1), MelsecMcDataType.W.FromBase);
+                            break;
+                        }
+                    case 'L':
+                    case 'l':
+                        {
+                            addressData.McDataType = MelsecMcDataType.L;
+                            addressData.AddressStart = Convert.ToInt32(address.Substring(1), MelsecMcDataType.L.FromBase);
+                            break;
+                        }
+                    case 'F':
+                    case 'f':
+                        {
+                            addressData.McDataType = MelsecMcDataType.F;
+                            addressData.AddressStart = Convert.ToInt32(address.Substring(1), MelsecMcDataType.F.FromBase);
+                            break;
+                        }
+                    case 'V':
+                    case 'v':
+                        {
+                            addressData.McDataType = MelsecMcDataType.V;
+                            addressData.AddressStart = Convert.ToInt32(address.Substring(1), MelsecMcDataType.V.FromBase);
+                            break;
+                        }
+                    case 'B':
+                    case 'b':
+                        {
+                            addressData.McDataType = MelsecMcDataType.B;
+                            addressData.AddressStart = Convert.ToInt32(address.Substring(1), MelsecMcDataType.B.FromBase);
+                            break;
+                        }
+                    case 'R':
+                    case 'r':
+                        {
+                            addressData.McDataType = MelsecMcDataType.R;
+                            addressData.AddressStart = Convert.ToInt32(address.Substring(1), MelsecMcDataType.R.FromBase);
+                            break;
+                        }
+                    case 'S':
+                    case 's':
+                        {
+                            if (address[1] == 'N' || address[1] == 'n')
+                            {
+                                addressData.McDataType = MelsecMcDataType.SN;
+                                addressData.AddressStart = Convert.ToInt32(address.Substring(2), MelsecMcDataType.SN.FromBase);
+                                break;
+                            }
+                            else if (address[1] == 'S' || address[1] == 's')
+                            {
+                                addressData.McDataType = MelsecMcDataType.SS;
+                                addressData.AddressStart = Convert.ToInt32(address.Substring(2), MelsecMcDataType.SS.FromBase);
+                                break;
+                            }
+                            else if (address[1] == 'C' || address[1] == 'c')
+                            {
+                                addressData.McDataType = MelsecMcDataType.SC;
+                                addressData.AddressStart = Convert.ToInt32(address.Substring(2), MelsecMcDataType.SC.FromBase);
+                                break;
+                            }
+                            else
+                            {
+                                addressData.McDataType = MelsecMcDataType.S;
+                                addressData.AddressStart = Convert.ToInt32(address.Substring(1), MelsecMcDataType.S.FromBase);
+                                break;
+                            }
+                        }
+                    case 'Z':
+                    case 'z':
+                        {
+                            if (address.StartsWith("ZR") || address.StartsWith("zr"))
+                            {
+                                addressData.McDataType = MelsecMcDataType.ZR;
+                                addressData.AddressStart = Convert.ToInt32(address.Substring(2), MelsecMcDataType.ZR.FromBase);
+                                break;
+                            }
+                            else
+                            {
+                                addressData.McDataType = MelsecMcDataType.Z;
+                                addressData.AddressStart = Convert.ToInt32(address.Substring(1), MelsecMcDataType.Z.FromBase);
+                                break;
+                            }
+                        }
+                    case 'T':
+                    case 't':
+                        {
+                            if (address[1] == 'N' || address[1] == 'n')
+                            {
+                                addressData.McDataType = MelsecMcDataType.TN;
+                                addressData.AddressStart = Convert.ToInt32(address.Substring(2), MelsecMcDataType.TN.FromBase);
+                                break;
+                            }
+                            else if (address[1] == 'S' || address[1] == 's')
+                            {
+                                addressData.McDataType = MelsecMcDataType.TS;
+                                addressData.AddressStart = Convert.ToInt32(address.Substring(2), MelsecMcDataType.TS.FromBase);
+                                break;
+                            }
+                            else if (address[1] == 'C' || address[1] == 'c')
+                            {
+                                addressData.McDataType = MelsecMcDataType.TC;
+                                addressData.AddressStart = Convert.ToInt32(address.Substring(2), MelsecMcDataType.TC.FromBase);
+                                break;
+                            }
+                            else
+                            {
+                                throw new Exception(StringResources.Language.NotSupportedDataType);
+                            }
+                        }
+                    case 'C':
+                    case 'c':
+                        {
+                            if (address[1] == 'N' || address[1] == 'n')
+                            {
+                                addressData.McDataType = MelsecMcDataType.CN;
+                                addressData.AddressStart = Convert.ToInt32(address.Substring(2), MelsecMcDataType.CN.FromBase);
+                                break;
+                            }
+                            else if (address[1] == 'S' || address[1] == 's')
+                            {
+                                addressData.McDataType = MelsecMcDataType.CS;
+                                addressData.AddressStart = Convert.ToInt32(address.Substring(2), MelsecMcDataType.CS.FromBase);
+                                break;
+                            }
+                            else if (address[1] == 'C' || address[1] == 'c')
+                            {
+                                addressData.McDataType = MelsecMcDataType.CC;
+                                addressData.AddressStart = Convert.ToInt32(address.Substring(2), MelsecMcDataType.CC.FromBase);
+                                break;
+                            }
+                            else
+                            {
+                                throw new Exception(StringResources.Language.NotSupportedDataType);
+                            }
+                        }
+                    default: throw new Exception(StringResources.Language.NotSupportedDataType);
+                }
+            }
+            catch (Exception ex)
+            {
+                return new OperateResult<McAddressData>(ex.Message);
+            }
+
+            return OperateResult.CreateSuccessResult(addressData);
+        }
+
+        /// <summary>
+        /// 从实际基恩士的地址里面解析出
+        /// </summary>
+        /// <param name="address">基恩士的地址数据信息</param>
+        /// <param name="length">读取的数据长度</param>
+        /// <returns>是否成功的结果对象</returns>
+        public static OperateResult<McAddressData> ParseKeyenceFrom(string address, ushort length)
+        {
+            McAddressData addressData = new McAddressData();
+            addressData.Length = length;
+            try
+            {
+                switch (address[0])
+                {
+                    case 'M':
+                    case 'm':
+                        {
+                            addressData.McDataType = MelsecMcDataType.Keyence_M;
+                            addressData.AddressStart = Convert.ToInt32(address.Substring(1), MelsecMcDataType.Keyence_M.FromBase);
+                            break;
+                        }
+                    case 'X':
+                    case 'x':
+                        {
+                            addressData.McDataType = MelsecMcDataType.Keyence_X;
+                            addressData.AddressStart = Convert.ToInt32(address.Substring(1), MelsecMcDataType.Keyence_X.FromBase);
+                            break;
+                        }
+                    case 'Y':
+                    case 'y':
+                        {
+                            addressData.McDataType = MelsecMcDataType.Keyence_Y;
+                            addressData.AddressStart = Convert.ToInt32(address.Substring(1), MelsecMcDataType.Keyence_Y.FromBase);
+                            break;
+                        }
+                    case 'B':
+                    case 'b':
+                        {
+                            addressData.McDataType = MelsecMcDataType.Keyence_B;
+                            addressData.AddressStart = Convert.ToInt32(address.Substring(1), MelsecMcDataType.Keyence_B.FromBase);
+                            break;
+                        }
+                    case 'L':
+                    case 'l':
+                        {
+                            addressData.McDataType = MelsecMcDataType.Keyence_L;
+                            addressData.AddressStart = Convert.ToInt32(address.Substring(1), MelsecMcDataType.Keyence_L.FromBase);
+                            break;
+                        }
+                    case 'S':
+                    case 's':
+                        {
+                            if (address[1] == 'M' || address[1] == 'm')
+                            {
+                                addressData.McDataType = MelsecMcDataType.Keyence_SM;
+                                addressData.AddressStart = Convert.ToInt32(address.Substring(2), MelsecMcDataType.Keyence_SM.FromBase);
+                                break;
+                            }
+                            else if (address[1] == 'D' || address[1] == 'd')
+                            {
+                                addressData.McDataType = MelsecMcDataType.Keyence_SD;
+                                addressData.AddressStart = Convert.ToInt32(address.Substring(2), MelsecMcDataType.Keyence_SD.FromBase);
+                                break;
+                            }
+                            else
+                            {
+                                throw new Exception(StringResources.Language.NotSupportedDataType);
+                            }
+                        }
+                    case 'D':
+                    case 'd':
+                        {
+                            addressData.McDataType = MelsecMcDataType.Keyence_D;
+                            addressData.AddressStart = Convert.ToInt32(address.Substring(1), MelsecMcDataType.Keyence_D.FromBase);
+                            break;
+                        }
+                    case 'R':
+                    case 'r':
+                        {
+                            addressData.McDataType = MelsecMcDataType.Keyence_R;
+                            addressData.AddressStart = Convert.ToInt32(address.Substring(1), MelsecMcDataType.Keyence_R.FromBase);
+                            break;
+                        }
+                    case 'Z':
+                    case 'z':
+                        {
+                            if (address[1] == 'R' || address[1] == 'r')
+                            {
+                                addressData.McDataType = MelsecMcDataType.Keyence_ZR;
+                                addressData.AddressStart = Convert.ToInt32(address.Substring(2), MelsecMcDataType.Keyence_ZR.FromBase);
+                                break;
+                            }
+                            else
+                            {
+                                throw new Exception(StringResources.Language.NotSupportedDataType);
+                            }
+                        }
+                    case 'W':
+                    case 'w':
+                        {
+                            addressData.McDataType = MelsecMcDataType.Keyence_W;
+                            addressData.AddressStart = Convert.ToInt32(address.Substring(1), MelsecMcDataType.Keyence_W.FromBase);
+                            break;
+                        }
+                    case 'T':
+                    case 't':
+                        {
+                            if (address[1] == 'N' || address[1] == 'n')
+                            {
+                                addressData.McDataType = MelsecMcDataType.Keyence_TN;
+                                addressData.AddressStart = Convert.ToInt32(address.Substring(2), MelsecMcDataType.Keyence_TN.FromBase);
+                                break;
+                            }
+                            else if (address[1] == 'S' || address[1] == 's')
+                            {
+                                addressData.McDataType = MelsecMcDataType.Keyence_TS;
+                                addressData.AddressStart = Convert.ToInt32(address.Substring(2), MelsecMcDataType.Keyence_TS.FromBase);
+                                break;
+                            }
+                            else
+                            {
+                                throw new Exception(StringResources.Language.NotSupportedDataType);
+                            }
+                        }
+                    case 'C':
+                    case 'c':
+                        {
+                            if (address[1] == 'N' || address[1] == 'n')
+                            {
+                                addressData.McDataType = MelsecMcDataType.Keyence_CN;
+                                addressData.AddressStart = Convert.ToInt32(address.Substring(2), MelsecMcDataType.Keyence_CN.FromBase);
+                                break;
+                            }
+                            else if (address[1] == 'S' || address[1] == 's')
+                            {
+                                addressData.McDataType = MelsecMcDataType.Keyence_CS;
+                                addressData.AddressStart = Convert.ToInt32(address.Substring(2), MelsecMcDataType.Keyence_CS.FromBase);
+                                break;
+                            }
+                            else
+                            {
+                                throw new Exception(StringResources.Language.NotSupportedDataType);
+                            }
+                        }
+                    default: throw new Exception(StringResources.Language.NotSupportedDataType);
+                }
+            }
+            catch (Exception ex)
+            {
+                return new OperateResult<McAddressData>(ex.Message);
+            }
+
+            return OperateResult.CreateSuccessResult(addressData);
+        }
+
+        /// <summary>
+        /// 计算松下的MC协议的偏移地址的机制
+        /// </summary>
+        /// <param name="address">字符串形式的地址</param>
+        /// <returns>实际的偏移地址</returns>
+        public static int GetPanasonicAddress(string address)
+        {
+            if (address.IndexOf('.') > 0)
+            {
+                string[] values = address.Split('.');
+                return Convert.ToInt32(values[0]) * 16 + Convert.ToInt32(values[1]);
+            }
+            else
+            {
+                return Convert.ToInt32(address.Substring(0, address.Length - 1)) * 16 + Convert.ToInt32(address.Substring(address.Length - 1), 16);
+            }
+        }
+
+        /// <summary>
+        /// 从实际松下的地址里面解析出
+        /// </summary>
+        /// <param name="address">松下的地址数据信息</param>
+        /// <param name="length">读取的数据长度</param>
+        /// <returns>是否成功的结果对象</returns>
+        public static OperateResult<McAddressData> ParsePanasonicFrom(string address, ushort length)
+        {
+            McAddressData addressData = new McAddressData();
+            addressData.Length = length;
+            try
+            {
+                switch (address[0])
+                {
+                    case 'R':
+                    case 'r':
+                        {
+                            int add = GetPanasonicAddress(address.Substring(1));
+                            if (add < 14400)
+                            {
+                                addressData.McDataType = MelsecMcDataType.Panasonic_R;
+                                addressData.AddressStart = add;
+                            }
+                            else
+                            {
+                                addressData.McDataType = MelsecMcDataType.Panasonic_SM;
+                                addressData.AddressStart = add - 14400;
+                            }
+                            break;
+                        }
+                    case 'X':
+                    case 'x':
+                        {
+                            addressData.McDataType = MelsecMcDataType.Panasonic_X;
+                            addressData.AddressStart = GetPanasonicAddress(address.Substring(1));
+                            break;
+                        }
+                    case 'Y':
+                    case 'y':
+                        {
+                            addressData.McDataType = MelsecMcDataType.Panasonic_Y;
+                            addressData.AddressStart = GetPanasonicAddress(address.Substring(1));
+                            break;
+                        }
+                    case 'L':
+                    case 'l':
+                        {
+                            if (address[1] == 'D' || address[1] == 'd')
+                            {
+                                addressData.McDataType = MelsecMcDataType.Panasonic_LD;
+                                addressData.AddressStart = Convert.ToInt32(address.Substring(2));
+                                break;
+                            }
+                            else
+                            {
+                                addressData.McDataType = MelsecMcDataType.Panasonic_L;
+                                addressData.AddressStart = GetPanasonicAddress(address.Substring(1));
+                            }
+                            break;
+                        }
+                    case 'D':
+                    case 'd':
+                        {
+                            int add = Convert.ToInt32(address.Substring(1));
+                            if (add < 90000)
+                            {
+                                addressData.McDataType = MelsecMcDataType.Panasonic_DT;
+                                addressData.AddressStart = Convert.ToInt32(address.Substring(1));
+                            }
+                            else
+                            {
+                                addressData.McDataType = MelsecMcDataType.Panasonic_SD;
+                                addressData.AddressStart = Convert.ToInt32(address.Substring(1)) - 90000;
+                            }
+                            break;
+                        }
+                    case 'T':
+                    case 't':
+                        {
+                            if (address[1] == 'N' || address[1] == 'n')
+                            {
+                                addressData.McDataType = MelsecMcDataType.Panasonic_TN;
+                                addressData.AddressStart = Convert.ToInt32(address.Substring(2));
+                                break;
+                            }
+                            else if (address[1] == 'S' || address[1] == 's')
+                            {
+                                addressData.McDataType = MelsecMcDataType.Panasonic_TS;
+                                addressData.AddressStart = Convert.ToInt32(address.Substring(2));
+                                break;
+                            }
+                            else
+                            {
+                                throw new Exception(StringResources.Language.NotSupportedDataType);
+                            }
+                        }
+                    case 'C':
+                    case 'c':
+                        {
+                            if (address[1] == 'N' || address[1] == 'n')
+                            {
+                                addressData.McDataType = MelsecMcDataType.Panasonic_CN;
+                                addressData.AddressStart = Convert.ToInt32(address.Substring(2));
+                                break;
+                            }
+                            else if (address[1] == 'S' || address[1] == 's')
+                            {
+                                addressData.McDataType = MelsecMcDataType.Panasonic_CS;
+                                addressData.AddressStart = Convert.ToInt32(address.Substring(2));
+                                break;
+                            }
+                            else
+                            {
+                                throw new Exception(StringResources.Language.NotSupportedDataType);
+                            }
+                        }
+                    default: throw new Exception(StringResources.Language.NotSupportedDataType);
+                }
+            }
+            catch (Exception ex)
+            {
+                return new OperateResult<McAddressData>(ex.Message);
+            }
+
+            return OperateResult.CreateSuccessResult(addressData);
+        }
+
+        #endregion
+    }
+}

+ 70 - 0
BlankApp1/TFT-MelsecMcNet/MelsecA1EDataType.cs

@@ -0,0 +1,70 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TFT_MelsecMcNet
+{
+    /// <summary>
+    /// 三菱PLC的数据类型,此处包含了几个常用的类型
+    /// </summary>
+    public class MelsecA1EDataType
+    {
+        /// <summary>
+        /// 如果您清楚类型代号,可以根据值进行扩展
+        /// </summary>
+        /// <param name="code">数据类型的代号</param>
+        /// <param name="type">0或1,默认为0</param>
+        /// <param name="asciiCode">ASCII格式的类型信息</param>
+        /// <param name="fromBase">指示地址的多少进制的,10或是16</param>
+        public MelsecA1EDataType(byte[] code, byte type, string asciiCode, int fromBase)
+        {
+            DataCode = code;
+            AsciiCode = asciiCode;
+            FromBase = fromBase;
+            if (type < 2) DataType = type;
+        }
+        /// <summary>
+        /// 类型的代号值(软元件代码,用于区分软元件类型,如:D,R)
+        /// </summary>
+        public byte[] DataCode { get; private set; } = { 0x00, 0x00 };
+        /// <summary>
+        /// 数据的类型,0代表按字,1代表按位
+        /// </summary>
+        public byte DataType { get; private set; } = 0x00;
+
+        /// <summary>
+        /// 当以ASCII格式通讯时的类型描述
+        /// </summary>
+        public string AsciiCode { get; private set; }
+
+        /// <summary>
+        /// 指示地址是10进制,还是16进制的
+        /// </summary>
+        public int FromBase { get; private set; }
+
+        /// <summary>
+        /// X输入寄存器
+        /// </summary>
+        public readonly static MelsecA1EDataType X = new MelsecA1EDataType(new byte[] { 0x58, 0x20 }, 0x01, "X*", 8);
+        /// <summary>
+        /// Y输出寄存器
+        /// </summary>
+        public readonly static MelsecA1EDataType Y = new MelsecA1EDataType(new byte[] { 0x59, 0x20 }, 0x01, "Y*", 8);
+        /// <summary>
+        /// M中间寄存器
+        /// </summary>
+        public readonly static MelsecA1EDataType M = new MelsecA1EDataType(new byte[] { 0x4D, 0x20 }, 0x01, "M*", 10);
+        /// <summary>
+        /// S状态寄存器
+        /// </summary>
+        public readonly static MelsecA1EDataType S = new MelsecA1EDataType(new byte[] { 0x53, 0x20 }, 0x01, "S*", 10);
+        /// <summary>
+        /// D数据寄存器
+        /// </summary>
+        public readonly static MelsecA1EDataType D = new MelsecA1EDataType(new byte[] { 0x44, 0x20 }, 0x00, "D*", 10);
+        /// <summary>
+        /// R文件寄存器
+        /// </summary>
+        public readonly static MelsecA1EDataType R = new MelsecA1EDataType(new byte[] { 0x52, 0x20 }, 0x00, "R*", 10);
+    }
+}

+ 361 - 0
BlankApp1/TFT-MelsecMcNet/MelsecHelper.cs

@@ -0,0 +1,361 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace TFT_MelsecMcNet
+{
+    /// <summary>
+    /// 所有三菱通讯类的通用辅助工具类,包含了一些通用的静态方法,可以使用本类来获取一些原始的报文信息。详细的操作参见例子
+    /// </summary>
+    public class MelsecHelper
+    {
+        #region Melsec Mc
+
+        /// <summary>
+        /// 解析A1E协议数据地址
+        /// </summary>
+        /// <param name="address">数据地址</param>
+        /// <returns></returns>
+        public static OperateResult<MelsecA1EDataType, ushort> McA1EAnalysisAddress(string address)
+        {
+            var result = new OperateResult<MelsecA1EDataType, ushort>();
+            try
+            {
+                switch (address[0])
+                {
+                    case 'X':
+                    case 'x':
+                        {
+                            result.Content1 = MelsecA1EDataType.X;
+                            result.Content2 = Convert.ToUInt16(address.Substring(1), MelsecA1EDataType.X.FromBase);
+                            break;
+                        }
+                    case 'Y':
+                    case 'y':
+                        {
+                            result.Content1 = MelsecA1EDataType.Y;
+                            result.Content2 = Convert.ToUInt16(address.Substring(1), MelsecA1EDataType.Y.FromBase);
+                            break;
+                        }
+                    case 'M':
+                    case 'm':
+                        {
+                            result.Content1 = MelsecA1EDataType.M;
+                            result.Content2 = Convert.ToUInt16(address.Substring(1), MelsecA1EDataType.M.FromBase);
+                            break;
+                        }
+                    case 'S':
+                    case 's':
+                        {
+                            result.Content1 = MelsecA1EDataType.S;
+                            result.Content2 = Convert.ToUInt16(address.Substring(1), MelsecA1EDataType.S.FromBase);
+                            break;
+                        }
+                    case 'D':
+                    case 'd':
+                        {
+                            result.Content1 = MelsecA1EDataType.D;
+                            result.Content2 = Convert.ToUInt16(address.Substring(1), MelsecA1EDataType.D.FromBase);
+                            break;
+                        }
+                    case 'R':
+                    case 'r':
+                        {
+                            result.Content1 = MelsecA1EDataType.R;
+                            result.Content2 = Convert.ToUInt16(address.Substring(1), MelsecA1EDataType.R.FromBase);
+                            break;
+                        }
+                    default: throw new Exception(StringResources.Language.NotSupportedDataType);
+                }
+            }
+            catch (Exception ex)
+            {
+                result.Message = ex.Message;
+                return result;
+            }
+
+            result.IsSuccess = true;
+            return result;
+        }
+
+        /// <summary>
+        /// 从三菱地址,是否位读取进行创建读取的MC的核心报文
+        /// </summary>
+        /// <param name="isBit">是否进行了位读取操作</param>
+        /// <param name="addressData">三菱Mc协议的数据地址</param>
+        /// <returns>带有成功标识的报文对象</returns>
+        public static byte[] BuildReadMcCoreCommand(McAddressData addressData, bool isBit)
+        {
+            byte[] command = new byte[10];
+            command[0] = 0x01;                                                      // 批量读取数据命令
+            command[1] = 0x04;
+            command[2] = isBit ? (byte)0x01 : (byte)0x00;                           // 以点为单位还是字为单位成批读取
+            command[3] = 0x00;
+            command[4] = BitConverter.GetBytes(addressData.AddressStart)[0];      // 起始地址的地位
+            command[5] = BitConverter.GetBytes(addressData.AddressStart)[1];
+            command[6] = BitConverter.GetBytes(addressData.AddressStart)[2];
+            command[7] = addressData.McDataType.DataCode;                           // 指明读取的数据
+            command[8] = (byte)(addressData.Length % 256);                          // 软元件的长度
+            command[9] = (byte)(addressData.Length / 256);
+
+            return command;
+        }
+
+        /// <summary>
+        /// 从三菱地址,是否位读取进行创建读取Ascii格式的MC的核心报文
+        /// </summary>
+        /// <param name="addressData">三菱Mc协议的数据地址</param>
+        /// <param name="isBit">是否进行了位读取操作</param>
+        /// <returns>带有成功标识的报文对象</returns>
+        public static byte[] BuildAsciiReadMcCoreCommand(McAddressData addressData, bool isBit)
+        {
+            byte[] command = new byte[20];
+            command[0] = 0x30;                                                               // 批量读取数据命令
+            command[1] = 0x34;
+            command[2] = 0x30;
+            command[3] = 0x31;
+            command[4] = 0x30;                                                               // 以点为单位还是字为单位成批读取
+            command[5] = 0x30;
+            command[6] = 0x30;
+            command[7] = isBit ? (byte)0x31 : (byte)0x30;
+            command[8] = Encoding.ASCII.GetBytes(addressData.McDataType.AsciiCode)[0];          // 软元件类型
+            command[9] = Encoding.ASCII.GetBytes(addressData.McDataType.AsciiCode)[1];
+            command[10] = BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[0];            // 起始地址的地位
+            command[11] = BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[1];
+            command[12] = BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[2];
+            command[13] = BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[3];
+            command[14] = BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[4];
+            command[15] = BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[5];
+            command[16] = SoftBasic.BuildAsciiBytesFrom(addressData.Length)[0];                                             // 软元件点数
+            command[17] = SoftBasic.BuildAsciiBytesFrom(addressData.Length)[1];
+            command[18] = SoftBasic.BuildAsciiBytesFrom(addressData.Length)[2];
+            command[19] = SoftBasic.BuildAsciiBytesFrom(addressData.Length)[3];
+
+            return command;
+        }
+
+        /// <summary>
+        /// 以字为单位,创建数据写入的核心报文
+        /// </summary>
+        /// <param name="addressData">三菱Mc协议的数据地址</param>
+        /// <param name="value">实际的原始数据信息</param>
+        /// <returns>带有成功标识的报文对象</returns>
+        public static byte[] BuildWriteWordCoreCommand(McAddressData addressData, byte[] value)
+        {
+            if (value == null) value = new byte[0];
+            byte[] command = new byte[10 + value.Length];
+            command[0] = 0x01;                                                        // 批量写入数据命令
+            command[1] = 0x14;
+            command[2] = 0x00;                                                        // 以字为单位成批读取
+            command[3] = 0x00;
+            command[4] = BitConverter.GetBytes(addressData.AddressStart)[0];        // 起始地址的地位
+            command[5] = BitConverter.GetBytes(addressData.AddressStart)[1];
+            command[6] = BitConverter.GetBytes(addressData.AddressStart)[2];
+            command[7] = addressData.McDataType.DataCode;                             // 指明写入的数据
+            command[8] = (byte)(value.Length / 2 % 256);                              // 软元件长度的地位
+            command[9] = (byte)(value.Length / 2 / 256);
+            value.CopyTo(command, 10);
+
+            return command;
+        }
+
+        /// <summary>
+        /// 以字为单位,创建ASCII数据写入的核心报文
+        /// </summary>
+        /// <param name="addressData">三菱Mc协议的数据地址</param>
+        /// <param name="value">实际的原始数据信息</param>
+        /// <returns>带有成功标识的报文对象</returns>
+        public static byte[] BuildAsciiWriteWordCoreCommand(McAddressData addressData, byte[] value)
+        {
+            if (value == null) value = new byte[0];
+            byte[] buffer = new byte[value.Length * 2];
+            for (int i = 0; i < value.Length / 2; i++)
+            {
+                SoftBasic.BuildAsciiBytesFrom(BitConverter.ToUInt16(value, i * 2)).CopyTo(buffer, 4 * i);
+            }
+            value = buffer;
+
+            byte[] command = new byte[20 + value.Length];
+            command[0] = 0x31;                                                                                          // 批量写入的命令
+            command[1] = 0x34;
+            command[2] = 0x30;
+            command[3] = 0x31;
+            command[4] = 0x30;                                                                                          // 子命令
+            command[5] = 0x30;
+            command[6] = 0x30;
+            command[7] = 0x30;
+            command[8] = Encoding.ASCII.GetBytes(addressData.McDataType.AsciiCode)[0];                                // 软元件类型
+            command[9] = Encoding.ASCII.GetBytes(addressData.McDataType.AsciiCode)[1];
+            command[10] = BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[0];     // 起始地址的地位
+            command[11] = BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[1];
+            command[12] = BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[2];
+            command[13] = BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[3];
+            command[14] = BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[4];
+            command[15] = BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[5];
+            command[16] = SoftBasic.BuildAsciiBytesFrom((ushort)(value.Length / 4))[0];                              // 软元件点数
+            command[17] = SoftBasic.BuildAsciiBytesFrom((ushort)(value.Length / 4))[1];
+            command[18] = SoftBasic.BuildAsciiBytesFrom((ushort)(value.Length / 4))[2];
+            command[19] = SoftBasic.BuildAsciiBytesFrom((ushort)(value.Length / 4))[3];
+            value.CopyTo(command, 20);
+
+            return command;
+        }
+
+        /// <summary>
+        /// 以位为单位,创建数据写入的核心报文
+        /// </summary>
+        /// <param name="addressData">三菱Mc协议的数据地址</param>
+        /// <param name="value">原始的bool数组数据</param>
+        /// <returns>带有成功标识的报文对象</returns>
+        public static byte[] BuildWriteBitCoreCommand(McAddressData addressData, bool[] value)
+        {
+            if (value == null) value = new bool[0];
+            byte[] buffer = TransBoolArrayToByteData(value);
+            byte[] command = new byte[10 + buffer.Length];
+            command[0] = 0x01;                                                        // 批量写入数据命令
+            command[1] = 0x14;
+            command[2] = 0x01;                                                        // 以位为单位成批写入
+            command[3] = 0x00;
+            command[4] = BitConverter.GetBytes(addressData.AddressStart)[0];        // 起始地址的地位
+            command[5] = BitConverter.GetBytes(addressData.AddressStart)[1];
+            command[6] = BitConverter.GetBytes(addressData.AddressStart)[2];
+            command[7] = addressData.McDataType.DataCode;                             // 指明写入的数据
+            command[8] = (byte)(value.Length % 256);                                  // 软元件长度的地位
+            command[9] = (byte)(value.Length / 256);
+            buffer.CopyTo(command, 10);
+
+            return command;
+        }
+
+        /// <summary>
+        /// 以位为单位,创建ASCII数据写入的核心报文
+        /// </summary>
+        /// <param name="addressData">三菱Mc协议的数据地址</param>
+        /// <param name="value">原始的bool数组数据</param>
+        /// <returns>带有成功标识的报文对象</returns>
+        public static byte[] BuildAsciiWriteBitCoreCommand(McAddressData addressData, bool[] value)
+        {
+            if (value == null) value = new bool[0];
+            byte[] buffer = value.Select(m => m ? (byte)0x31 : (byte)0x30).ToArray();
+
+            byte[] command = new byte[20 + buffer.Length];
+            command[0] = 0x31;                                                                              // 批量写入的命令
+            command[1] = 0x34;
+            command[2] = 0x30;
+            command[3] = 0x31;
+            command[4] = 0x30;                                                                              // 子命令
+            command[5] = 0x30;
+            command[6] = 0x30;
+            command[7] = 0x31;
+            command[8] = Encoding.ASCII.GetBytes(addressData.McDataType.AsciiCode)[0];                         // 软元件类型
+            command[9] = Encoding.ASCII.GetBytes(addressData.McDataType.AsciiCode)[1];
+            command[10] = BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[0];     // 起始地址的地位
+            command[11] = BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[1];
+            command[12] = BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[2];
+            command[13] = BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[3];
+            command[14] = BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[4];
+            command[15] = BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[5];
+            command[16] = SoftBasic.BuildAsciiBytesFrom((ushort)(value.Length))[0];              // 软元件点数
+            command[17] = SoftBasic.BuildAsciiBytesFrom((ushort)(value.Length))[1];
+            command[18] = SoftBasic.BuildAsciiBytesFrom((ushort)(value.Length))[2];
+            command[19] = SoftBasic.BuildAsciiBytesFrom((ushort)(value.Length))[3];
+            buffer.CopyTo(command, 20);
+
+            return command;
+        }
+
+        #endregion
+
+        #region Common Logic
+
+        /// <summary>
+        /// 从三菱的地址中构建MC协议的6字节的ASCII格式的地址
+        /// </summary>
+        /// <param name="address">三菱地址</param>
+        /// <param name="type">三菱的数据类型</param>
+        /// <returns>6字节的ASCII格式的地址</returns>
+        internal static byte[] BuildBytesFromAddress(int address, MelsecMcDataType type)
+        {
+            return Encoding.ASCII.GetBytes(address.ToString(type.FromBase == 10 ? "D6" : "X6"));
+        }
+
+        /// <summary>
+        /// 将0,1,0,1的字节数组压缩成三菱格式的字节数组来表示开关量的
+        /// </summary>
+        /// <param name="value">原始的数据字节</param>
+        /// <returns>压缩过后的数据字节</returns>
+        internal static byte[] TransBoolArrayToByteData(byte[] value)
+        {
+            int length = (value.Length + 1) / 2;
+            byte[] buffer = new byte[length];
+
+            for (int i = 0; i < length; i++)
+            {
+                if (value[i * 2 + 0] != 0x00) buffer[i] += 0x10;
+                if ((i * 2 + 1) < value.Length)
+                {
+                    if (value[i * 2 + 1] != 0x00) buffer[i] += 0x01;
+                }
+            }
+
+            return buffer;
+        }
+
+        /// <summary>
+        /// 将bool的组压缩成三菱格式的字节数组来表示开关量的
+        /// </summary>
+        /// <param name="value">原始的数据字节</param>
+        /// <returns>压缩过后的数据字节</returns>
+        internal static byte[] TransBoolArrayToByteData(bool[] value)
+        {
+            int length = (value.Length + 1) / 2;
+            byte[] buffer = new byte[length];
+
+            for (int i = 0; i < length; i++)
+            {
+                if (value[i * 2 + 0]) buffer[i] += 0x10;
+                if ((i * 2 + 1) < value.Length)
+                {
+                    if (value[i * 2 + 1]) buffer[i] += 0x01;
+                }
+            }
+
+            return buffer;
+        }
+
+        #endregion
+
+        #region CRC Check
+
+        /// <summary>
+        /// 计算Fx协议指令的和校验信息
+        /// </summary>
+        /// <param name="data">字节数据</param>
+        /// <returns>校验之后的数据</returns>
+        internal static byte[] FxCalculateCRC(byte[] data)
+        {
+            int sum = 0;
+            for (int i = 1; i < data.Length - 2; i++)
+            {
+                sum += data[i];
+            }
+            return SoftBasic.BuildAsciiBytesFrom((byte)sum);
+        }
+
+        /// <summary>
+        /// 检查指定的和校验是否是正确的
+        /// </summary>
+        /// <param name="data">字节数据</param>
+        /// <returns>是否成功</returns>
+        internal static bool CheckCRC(byte[] data)
+        {
+            byte[] crc = FxCalculateCRC(data);
+            if (crc[0] != data[data.Length - 2]) return false;
+            if (crc[1] != data[^1]) return false;
+            return true;
+        }
+
+        #endregion
+    }
+}

+ 272 - 0
BlankApp1/TFT-MelsecMcNet/MelsecMcDataType.cs

@@ -0,0 +1,272 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TFT_MelsecMcNet
+{
+    /// <summary>
+    /// 三菱PLC的数据类型,此处包含了几个常用的类型
+    /// </summary>
+    public class MelsecMcDataType
+    {
+        /// <summary>
+        /// 如果您清楚类型代号,可以根据值进行扩展
+        /// </summary>
+        /// <param name="code">数据类型的代号</param>
+        /// <param name="type">0或1,默认为0</param>
+        /// <param name="asciiCode">ASCII格式的类型信息</param>
+        /// <param name="fromBase">指示地址的多少进制的,10或是16</param>
+        public MelsecMcDataType(byte code, byte type, string asciiCode, int fromBase)
+        {
+            DataCode = code;
+            AsciiCode = asciiCode;
+            FromBase = fromBase;
+            if (type < 2) DataType = type;
+        }
+
+        /// <summary>
+        /// 类型的代号值
+        /// </summary>
+        public byte DataCode { get; private set; } = 0x00;
+
+        /// <summary>
+        /// 数据的类型,0代表按字,1代表按位
+        /// </summary>
+        public byte DataType { get; private set; } = 0x00;
+
+        /// <summary>
+        /// 当以ASCII格式通讯时的类型描述
+        /// </summary>
+        public string AsciiCode { get; private set; }
+
+        /// <summary>
+        /// 指示地址是10进制,还是16进制的
+        /// </summary>
+        public int FromBase { get; private set; }
+
+        /// <summary>
+        /// X输入继电器
+        /// </summary>
+        public readonly static MelsecMcDataType X = new MelsecMcDataType(0x9C, 0x01, "X*", 16);
+
+        /// <summary>
+        /// Y输出继电器
+        /// </summary>
+        public readonly static MelsecMcDataType Y = new MelsecMcDataType(0x9D, 0x01, "Y*", 16);
+
+        /// <summary>
+        /// M中间继电器
+        /// </summary>
+        public readonly static MelsecMcDataType M = new MelsecMcDataType(0x90, 0x01, "M*", 10);
+
+        /// <summary>
+        /// D数据寄存器
+        /// </summary>
+        public readonly static MelsecMcDataType D = new MelsecMcDataType(0xA8, 0x00, "D*", 10);
+
+        /// <summary>
+        /// W链接寄存器
+        /// </summary>
+        public readonly static MelsecMcDataType W = new MelsecMcDataType(0xB4, 0x00, "W*", 16);
+
+        /// <summary>
+        /// L锁存继电器
+        /// </summary>
+        public readonly static MelsecMcDataType L = new MelsecMcDataType(0x92, 0x01, "L*", 10);
+
+        /// <summary>
+        /// F报警器
+        /// </summary>
+        public readonly static MelsecMcDataType F = new MelsecMcDataType(0x93, 0x01, "F*", 10);
+
+        /// <summary>
+        /// V边沿继电器
+        /// </summary>
+        public readonly static MelsecMcDataType V = new MelsecMcDataType(0x94, 0x01, "V*", 10);
+
+        /// <summary>
+        /// B链接继电器
+        /// </summary>
+        public readonly static MelsecMcDataType B = new MelsecMcDataType(0xA0, 0x01, "B*", 16);
+
+        /// <summary>
+        /// R文件寄存器
+        /// </summary>
+        public readonly static MelsecMcDataType R = new MelsecMcDataType(0xAF, 0x00, "R*", 10);
+
+        /// <summary>
+        /// S步进继电器
+        /// </summary>
+        public readonly static MelsecMcDataType S = new MelsecMcDataType(0x98, 0x01, "S*", 10);
+
+        /// <summary>
+        /// 变址寄存器
+        /// </summary>
+        public readonly static MelsecMcDataType Z = new MelsecMcDataType(0xCC, 0x00, "Z*", 10);
+
+        /// <summary>
+        /// 定时器的当前值
+        /// </summary>
+        public readonly static MelsecMcDataType TN = new MelsecMcDataType(0xC2, 0x00, "TN", 10);
+
+        /// <summary>
+        /// 定时器的触点
+        /// </summary>
+        public readonly static MelsecMcDataType TS = new MelsecMcDataType(0xC1, 0x01, "TS", 10);
+
+        /// <summary>
+        /// 定时器的线圈
+        /// </summary>
+        public readonly static MelsecMcDataType TC = new MelsecMcDataType(0xC0, 0x01, "TC", 10);
+
+        /// <summary>
+        /// 累计定时器的触点
+        /// </summary>
+        public readonly static MelsecMcDataType SS = new MelsecMcDataType(0xC7, 0x01, "SS", 10);
+
+        /// <summary>
+        /// 累计定时器的线圈
+        /// </summary>
+        public readonly static MelsecMcDataType SC = new MelsecMcDataType(0xC6, 0x01, "SC", 10);
+
+        /// <summary>
+        /// 累计定时器的当前值
+        /// </summary>
+        public readonly static MelsecMcDataType SN = new MelsecMcDataType(0xC8, 0x00, "SN", 100);
+
+        /// <summary>
+        /// 计数器的当前值
+        /// </summary>
+        public readonly static MelsecMcDataType CN = new MelsecMcDataType(0xC5, 0x00, "CN", 10);
+
+        /// <summary>
+        /// 计数器的触点
+        /// </summary>
+        public readonly static MelsecMcDataType CS = new MelsecMcDataType(0xC4, 0x01, "CS", 10);
+
+        /// <summary>
+        /// 计数器的线圈
+        /// </summary>
+        public readonly static MelsecMcDataType CC = new MelsecMcDataType(0xC3, 0x01, "CC", 10);
+
+        /// <summary>
+        /// 文件寄存器ZR区
+        /// </summary>
+        public readonly static MelsecMcDataType ZR = new MelsecMcDataType(0xB0, 0x00, "ZR", 10);
+
+
+
+
+        /// <summary>
+        /// X输入继电器
+        /// </summary>
+        public readonly static MelsecMcDataType Keyence_X = new MelsecMcDataType(0x9C, 0x01, "X*", 16);
+        /// <summary>
+        /// Y输出继电器
+        /// </summary>
+        public readonly static MelsecMcDataType Keyence_Y = new MelsecMcDataType(0x9D, 0x01, "Y*", 16);
+        /// <summary>
+        /// 链接继电器
+        /// </summary>
+        public readonly static MelsecMcDataType Keyence_B = new MelsecMcDataType(0xA0, 0x01, "B*", 16);
+        /// <summary>
+        /// 内部辅助继电器
+        /// </summary>
+        public readonly static MelsecMcDataType Keyence_M = new MelsecMcDataType(0x90, 0x01, "M*", 10);
+        /// <summary>
+        /// 锁存继电器
+        /// </summary>
+        public readonly static MelsecMcDataType Keyence_L = new MelsecMcDataType(0x92, 0x01, "L*", 10);
+        /// <summary>
+        /// 控制继电器
+        /// </summary>
+        public readonly static MelsecMcDataType Keyence_SM = new MelsecMcDataType(0x91, 0x01, "SM", 10);
+        /// <summary>
+        /// 控制存储器
+        /// </summary>
+        public readonly static MelsecMcDataType Keyence_SD = new MelsecMcDataType(0xA9, 0x00, "SD", 10);
+        /// <summary>
+        /// 数据存储器
+        /// </summary>
+        public readonly static MelsecMcDataType Keyence_D = new MelsecMcDataType(0xA8, 0x00, "D*", 10);
+        /// <summary>
+        /// 文件寄存器
+        /// </summary>
+        public readonly static MelsecMcDataType Keyence_R = new MelsecMcDataType(0xAF, 0x00, "R*", 10);
+        /// <summary>
+        /// 文件寄存器
+        /// </summary>
+        public readonly static MelsecMcDataType Keyence_ZR = new MelsecMcDataType(0xB0, 0x00, "ZR", 16);
+        /// <summary>
+        /// 链路寄存器
+        /// </summary>
+        public readonly static MelsecMcDataType Keyence_W = new MelsecMcDataType(0xB4, 0x00, "W*", 16);
+        /// <summary>
+        /// 计时器(当前值)
+        /// </summary>
+        public readonly static MelsecMcDataType Keyence_TN = new MelsecMcDataType(0xC2, 0x00, "TN", 10);
+        /// <summary>
+        /// 计时器(接点)
+        /// </summary>
+        public readonly static MelsecMcDataType Keyence_TS = new MelsecMcDataType(0xC1, 0x01, "TS", 10);
+        /// <summary>
+        /// 计数器(当前值)
+        /// </summary>
+        public readonly static MelsecMcDataType Keyence_CN = new MelsecMcDataType(0xC5, 0x00, "CN", 10);
+        /// <summary>
+        /// 计数器(接点)
+        /// </summary>
+        public readonly static MelsecMcDataType Keyence_CS = new MelsecMcDataType(0xC4, 0x01, "CS", 10);
+
+
+        /// <summary>
+        /// 输入继电器
+        /// </summary>
+        public readonly static MelsecMcDataType Panasonic_X = new MelsecMcDataType(0x9C, 0x01, "X*", 10);
+        /// <summary>
+        /// 输出继电器
+        /// </summary>
+        public readonly static MelsecMcDataType Panasonic_Y = new MelsecMcDataType(0x9D, 0x01, "Y*", 10);
+        /// <summary>
+        /// 链接继电器
+        /// </summary>
+        public readonly static MelsecMcDataType Panasonic_L = new MelsecMcDataType(0xA0, 0x01, "L*", 10);
+        /// <summary>
+        /// 内部继电器
+        /// </summary>
+        public readonly static MelsecMcDataType Panasonic_R = new MelsecMcDataType(0x90, 0x01, "R*", 10);
+        /// <summary>
+        /// 数据存储器
+        /// </summary>
+        public readonly static MelsecMcDataType Panasonic_DT = new MelsecMcDataType(0xA8, 0x00, "D*", 10);
+        /// <summary>
+        /// 链接存储器
+        /// </summary>
+        public readonly static MelsecMcDataType Panasonic_LD = new MelsecMcDataType(0xB4, 0x00, "W*", 10);
+        /// <summary>
+        /// 计时器(当前值)
+        /// </summary>
+        public readonly static MelsecMcDataType Panasonic_TN = new MelsecMcDataType(0xC2, 0x00, "TN", 10);
+        /// <summary>
+        /// 计时器(接点)
+        /// </summary>
+        public readonly static MelsecMcDataType Panasonic_TS = new MelsecMcDataType(0xC1, 0x01, "TS", 10);
+        /// <summary>
+        /// 计数器(当前值)
+        /// </summary>
+        public readonly static MelsecMcDataType Panasonic_CN = new MelsecMcDataType(0xC5, 0x00, "CN", 10);
+        /// <summary>
+        /// 计数器(接点)
+        /// </summary>
+        public readonly static MelsecMcDataType Panasonic_CS = new MelsecMcDataType(0xC4, 0x01, "CS", 10);
+        /// <summary>
+        /// 特殊链接继电器
+        /// </summary>
+        public readonly static MelsecMcDataType Panasonic_SM = new MelsecMcDataType(0x91, 0x01, "SM", 10);
+        /// <summary>
+        /// 特殊链接存储器
+        /// </summary>
+        public readonly static MelsecMcDataType Panasonic_SD = new MelsecMcDataType(0xA9, 0x00, "SD", 10);
+
+    }
+}

+ 1960 - 0
BlankApp1/TFT-MelsecMcNet/MelsecMcNet.cs

@@ -0,0 +1,1960 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace TFT_MelsecMcNet
+{
+    public class MelsecMcNet
+    {
+        #region Global Member
+
+        /// <summary>
+        /// 单个数据字节的长度,西门子为2,三菱,欧姆龙,modbusTcp就为1,AB PLC无效
+        /// </summary>
+        /// <remarks>对设备来说,一个地址的数据对应的字节数,或是1个字节或是2个字节</remarks>
+        public ushort WordLength { get; set; } = 1;
+        /// <summary>
+        /// 连接的IP地址
+        /// </summary>
+        private string ipAddress = "127.0.0.1";          // 连接的IP地址
+        /// <summary>
+        /// 端口号
+        /// </summary>
+        private int port = 10000;                        // 端口号
+        /// <summary>
+        /// TCP网络交互客户端对象
+        /// </summary>
+        private TcpClient tcpClient = null;
+        /// <summary>
+        /// 获取或是设置服务器的IP地址
+        /// </summary>
+        /// <remarks>
+        /// 最好实在初始化的时候进行指定,当使用短连接的时候,支持动态更改,切换;当使用长连接后,无法动态更改
+        /// </remarks>
+        public string IpAddress
+        {
+            get
+            {
+                return ipAddress;
+            }
+            set
+            {
+                if (!string.IsNullOrEmpty(value))
+                {
+                    if (!IPAddress.TryParse(value, out _))
+                    {
+                        throw new Exception("Ip地址输入异常,格式不正确!");
+                    }
+                    ipAddress = value;
+                }
+                else
+                {
+                    ipAddress = "127.0.0.1";
+                }
+            }
+        }
+        /// <summary>
+        /// 连接超时时间
+        /// </summary>
+        public int connectTimeOut = 5000;              // 连接超时时间设置
+        /// <summary>
+        /// 接收数据的超时时间
+        /// </summary>
+        public int receiveTimeOut = 10000;            // 数据接收的超时时间
+        /// <summary>
+        /// 发送数据的超时时间
+        /// </summary>
+        public int sendTimeOut = 10000;            // 数据发送的超时时间
+        /// <summary>
+        /// 是否是长连接的状态
+        /// </summary>
+        public bool isPersistentConn = false;         // 是否处于长连接的状态
+        /// <summary>
+        /// 当前的socket是否发生了错误
+        /// </summary>
+        public bool IsSocketError = false;            // 指示长连接的套接字是否处于错误的状态
+        /// <summary>
+        /// 交互的混合锁
+        /// </summary>
+        private readonly SimpleHybirdLock InteractiveLock;      // 一次正常的交互的互斥锁
+        /// <summary>
+        /// 获取或设置服务器的端口号
+        /// </summary>
+        /// <remarks>
+        /// 最好实在初始化的时候进行指定,当使用短连接的时候,支持动态更改,切换;当使用长连接后,无法动态更改
+        /// </remarks>
+        /// <example>
+        /// 动态更改请参照IpAddress属性的更改。
+        /// </example>
+        public int Port
+        {
+            get
+            {
+                return port;
+            }
+            set
+            {
+                port = value;
+            }
+        }
+        /// <summary>
+        /// 网络号,通常为0
+        /// </summary>
+        /// <remarks>
+        /// 依据PLC的配置而配置,如果PLC配置了1,那么此处也填0,如果PLC配置了2,此处就填2,测试不通的话,继续测试0
+        /// </remarks>
+        public byte NetworkNumber { get; set; } = 0x00;
+
+        /// <summary>
+        /// 网络站号,通常为0
+        /// </summary>
+        /// <remarks>
+        /// 依据PLC的配置而配置,如果PLC配置了1,那么此处也填0,如果PLC配置了2,此处就填2,测试不通的话,继续测试0
+        /// </remarks>
+        public byte NetworkStationNumber { get; set; } = 0x00;
+        public Guid Token { get; set; }
+        /// <summary>
+        /// Socket传输中的缓冲池大小
+        /// </summary>
+        private readonly int SocketBufferSize = 4096;
+        /// <summary>
+        /// 获取或设置数据解析的格式,默认DCBA,也即是无修改,可选ABCD,BADC,CDAB,DCBA格式,对于Modbus协议来说,默认ABCD
+        /// </summary>
+        public DataFormatEnum DataFormat { get; set; }
+        /// <summary>
+        /// 是否使用同步的网络通讯
+        /// </summary>
+        public bool UseSynchronousNet { get; set; } = false;
+        #endregion Global Member
+
+        #region Constructor
+
+        /// <summary>
+        /// 实例化一个三菱的Qna兼容3E帧协议的通讯对象
+        /// </summary>
+        /// <param name="ipAddress">PLC的Ip地址</param>
+        /// <param name="port">PLC的端口</param>
+        /// <param name="isPersistentConnected">是否使用Socket长链接。默认值为:true,默认使用长链接</param>
+        public MelsecMcNet(string ipAddress, int port, bool isPersistentConnected = true)
+        {
+            WordLength = 1;
+            IpAddress = ipAddress;
+            Port = port;
+            isPersistentConn = isPersistentConnected;
+            InteractiveLock = new SimpleHybirdLock(); // 实例化数据访问锁
+            DataFormat = DataFormatEnum.DCBA;
+        }
+        #endregion
+
+        #region Connect And Close
+        /// <summary>
+        /// 连接TcpServer端。
+        /// </summary>
+        /// <returns>返回连接结果,如果失败的话(也即IsSuccess为False),包含失败信息</returns>
+        public OperateResult ConnectServer()
+        {
+            OperateResult result = new OperateResult();
+
+            // 重新连接之前,先将旧的数据进行清空
+            tcpClient?.Close();
+            tcpClient?.Dispose();
+
+            OperateResult<TcpClient> rSocket = CreateSocketAndInitialication();
+
+            if (!rSocket.IsSuccess)
+            {
+                IsSocketError = true;
+                rSocket.Content = null;
+                result.Message = rSocket.Message;
+            }
+            else
+            {
+                tcpClient = rSocket.Content;
+                result.IsSuccess = true;
+                result.Message = rSocket.Message;
+            }
+
+            return result;
+        }
+        /// <summary>
+        /// 连接并初始化网络套接字
+        /// </summary>
+        /// <returns>带有socket的结果对象</returns>
+        private OperateResult<TcpClient> CreateSocketAndInitialication()
+        {
+            OperateResult<TcpClient> result = CreateSocketAndConnect(new IPEndPoint(IPAddress.Parse(ipAddress), port), connectTimeOut);
+            if (result.IsSuccess)
+            {
+                // 初始化
+                OperateResult initi = InitializationOnConnect(result.Content);
+                if (!initi.IsSuccess)
+                {
+                    result.Content?.Close();
+                    result.IsSuccess = initi.IsSuccess;
+                    result.CopyErrorFromOther(initi);
+                }
+            }
+            return result;
+        }
+        /// <summary>
+        /// 连接上服务器后需要进行的初始化操作
+        /// </summary>
+        /// <param name="socket">网络套接字</param>
+        /// <returns>是否初始化成功,依据具体的协议进行重写</returns>
+        /// <example>
+        /// 有些协议不需要握手信号,比如三菱的MC协议、Modbus协议;西门子和欧姆龙就存在握手信息;
+        /// </example>
+        private OperateResult InitializationOnConnect(TcpClient socket)
+        {
+            return OperateResult.CreateSuccessResult();
+        }
+        /// <summary>
+        /// 创建一个新的socket对象并连接到远程的地址
+        /// </summary>
+        /// <param name="endPoint">连接的目标终结点</param>
+        /// <param name="timeOut">连接的超时时间</param>
+        /// <returns>返回套接字的封装结果对象</returns>
+        private OperateResult<TcpClient> CreateSocketAndConnect(IPEndPoint endPoint, int timeOut)
+        {
+            tcpClient?.Close();
+            tcpClient = null;
+            tcpClient = new TcpClient
+            {
+                ReceiveTimeout = receiveTimeOut,
+                SendTimeout = sendTimeOut
+            };
+            try
+            {
+                SylTimeOut connectTimeout = new SylTimeOut()
+                {
+                    WorkSocket = tcpClient,
+                    DelayTime = timeOut
+                };
+                Task.Run(() => ThreadPoolCheckTimeOut(connectTimeout));//超时检查
+                tcpClient.Connect(endPoint);
+                connectTimeout.IsSuccessful = true;
+
+                return OperateResult.CreateSuccessResult(tcpClient);
+            }
+            catch (Exception ex)
+            {
+                tcpClient?.Close();
+                return OperateResult.CreateFailedResult<TcpClient>(new OperateResult(ex.HResult, $"【{ex.Message}】-【{ex.StackTrace}】"));
+            }
+        }
+        /// <summary>
+        /// 检查网络套接字是否操作超时,需要对套接字进行封装
+        /// </summary>
+        /// <param name="obj">通常是 <see cref="HslTimeOut"/> 对象 </param>
+        private void ThreadPoolCheckTimeOut(SylTimeOut timeout)
+        {
+            while (!timeout.IsSuccessful)
+            {
+                Thread.Sleep(100);
+                if ((DateTime.Now - timeout.StartTime).TotalMilliseconds > timeout.DelayTime)
+                {
+                    // 连接超时或是验证超时
+                    if (!timeout.IsSuccessful)
+                    {
+                        timeout.Operator?.Invoke();
+                        timeout.WorkSocket?.Close();
+                    }
+                    break;
+                }
+            }
+        }
+        /// <summary>
+        /// 断开服务器的连接
+        /// </summary>
+        /// <returns>关闭连接,不需要查看IsSuccess属性查看</returns>
+        public OperateResult ConnectClose()
+        {
+            InteractiveLock.Enter();
+            // 额外操作
+            OperateResult result = ExtraOnDisconnect(tcpClient.Client);
+            // 关闭信息
+            tcpClient?.Close();
+            tcpClient?.Dispose();
+            InteractiveLock.Leave();
+
+            return result;
+        }
+        /// <summary>
+        /// 在将要和服务器进行断开的情况下额外的操作,需要根据对应协议进行重写
+        /// </summary>
+        /// <param name="socket">网络套接字</param>
+        /// <example>
+        /// 目前暂无相关的示例,组件支持的协议都不用实现这个方法。
+        /// </example>
+        /// <returns>当断开连接时额外的操作结果</returns>
+        private OperateResult ExtraOnDisconnect(Socket socket)
+        {
+            return OperateResult.CreateSuccessResult();
+        }
+        #endregion Connect And Close
+
+        #region Read Write Support
+
+        #region Read Bool
+        /// <summary>
+        /// 从三菱PLC中批量读取位软元件,返回读取结果
+        /// </summary>
+        /// <param name="address">起始地址</param>
+        /// <returns>带成功标志的结果数据对象</returns>
+        /// <example>参照 <see cref="ReadBool(string, ushort)"/> 方法 </example>
+        public OperateResult<bool> ReadBool(string address)
+        {
+            OperateResult<bool[]> read = ReadBool(address, 1);
+            if (!read.IsSuccess) return OperateResult.CreateFailedResult<bool>(read);
+
+            return OperateResult.CreateSuccessResult(read.Content[0]);
+        }
+        /// <summary>
+        /// 从三菱PLC中批量读取位软元件,返回读取结果
+        /// </summary>
+        /// <param name="address">起始地址</param>
+        /// <param name="length">读取的长度</param>
+        /// <returns>带成功标志的结果数据对象</returns>
+        /// <remarks>
+        /// 地址支持的列表参考 <seealso cref="MelsecMcNet"/> 的备注说明
+        /// </remarks>
+        public OperateResult<bool[]> ReadBool(string address, ushort length)
+        {
+            // 分析地址
+            OperateResult<McAddressData> addressResult = McAnalysisAddress(address, length);
+            if (!addressResult.IsSuccess) return OperateResult.CreateFailedResult<bool[]>(addressResult);
+
+            // 获取指令
+            byte[] coreResult = MelsecHelper.BuildReadMcCoreCommand(addressResult.Content, true);
+
+            // 核心交互
+            var read = ReadFromCoreServer(PackMcCommand(coreResult, NetworkNumber, NetworkStationNumber));
+            if (!read.IsSuccess) return OperateResult.CreateFailedResult<bool[]>(read);
+
+            // 错误代码验证
+            ushort errorCode = BitConverter.ToUInt16(read.Content, 9);
+            if (errorCode != 0) return new OperateResult<bool[]>(errorCode, StringResources.Language.MelsecPleaseReferToManulDocument);
+
+            // 数据解析,需要传入是否使用位的参数
+            var extract = ExtractActualData(SoftBasic.BytesArrayRemoveBegin(read.Content, 11), true);
+            if (!extract.IsSuccess) return OperateResult.CreateFailedResult<bool[]>(extract);
+
+            // 转化bool数组
+            return OperateResult.CreateSuccessResult(extract.Content.Select(m => m == 0x01).Take(length).ToArray());
+        }
+        #endregion Read Bool
+
+        #region Read short
+        /// <summary>
+        /// 读取设备的short类型的数据
+        /// </summary>
+        /// <param name="address">起始地址</param>
+        /// <returns>带成功标志的结果数据对象</returns>
+        public OperateResult<short> ReadInt16(string address)
+        {
+            return ByteTransformHelper.GetResultFromArray(ReadInt16(address, 1));
+        }
+        /// <summary>
+        /// 读取设备的short类型的数组
+        /// </summary>
+        /// <param name="address">起始地址</param>
+        /// <param name="length">数组长度</param>
+        /// <returns>带成功标志的结果数据对象</returns>
+        public OperateResult<short[]> ReadInt16(string address, ushort length)
+        {
+            return ByteTransformHelper.GetResultFromBytes(Read(address, (ushort)(length * WordLength)), m => TransInt16(m, 0, length));
+        }
+        /// <summary>
+        /// 从缓存中提取short结果
+        /// </summary>
+        /// <param name="buffer">缓存数据</param>
+        /// <param name="index">索引位置</param>
+        /// <returns>short对象</returns>
+        private short TransInt16(byte[] buffer, int index)
+        {
+            return BitConverter.ToInt16(buffer, index);
+        }
+
+        /// <summary>
+        /// 从缓存中提取short数组结果
+        /// </summary>
+        /// <param name="buffer">缓存数据</param>
+        /// <param name="index">索引位置</param>
+        /// <param name="length">读取的数组长度</param>
+        /// <returns>short数组对象</returns>
+        private short[] TransInt16(byte[] buffer, int index, int length)
+        {
+            short[] tmp = new short[length];
+            for (int i = 0; i < length; i++)
+            {
+                tmp[i] = TransInt16(buffer, index + 2 * i);
+            }
+            return tmp;
+        }
+        #endregion Read short
+
+        #region Read ushort
+        /// <summary>
+        /// 读取设备的ushort数据类型的数据
+        /// </summary>
+        /// <param name="address">起始地址</param>
+        /// <returns>带成功标志的结果数据对象</returns>
+        public OperateResult<ushort> ReadUInt16(string address)
+        {
+            return ByteTransformHelper.GetResultFromArray(ReadUInt16(address, 1));
+        }
+
+
+        /// <summary>
+        /// 读取设备的ushort类型的数组
+        /// </summary>
+        /// <param name="address">起始地址</param>
+        /// <param name="length">数组长度</param>
+        /// <returns>带成功标志的结果数据对象</returns>
+        public OperateResult<ushort[]> ReadUInt16(string address, ushort length)
+        {
+            return ByteTransformHelper.GetResultFromBytes(Read(address, (ushort)(length * WordLength)), m => TransUInt16(m, 0, length));
+        }
+        /// <summary>
+        /// 从缓存中提取ushort结果
+        /// </summary>
+        /// <param name="buffer">缓存数据</param>
+        /// <param name="index">索引位置</param>
+        /// <returns>ushort对象</returns>
+        private ushort TransUInt16(byte[] buffer, int index)
+        {
+            return BitConverter.ToUInt16(buffer, index);
+        }
+
+        /// <summary>
+        /// 从缓存中提取ushort数组结果
+        /// </summary>
+        /// <param name="buffer">缓存数据</param>
+        /// <param name="index">索引位置</param>
+        /// <param name="length">读取的数组长度</param>
+        /// <returns>ushort数组对象</returns>
+        private ushort[] TransUInt16(byte[] buffer, int index, int length)
+        {
+            ushort[] tmp = new ushort[length];
+            for (int i = 0; i < length; i++)
+            {
+                tmp[i] = TransUInt16(buffer, index + 2 * i);
+            }
+            return tmp;
+        }
+        #endregion Read ushort
+
+        #region  Read int
+        /// <summary>
+        /// 读取设备的int类型的数据
+        /// </summary>
+        /// <param name="address">起始地址</param>
+        /// <returns>带成功标志的结果数据对象</returns>
+        public OperateResult<int> ReadInt32(string address)
+        {
+            return ByteTransformHelper.GetResultFromArray(ReadInt32(address, 1));
+        }
+
+        /// <summary>
+        /// 读取设备的int类型的数组
+        /// </summary>
+        /// <param name="address">起始地址</param>
+        /// <param name="length">数组长度</param>
+        /// <returns>带成功标志的结果数据对象</returns>
+        public OperateResult<int[]> ReadInt32(string address, ushort length)
+        {
+            return ByteTransformHelper.GetResultFromBytes(Read(address, (ushort)(length * WordLength * 2)), m => TransInt32(m, 0, length));
+        }
+        /// <summary>
+        /// 从缓存中提取int结果
+        /// </summary>
+        /// <param name="buffer">缓存数据</param>
+        /// <param name="index">索引位置</param>
+        /// <returns>int对象</returns>
+        private int TransInt32(byte[] buffer, int index)
+        {
+            return BitConverter.ToInt32(ByteTransDataFormat4(buffer, index), 0);
+        }
+
+        /// <summary>
+        /// 从缓存中提取int数组结果
+        /// </summary>
+        /// <param name="buffer">缓存数据</param>
+        /// <param name="index">索引位置</param>
+        /// <param name="length">读取的数组长度</param>
+        /// <returns>int数组对象</returns>
+        private int[] TransInt32(byte[] buffer, int index, int length)
+        {
+            int[] tmp = new int[length];
+            for (int i = 0; i < length; i++)
+            {
+                tmp[i] = TransInt32(buffer, index + 4 * i);
+            }
+            return tmp;
+        }
+        #endregion Read int
+
+        #region Read uint
+        /// <summary>
+        /// 读取设备的uint类型的数据
+        /// </summary>
+        /// <param name="address">起始地址</param>
+        /// <returns>带成功标志的结果数据对象</returns>
+        public OperateResult<uint> ReadUInt32(string address)
+        {
+            return ByteTransformHelper.GetResultFromArray(ReadUInt32(address, 1));
+        }
+
+        /// <summary>
+        /// 读取设备的uint类型的数组
+        /// </summary>
+        /// <param name="address">起始地址</param>
+        /// <param name="length">数组长度</param>
+        /// <returns>带成功标志的结果数据对象</returns>
+        /// <example>
+        public OperateResult<uint[]> ReadUInt32(string address, ushort length)
+        {
+            return ByteTransformHelper.GetResultFromBytes(Read(address, (ushort)(length * WordLength * 2)), m => TransUInt32(m, 0, length));
+        }
+        /// <summary>
+        /// 从缓存中提取uint结果
+        /// </summary>
+        /// <param name="buffer">缓存数据</param>
+        /// <param name="index">索引位置</param>
+        /// <returns>uint对象</returns>
+        private uint TransUInt32(byte[] buffer, int index)
+        {
+            return BitConverter.ToUInt32(ByteTransDataFormat4(buffer, index), 0);
+        }
+
+        /// <summary>
+        /// 从缓存中提取uint数组结果
+        /// </summary>
+        /// <param name="buffer">缓存数据</param>
+        /// <param name="index">索引位置</param>
+        /// <param name="length">读取的数组长度</param>
+        /// <returns>uint数组对象</returns>
+        private uint[] TransUInt32(byte[] buffer, int index, int length)
+        {
+            uint[] tmp = new uint[length];
+            for (int i = 0; i < length; i++)
+            {
+                tmp[i] = TransUInt32(buffer, index + 4 * i);
+            }
+            return tmp;
+        }
+        #endregion Read uint
+
+        #region Read long
+        /// <summary>
+        /// 读取设备的long类型的数据
+        /// </summary>
+        /// <param name="address">起始地址</param>
+        /// <returns>带成功标志的结果数据对象</returns>
+        public OperateResult<long> ReadInt64(string address)
+        {
+            return ByteTransformHelper.GetResultFromArray(ReadInt64(address, 1));
+        }
+
+        /// <summary>
+        /// 读取设备的long类型的数组
+        /// </summary>
+        /// <param name="address">起始地址</param>
+        /// <param name="length">数组长度</param>
+        /// <returns>带成功标志的结果数据对象</returns>
+        public OperateResult<long[]> ReadInt64(string address, ushort length)
+        {
+            return ByteTransformHelper.GetResultFromBytes(Read(address, (ushort)(length * WordLength * 4)), m => TransInt64(m, 0, length));
+        }
+        /// <summary>
+        /// 从缓存中提取long结果
+        /// </summary>
+        /// <param name="buffer">缓存数据</param>
+        /// <param name="index">索引位置</param>
+        /// <returns>long对象</returns>
+        private long TransInt64(byte[] buffer, int index)
+        {
+            return BitConverter.ToInt64(ByteTransDataFormat8(buffer, index), 0);
+        }
+
+        /// <summary>
+        /// 从缓存中提取long数组结果
+        /// </summary>
+        /// <param name="buffer">缓存数据</param>
+        /// <param name="index">索引位置</param>
+        /// <param name="length">读取的数组长度</param>
+        /// <returns>long数组对象</returns>
+        private long[] TransInt64(byte[] buffer, int index, int length)
+        {
+            long[] tmp = new long[length];
+            for (int i = 0; i < length; i++)
+            {
+                tmp[i] = TransInt64(buffer, index + 8 * i);
+            }
+            return tmp;
+        }
+        #endregion Read long
+
+        #region Read ulong
+        /// <summary>
+        /// 读取设备的ulong类型的数据
+        /// </summary>
+        /// <param name="address">起始地址</param>
+        /// <returns>带成功标志的结果数据对象</returns>
+        public OperateResult<ulong> ReadUInt64(string address)
+        {
+            return ByteTransformHelper.GetResultFromArray(ReadUInt64(address, 1));
+        }
+
+        /// <summary>
+        /// 读取设备的ulong类型的数组
+        /// </summary>
+        /// <param name="address">起始地址</param>
+        /// <param name="length">数组长度</param>
+        /// <returns>带成功标志的结果数据对象</returns>
+        public OperateResult<ulong[]> ReadUInt64(string address, ushort length)
+        {
+            return ByteTransformHelper.GetResultFromBytes(Read(address, (ushort)(length * WordLength * 4)), m => TransUInt64(m, 0, length));
+        }
+
+        /// <summary>
+        /// 从缓存中提取ulong结果
+        /// </summary>
+        /// <param name="buffer">缓存数据</param>
+        /// <param name="index">索引位置</param>
+        /// <returns>ulong对象</returns>
+        private ulong TransUInt64(byte[] buffer, int index)
+        {
+            return BitConverter.ToUInt64(ByteTransDataFormat8(buffer, index), 0);
+        }
+
+        /// <summary>
+        /// 从缓存中提取ulong数组结果
+        /// </summary>
+        /// <param name="buffer">缓存数据</param>
+        /// <param name="index">索引位置</param>
+        /// <param name="length">读取的数组长度</param>
+        /// <returns>ulong数组对象</returns>
+        private ulong[] TransUInt64(byte[] buffer, int index, int length)
+        {
+            ulong[] tmp = new ulong[length];
+            for (int i = 0; i < length; i++)
+            {
+                tmp[i] = TransUInt64(buffer, index + 8 * i);
+            }
+            return tmp;
+        }
+        #endregion Read ulong
+
+        #region Read float
+        /// <summary>
+        /// 读取设备的float类型的数据
+        /// </summary>
+        /// <param name="address">起始地址</param>
+        /// <returns>带成功标志的结果数据对象</returns>
+        public OperateResult<float> ReadFloat(string address)
+        {
+            return ByteTransformHelper.GetResultFromArray(ReadFloat(address, 1));
+        }
+
+
+        /// <summary>
+        /// 读取设备的float类型的数组
+        /// </summary>
+        /// <param name="address">起始地址</param>
+        /// <param name="length">数组长度</param>
+        /// <returns>带成功标志的结果数据对象</returns>
+        public OperateResult<float[]> ReadFloat(string address, ushort length)
+        {
+            return ByteTransformHelper.GetResultFromBytes(Read(address, (ushort)(length * WordLength * 2)), m => TransSingle(m, 0, length));
+        }
+        /// <summary>
+        /// 从缓存中提取float结果
+        /// </summary>
+        /// <param name="buffer">缓存对象</param>
+        /// <param name="index">索引位置</param>
+        /// <returns>float对象</returns>
+        private float TransSingle(byte[] buffer, int index)
+        {
+            return BitConverter.ToSingle(ByteTransDataFormat4(buffer, index), 0);
+        }
+
+        /// <summary>
+        /// 从缓存中提取float数组结果
+        /// </summary>
+        /// <param name="buffer">缓存数据</param>
+        /// <param name="index">索引位置</param>
+        /// <param name="length">读取的数组长度</param>
+        /// <returns>float数组对象</returns>
+        private float[] TransSingle(byte[] buffer, int index, int length)
+        {
+            float[] tmp = new float[length];
+            for (int i = 0; i < length; i++)
+            {
+                tmp[i] = TransSingle(buffer, index + 4 * i);
+            }
+            return tmp;
+        }
+        #endregion Read float
+
+        #region Read double
+        /// <summary>
+        /// 读取设备的double类型的数据
+        /// </summary>
+        /// <param name="address">起始地址</param>
+        /// <returns>带成功标志的结果数据对象</returns>
+        public OperateResult<double> ReadDouble(string address)
+        {
+            return ByteTransformHelper.GetResultFromArray(ReadDouble(address, 1));
+        }
+
+        /// <summary>
+        /// 读取设备的double类型的数组
+        /// </summary>
+        /// <param name="address">起始地址</param>
+        /// <param name="length">数组长度</param>
+        /// <returns>带成功标志的结果数据对象</returns>
+        public OperateResult<double[]> ReadDouble(string address, ushort length)
+        {
+            return ByteTransformHelper.GetResultFromBytes(Read(address, (ushort)(length * WordLength * 4)), m => TransDouble(m, 0, length));
+        }
+        /// <summary>
+        /// 从缓存中提取double结果
+        /// </summary>
+        /// <param name="buffer">缓存对象</param>
+        /// <param name="index">索引位置</param>
+        /// <returns>double对象</returns>
+        private double TransDouble(byte[] buffer, int index)
+        {
+            return BitConverter.ToDouble(ByteTransDataFormat8(buffer, index), 0);
+        }
+
+        /// <summary>
+        /// 从缓存中提取double数组结果
+        /// </summary>
+        /// <param name="buffer">缓存对象</param>
+        /// <param name="index">索引位置</param>
+        /// <param name="length">读取的数组长度</param>
+        /// <returns>double数组对象</returns>
+        private double[] TransDouble(byte[] buffer, int index, int length)
+        {
+            double[] tmp = new double[length];
+            for (int i = 0; i < length; i++)
+            {
+                tmp[i] = TransDouble(buffer, index + 8 * i);
+            }
+            return tmp;
+        }
+        #endregion Read double
+
+        #region Read string
+        /// <summary>
+        /// 读取设备的字符串数据,编码为ASCII
+        /// </summary>
+        /// <param name="address">起始地址</param>
+        /// <param name="length">地址长度</param>
+        /// <returns>带成功标志的结果数据对象</returns>
+        /// <example>
+        /// 以下为三菱的连接对象示例,其他的设备读写情况参照下面的代码:
+        /// <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\Core\NetworkDeviceBase.cs" region="ReadString" title="String类型示例" />
+        /// </example>
+        public OperateResult<string> ReadString(string address, ushort length)
+        {
+            return ByteTransformHelper.GetResultFromBytes(Read(address, length), m => TransString(m, 0, m.Length, Encoding.ASCII));
+        }
+
+        /// <summary>
+        /// 读取设备的字符串数据,编码为指定的编码信息
+        /// </summary>
+        /// <param name="address">起始地址</param>
+        /// <param name="length">地址长度</param>
+        /// <param name="encoding">编码机制</param>
+        /// <returns>带成功标志的结果数据对象</returns>
+        /// <example>
+        /// 以下为三菱的连接对象示例,其他的设备读写情况参照下面的代码:
+        /// <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\Core\NetworkDeviceBase.cs" region="ReadString" title="String类型示例" />
+        /// </example>
+        public OperateResult<string> ReadString(string address, ushort length, Encoding encoding)
+        {
+            return ByteTransformHelper.GetResultFromBytes(Read(address, length), m => TransString(m, 0, m.Length, encoding));
+        }
+        /// <summary>
+        /// 从缓存中提取string结果,使用指定的编码
+        /// </summary>
+        /// <param name="buffer">缓存对象</param>
+        /// <param name="index">索引位置</param>
+        /// <param name="length">byte数组长度</param>
+        /// <param name="encoding">字符串的编码</param>
+        /// <returns>string对象</returns>
+        private string TransString(byte[] buffer, int index, int length, Encoding encoding)
+        {
+            byte[] tmp = TransByte(buffer, index, length);
+            return encoding.GetString(tmp);
+        }
+        #endregion Read string
+
+        #region Read byte array 读取PLC数据 核心代码
+        public OperateResult<byte> Read(string address)
+        {
+            OperateResult<byte[]> read = Read(address, 1);
+            if (!read.IsSuccess) return OperateResult.CreateFailedResult<byte>(read);
+
+            return OperateResult.CreateSuccessResult(read.Content[0]);
+        }
+        /// <summary>
+        /// 从三菱PLC中读取想要的数据,输入地址,按照字单位读取,返回读取结果
+        /// </summary>
+        /// <param name="address">读取地址,格式为"M100","D100","W1A0"</param>
+        /// <param name="length">读取的数据长度,字最大值960,位最大值7168</param>
+        /// <returns>带成功标志的结果数据对象</returns>
+        /// <remarks>
+        /// 地址支持的列表参考 <seealso cref="MelsecMcNet"/> 的备注说明
+        /// </remarks>
+        public OperateResult<byte[]> Read(string address, ushort length)
+        {
+            // 分析地址
+            OperateResult<McAddressData> addressResult = McAnalysisAddress(address, length);
+            if (!addressResult.IsSuccess) return OperateResult.CreateFailedResult<byte[]>(addressResult);
+
+            List<byte> bytesContent = new List<byte>();
+            ushort alreadyFinished = 0;
+            while (alreadyFinished < length)
+            {
+                ushort readLength = (ushort)Math.Min(length - alreadyFinished, 900);
+                addressResult.Content.Length = readLength;
+                OperateResult<byte[]> read = ReadAddressData(addressResult.Content);
+                if (!read.IsSuccess) return read;
+
+                bytesContent.AddRange(read.Content);
+                alreadyFinished += readLength;
+
+                // 字的话就是正常的偏移位置,如果是位的话,就转到位的数据
+                if (addressResult.Content.McDataType.DataType == 0)
+                    addressResult.Content.AddressStart += readLength;
+                else
+                    addressResult.Content.AddressStart += readLength * 16;
+            }
+            return OperateResult.CreateSuccessResult(bytesContent.ToArray());
+        }
+        /// <summary>
+        /// 分析地址的方法,允许派生类里进行重写操作
+        /// </summary>
+        /// <param name="address">地址信息</param>
+        /// <param name="length">数据长度</param>
+        /// <returns>解析后的数据信息</returns>
+        private OperateResult<McAddressData> McAnalysisAddress(string address, ushort length)
+        {
+            return McAddressData.ParseMelsecFrom(address, length);
+        }
+        private OperateResult<byte[]> ReadAddressData(McAddressData addressData)
+        {
+            byte[] coreResult = MelsecHelper.BuildReadMcCoreCommand(addressData, false);
+
+            // 核心交互
+            var read = ReadFromCoreServer(PackMcCommand(coreResult, this.NetworkNumber, this.NetworkStationNumber));
+            if (!read.IsSuccess) return OperateResult.CreateFailedResult<byte[]>(read);
+
+            // 错误代码验证
+            ushort errorCode = BitConverter.ToUInt16(read.Content, 9);
+            if (errorCode != 0) return new OperateResult<byte[]>(errorCode, StringResources.Language.MelsecPleaseReferToManulDocument);
+
+            // 数据解析,需要传入是否使用位的参数
+            return ExtractActualData(SoftBasic.BytesArrayRemoveBegin(read.Content, 11), false);
+        }
+        /// <summary>
+        /// 使用底层的数据报文来通讯,传入需要发送的消息,返回一条完整的数据指令
+        /// </summary>
+        /// <param name="send">发送的完整的报文信息</param>
+        /// <returns>接收的完整的报文信息</returns>
+        /// <remarks>
+        public OperateResult<byte[]> ReadFromCoreServer(byte[] send)
+        {
+            var result = new OperateResult<byte[]>();
+
+            InteractiveLock.Enter();
+
+            // 获取有用的网络通道,如果没有,就建立新的连接
+            OperateResult<TcpClient> resultSocket = GetAvailableSocket();
+            if (!resultSocket.IsSuccess)
+            {
+                IsSocketError = true;
+                InteractiveLock.Leave();
+                result.CopyErrorFromOther(resultSocket);
+                return result;
+            }
+
+            OperateResult<byte[]> read = ReadFromCoreServer(resultSocket.Content, send);
+
+            if (read.IsSuccess)
+            {
+                IsSocketError = false;
+                result.IsSuccess = read.IsSuccess;
+                result.Content = read.Content;
+                result.Message = StringResources.Language.SuccessText;
+            }
+            else
+            {
+                IsSocketError = true;
+                result.CopyErrorFromOther(read);
+            }
+
+            ExtraAfterReadFromCoreServer(read);
+
+            InteractiveLock.Leave();
+            if (!isPersistentConn) resultSocket.Content?.Close();
+            return result;
+        }
+        /// <summary>
+        /// 在其他指定的套接字上,使用报文来通讯,传入需要发送的消息,返回一条完整的数据指令
+        /// </summary>
+        /// <param name="socket">指定的套接字</param>
+        /// <param name="send">发送的完整的报文信息</param>
+        /// <remarks>
+        /// 无锁的基于套接字直接进行叠加协议的操作。
+        /// </remarks>
+        /// <returns>接收的完整的报文信息</returns>
+        public OperateResult<byte[]> ReadFromCoreServer(TcpClient socket, byte[] send)
+        {
+            INetMessage netMessage = new MelsecQnA3EBinaryMessage
+            {
+                SendBytes = send
+            };
+
+            // send
+            OperateResult sendResult = Send(socket, send);
+            if (!sendResult.IsSuccess)
+            {
+                socket?.Close();
+                return OperateResult.CreateFailedResult<byte[]>(sendResult);
+            }
+
+            if (receiveTimeOut < 0) return OperateResult.CreateSuccessResult(new byte[0]);
+
+            // receive msg
+            OperateResult<byte[]> resultReceive = ReceiveByMessage(socket, receiveTimeOut, netMessage);
+            if (!resultReceive.IsSuccess)
+            {
+                socket?.Close();
+                return new OperateResult<byte[]>(StringResources.Language.ReceiveDataTimeout + receiveTimeOut);
+            }
+
+            // check
+            if (!netMessage.CheckHeadBytesLegal(Token.ToByteArray()))
+            {
+                socket?.Close();
+                return new OperateResult<byte[]>(StringResources.Language.CommandHeadCodeCheckFailed);
+            }
+
+            // Success
+            return OperateResult.CreateSuccessResult(resultReceive.Content);
+        }
+        /// <summary>
+        /// 发送消息给套接字,直到完成的时候返回
+        /// </summary>
+        /// <param name="socket">网络套接字</param>
+        /// <param name="data">字节数据</param>
+        /// <returns>发送是否成功的结果</returns>
+        protected OperateResult Send(TcpClient socket, byte[] data)
+        {
+            if (data == null) return OperateResult.CreateSuccessResult();
+            try
+            {
+                NetworkStream stream = socket.GetStream();
+                stream.Write(data, 0, data.Length);
+                //socket.Client.Send(data);
+                return OperateResult.CreateSuccessResult();
+            }
+            catch (Exception ex)
+            {
+                socket?.Close();
+                return new OperateResult<byte[]>(ex.Message);
+            }
+        }
+        /// <summary>
+        /// 接收一条完整的 <seealso cref="INetMessage"/> 数据内容 ->
+        /// Receive a complete <seealso cref="INetMessage"/> data content
+        /// </summary>
+        /// <param name="socket">网络的套接字</param>
+        /// <param name="timeOut">超时时间</param>
+        /// <param name="netMessage">消息的格式定义</param>
+        /// <returns>带有是否成功的byte数组对象</returns>
+        protected OperateResult<byte[]> ReceiveByMessage(TcpClient socket, int timeOut, INetMessage netMessage)
+        {
+            SylTimeOut receiveTimeout = new SylTimeOut()
+            {
+                WorkSocket = tcpClient,
+                DelayTime = timeOut
+            };
+            Task.Run(() => ThreadPoolCheckTimeOut(receiveTimeout));//超时检查
+            // 接收指令头
+            OperateResult<byte[]> headResult = Receive(socket, netMessage.ProtocolHeadBytesLength);
+            if (!headResult.IsSuccess)
+            {
+                receiveTimeout.IsSuccessful = true;
+                return headResult;
+            }
+
+            netMessage.HeadBytes = headResult.Content;
+            int contentLength = netMessage.GetContentLengthByHeadBytes();
+            if (contentLength <= 0)
+            {
+                receiveTimeout.IsSuccessful = true;
+                return headResult;
+            }
+
+            OperateResult<byte[]> contentResult = Receive(socket, contentLength);
+            if (!contentResult.IsSuccess)
+            {
+                receiveTimeout.IsSuccessful = true;
+                return contentResult;
+            }
+
+            receiveTimeout.IsSuccessful = true;
+            netMessage.ContentBytes = contentResult.Content;
+            return OperateResult.CreateSuccessResult(SoftBasic.SpliceTwoByteArray(headResult.Content, contentResult.Content));
+        }
+        /// <summary>
+        /// 接收固定长度的字节数组
+        /// </summary>
+        /// <remarks>
+        /// Receive Special Length Bytes
+        /// </remarks>
+        /// <param name="socket">网络通讯的套接字</param>
+        /// <param name="length">准备接收的数据长度</param>
+        /// <returns>包含了字节数据的结果类</returns>
+        protected OperateResult<byte[]> Receive(TcpClient socket, int length)
+        {
+            if (length == 0) return OperateResult.CreateSuccessResult(new byte[0]);
+
+            if (UseSynchronousNet)
+            {
+                try
+                {
+                    byte[] data = ReadBytesFromSocket(socket, length);
+                    return OperateResult.CreateSuccessResult(data);
+                }
+                catch (Exception ex)
+                {
+                    socket?.Close();
+                    return new OperateResult<byte[]>($"【{ex.Message}】---【{ex.StackTrace}】");
+                }
+            }
+
+            NetworkStream stream = socket.GetStream();
+            OperateResult<byte[]> result = new OperateResult<byte[]>();
+            ManualResetEvent receiveDone = null;
+            StateObject state = null;
+            try
+            {
+                receiveDone = new ManualResetEvent(false);
+                state = new StateObject(length);
+            }
+            catch (Exception ex)
+            {
+                return new OperateResult<byte[]>($"【{ex.Message}】---【{ex.StackTrace}】");
+            }
+
+
+            try
+            {
+                state.WaitDone = receiveDone;
+                state.WorkSocket = socket;
+
+                // Begin receiving the data from the remote device.
+                //socket.BeginReceive(state.Buffer, state.AlreadyDealLength,state.DataLength - state.AlreadyDealLength, SocketFlags.None,new AsyncCallback(ReceiveCallback), state);
+                stream.BeginRead(state.Buffer, state.AlreadyDealLength, state.DataLength - state.AlreadyDealLength, new AsyncCallback(ReceiveCallback), state);
+            }
+            catch (Exception ex)
+            {
+                // 发生了错误,直接返回
+                result.Message = $"【{ex.Message}】---【{ex.StackTrace}】";
+                receiveDone.Close();
+                socket?.Close();
+                return result;
+            }
+
+
+
+            // 等待接收完成,或是发生异常
+            receiveDone.WaitOne();
+            receiveDone.Close();
+            stream.Flush();
+
+
+            // 接收数据失败
+            if (state.IsError)
+            {
+                socket?.Close();
+                result.Message = state.ErrerMsg;
+                return result;
+            }
+
+
+            // 远程关闭了连接
+            if (state.IsClose)
+            {
+                // result.IsSuccess = true;
+                result.Message = StringResources.Language.RemoteClosedConnection;
+                socket?.Close();
+                return result;
+            }
+
+
+            // 正常接收到数据
+            result.Content = state.Buffer;
+            result.IsSuccess = true;
+            state.Clear();
+            state = null;
+            return result;
+        }
+
+        #region 异步网络通讯
+
+        private void ReceiveCallback(IAsyncResult ar)
+        {
+            if (ar.AsyncState is StateObject state)
+            {
+                try
+                {
+                    //Socket client = state.WorkSocket;
+                    NetworkStream stream = state.WorkSocket.GetStream();
+                    int bytesRead = stream.EndRead(ar);
+
+                    if (bytesRead > 0)
+                    {
+                        // 接收到了数据
+                        state.AlreadyDealLength += bytesRead;
+                        if (state.AlreadyDealLength < state.DataLength)
+                        {
+                            // 获取接下来的所有的数据
+                            //client.BeginReceive(state.Buffer, state.AlreadyDealLength,state.DataLength - state.AlreadyDealLength, SocketFlags.None,new AsyncCallback(ReceiveCallback), state);
+                            stream.BeginRead(state.Buffer, state.AlreadyDealLength, state.DataLength - state.AlreadyDealLength, new AsyncCallback(ReceiveCallback), state);
+                        }
+                        else
+                        {
+                            // 接收到了所有的数据,通知接收数据的线程继续
+                            state.WaitDone.Set();
+                        }
+                    }
+                    else
+                    {
+                        // 对方关闭了网络通讯
+                        state.IsClose = true;
+                        state.WaitDone.Set();
+                    }
+                }
+                catch (Exception ex)
+                {
+                    state.IsError = true;
+                    state.ErrerMsg = $"【{ex.Message}】---【{ex.StackTrace}】";
+                    state.WaitDone.Set();
+                }
+            }
+        }
+
+        #endregion 异步网络通讯
+
+        #region 同步网络通讯
+        private byte[] ReadBytesFromSocket(TcpClient socket, int receive)
+        {
+            return ReadBytesFromSocket(socket, receive, null, false, false);
+        }
+        /// <summary>
+        /// 读取socket数据的基础方法,只适合用来接收指令头,或是同步数据
+        /// </summary>
+        /// <param name="socket">通信对象</param>
+        /// <param name="receive">接收的长度</param>
+        /// <param name="report">用于报告接收进度的对象</param>
+        /// <param name="reportByPercent">是否按照百分比报告进度</param>
+        /// <param name="response">是否回发接收数据长度</param>
+        /// <returns>接收到的字节数据</returns>
+        /// <exception cref="ArgumentNullException"></exception>
+        /// <exception cref="SocketException"></exception>
+        /// <exception cref="ObjectDisposedException"></exception>
+        /// <exception cref="System.Security.SecurityException"></exception>
+        /// <example>
+        /// 接收数据的举例,输出报告,不根据百分比来产生报告,不回复接收进度。
+        /// </example>
+        public byte[] ReadBytesFromSocket(TcpClient socket, int receive, Action<long, long> report, bool reportByPercent, bool response)
+        {
+            byte[] bytes_receive = new byte[receive];
+            int count_receive = 0;
+            long percent = 0;
+            NetworkStream stream = socket.GetStream();
+            while (count_receive < receive)
+            {
+                // 分割成2KB来接收数据
+                int receive_length = (receive - count_receive) >= SocketBufferSize ? SocketBufferSize : (receive - count_receive);
+                //count_receive += socket.Client.Receive(bytes_receive, count_receive, receive_length, SocketFlags.None);
+                count_receive += stream.Read(bytes_receive, count_receive, receive_length);
+                if (reportByPercent)
+                {
+                    long percentCurrent = (long)count_receive * 100 / receive;
+                    if (percent != percentCurrent)
+                    {
+                        percent = percentCurrent;
+                        // 报告进度
+                        report?.Invoke(count_receive, receive);
+                    }
+                }
+                else
+                {
+                    // 报告进度
+                    report?.Invoke(count_receive, receive);
+                }
+                // 回发进度
+                if (response) socket.Client.Send(BitConverter.GetBytes((long)count_receive));
+            }
+            stream.Close();
+            return bytes_receive;
+        }
+        #endregion 同步网络通讯
+
+        /// <summary>
+        /// 和服务器交互完成的时候调用的方法,无论是成功或是失败,都将会调用,具体的操作需要重写实现
+        /// </summary>
+        /// <param name="read">读取结果</param>
+        private void ExtraAfterReadFromCoreServer(OperateResult read)
+        {
+
+        }
+        /// <summary>
+        /// 获取本次操作的可用的网络套接字
+        /// </summary>
+        /// <returns>是否成功,如果成功,使用这个套接字</returns>
+        protected OperateResult<TcpClient> GetAvailableSocket()
+        {
+            if (isPersistentConn) // 长连接模式
+            {                
+                if (IsSocketError || tcpClient == null)
+                {
+                    OperateResult connect = ConnectServer();
+                    if (!connect.IsSuccess)
+                    {
+                        IsSocketError = true;
+                        return OperateResult.CreateFailedResult<TcpClient>(connect);
+                    }
+                    else
+                    {
+                        IsSocketError = false;
+                        return OperateResult.CreateSuccessResult(tcpClient);
+                    }
+                }
+                else
+                {
+                    return OperateResult.CreateSuccessResult(tcpClient);
+                }
+            }
+            else // 短连接模式
+            {                
+                return CreateSocketAndInitialication();
+            }
+        }
+        #endregion Read byte array 读取PLC数据 核心代码
+
+        #region Common method Helper
+        /// <summary>
+        /// 反转多字节的数据信息
+        /// </summary>
+        /// <param name="value">数据字节</param>
+        /// <param name="index">起始索引,默认值为0</param>
+        /// <returns>实际字节信息</returns>
+        private byte[] ByteTransDataFormat4(byte[] value, int index = 0)
+        {
+            byte[] buffer = new byte[4];
+            switch (DataFormat)
+            {
+                case DataFormatEnum.ABCD:
+                    {
+                        buffer[0] = value[index + 3];
+                        buffer[1] = value[index + 2];
+                        buffer[2] = value[index + 1];
+                        buffer[3] = value[index + 0];
+                        break;
+                    }
+                case DataFormatEnum.BADC:
+                    {
+                        buffer[0] = value[index + 2];
+                        buffer[1] = value[index + 3];
+                        buffer[2] = value[index + 0];
+                        buffer[3] = value[index + 1];
+                        break;
+                    }
+
+                case DataFormatEnum.CDAB:
+                    {
+                        buffer[0] = value[index + 1];
+                        buffer[1] = value[index + 0];
+                        buffer[2] = value[index + 3];
+                        buffer[3] = value[index + 2];
+                        break;
+                    }
+                case DataFormatEnum.DCBA:
+                    {
+                        buffer[0] = value[index + 0];
+                        buffer[1] = value[index + 1];
+                        buffer[2] = value[index + 2];
+                        buffer[3] = value[index + 3];
+                        break;
+                    }
+            }
+            return buffer;
+        }
+        /// <summary>
+        /// 反转多字节的数据信息
+        /// </summary>
+        /// <param name="value">数据字节</param>
+        /// <param name="index">起始索引,默认值为0</param>
+        /// <returns>实际字节信息</returns>
+        private byte[] ByteTransDataFormat8(byte[] value, int index = 0)
+        {
+            byte[] buffer = new byte[8];
+            switch (DataFormat)
+            {
+                case DataFormatEnum.ABCD:
+                    {
+                        buffer[0] = value[index + 7];
+                        buffer[1] = value[index + 6];
+                        buffer[2] = value[index + 5];
+                        buffer[3] = value[index + 4];
+                        buffer[4] = value[index + 3];
+                        buffer[5] = value[index + 2];
+                        buffer[6] = value[index + 1];
+                        buffer[7] = value[index + 0];
+                        break;
+                    }
+                case DataFormatEnum.BADC:
+                    {
+                        buffer[0] = value[index + 6];
+                        buffer[1] = value[index + 7];
+                        buffer[2] = value[index + 4];
+                        buffer[3] = value[index + 5];
+                        buffer[4] = value[index + 2];
+                        buffer[5] = value[index + 3];
+                        buffer[6] = value[index + 0];
+                        buffer[7] = value[index + 1];
+                        break;
+                    }
+
+                case DataFormatEnum.CDAB:
+                    {
+                        buffer[0] = value[index + 1];
+                        buffer[1] = value[index + 0];
+                        buffer[2] = value[index + 3];
+                        buffer[3] = value[index + 2];
+                        buffer[4] = value[index + 5];
+                        buffer[5] = value[index + 4];
+                        buffer[6] = value[index + 7];
+                        buffer[7] = value[index + 6];
+                        break;
+                    }
+                case DataFormatEnum.DCBA:
+                    {
+                        buffer[0] = value[index + 0];
+                        buffer[1] = value[index + 1];
+                        buffer[2] = value[index + 2];
+                        buffer[3] = value[index + 3];
+                        buffer[4] = value[index + 4];
+                        buffer[5] = value[index + 5];
+                        buffer[6] = value[index + 6];
+                        buffer[7] = value[index + 7];
+                        break;
+                    }
+            }
+            return buffer;
+        }
+        /// <summary>
+        /// 将MC协议的核心报文打包成一个可以直接对PLC进行发送的原始报文
+        /// </summary>
+        /// <param name="mcCore">MC协议的核心报文</param>
+        /// <param name="networkNumber">网络号</param>
+        /// <param name="networkStationNumber">网络站号</param>
+        /// <returns>原始报文信息</returns>
+        private byte[] PackMcCommand(byte[] mcCore, byte networkNumber = 0, byte networkStationNumber = 0)
+        {
+            byte[] _PLCCommand = new byte[11 + mcCore.Length];
+            _PLCCommand[0] = 0x50;                                               // 副标题
+            _PLCCommand[1] = 0x00;
+            _PLCCommand[2] = networkNumber;                                      // 网络号
+            _PLCCommand[3] = 0xFF;                                               // PLC编号
+            _PLCCommand[4] = 0xFF;                                               // 目标模块IO编号
+            _PLCCommand[5] = 0x03;
+            _PLCCommand[6] = networkStationNumber;                               // 目标模块站号
+            _PLCCommand[7] = (byte)((_PLCCommand.Length - 9) % 256);             // 请求数据长度
+            _PLCCommand[8] = (byte)((_PLCCommand.Length - 9) / 256);
+            _PLCCommand[9] = 0x0A;                                               // CPU监视定时器
+            _PLCCommand[10] = 0x00;
+            mcCore.CopyTo(_PLCCommand, 11);
+
+            return _PLCCommand;
+        }
+        /// <summary>
+        /// 从PLC反馈的数据中提取出实际的数据内容,需要传入反馈数据,是否位读取
+        /// </summary>
+        /// <param name="response">反馈的数据内容</param>
+        /// <param name="isBit">是否位读取</param>
+        /// <returns>解析后的结果对象</returns>
+        private OperateResult<byte[]> ExtractActualData(byte[] response, bool isBit)
+        {
+            if (isBit)
+            {
+                // 位读取
+                byte[] Content = new byte[response.Length * 2];
+                for (int i = 0; i < response.Length; i++)
+                {
+                    if ((response[i] & 0x10) == 0x10)
+                    {
+                        Content[i * 2 + 0] = 0x01;
+                    }
+
+                    if ((response[i] & 0x01) == 0x01)
+                    {
+                        Content[i * 2 + 1] = 0x01;
+                    }
+                }
+
+                return OperateResult.CreateSuccessResult(Content);
+            }
+            else
+            {
+                // 字读取
+                return OperateResult.CreateSuccessResult(response);
+            }
+        }
+        /// <summary>
+        /// short数组变量转化缓存数据
+        /// </summary>
+        /// <param name="values">等待转化的数组</param>
+        /// <returns>buffer数据</returns>
+        private byte[] TransByte(short[] values)
+        {
+            if (values == null) return null;
+            byte[] buffer = new byte[values.Length * 2];
+            for (int i = 0; i < values.Length; i++)
+            {
+                BitConverter.GetBytes(values[i]).CopyTo(buffer, 2 * i);
+            }
+            return buffer;
+        }
+        /// <summary>
+        /// 从缓存中提取byte数组结果
+        /// </summary>
+        /// <param name="buffer">缓存数据</param>
+        /// <param name="index">索引位置</param>
+        /// <param name="length">读取的数组长度</param>
+        /// <returns>byte数组对象</returns>
+        private byte[] TransByte(byte[] buffer, int index, int length)
+        {
+            byte[] tmp = new byte[length];
+            Array.Copy(buffer, index, tmp, 0, length);
+            return tmp;
+        }
+        /// <summary>
+        /// ushort数组变量转化缓存数据
+        /// </summary>
+        /// <param name="values">等待转化的数组</param>
+        /// <returns>buffer数据</returns>
+        private byte[] TransByte(ushort[] values)
+        {
+            if (values == null) return null;
+
+            byte[] buffer = new byte[values.Length * 2];
+            for (int i = 0; i < values.Length; i++)
+            {
+                BitConverter.GetBytes(values[i]).CopyTo(buffer, 2 * i);
+            }
+
+            return buffer;
+        }
+        /// <summary>
+        /// int数组变量转化缓存数据
+        /// </summary>
+        /// <param name="values">等待转化的数组</param>
+        /// <returns>buffer数据</returns>
+        private byte[] TransByte(int[] values)
+        {
+            if (values == null) return null;
+
+            byte[] buffer = new byte[values.Length * 4];
+            for (int i = 0; i < values.Length; i++)
+            {
+                ByteTransDataFormat4(BitConverter.GetBytes(values[i])).CopyTo(buffer, 4 * i);
+            }
+
+            return buffer;
+        }
+        /// <summary>
+        /// uint数组变量转化缓存数据
+        /// </summary>
+        /// <param name="values">等待转化的数组</param>
+        /// <returns>buffer数据</returns>
+        private byte[] TransByte(uint[] values)
+        {
+            if (values == null) return null;
+
+            byte[] buffer = new byte[values.Length * 4];
+            for (int i = 0; i < values.Length; i++)
+            {
+                ByteTransDataFormat4(BitConverter.GetBytes(values[i])).CopyTo(buffer, 4 * i);
+            }
+
+            return buffer;
+        }
+        /// <summary>
+        /// long数组变量转化缓存数据
+        /// </summary>
+        /// <param name="values">等待转化的数组</param>
+        /// <returns>buffer数据</returns>
+        private byte[] TransByte(long[] values)
+        {
+            if (values == null) return null;
+
+            byte[] buffer = new byte[values.Length * 8];
+            for (int i = 0; i < values.Length; i++)
+            {
+                ByteTransDataFormat8(BitConverter.GetBytes(values[i])).CopyTo(buffer, 8 * i);
+            }
+
+            return buffer;
+        }
+        /// <summary>
+        /// ulong数组变量转化缓存数据
+        /// </summary>
+        /// <param name="values">等待转化的数组</param>
+        /// <returns>buffer数据</returns>
+        private byte[] TransByte(ulong[] values)
+        {
+            if (values == null) return null;
+
+            byte[] buffer = new byte[values.Length * 8];
+            for (int i = 0; i < values.Length; i++)
+            {
+                ByteTransDataFormat8(BitConverter.GetBytes(values[i])).CopyTo(buffer, 8 * i);
+            }
+
+            return buffer;
+        }
+        /// <summary>
+        /// float数组变量转化缓存数据
+        /// </summary>
+        /// <param name="values">等待转化的数组</param>
+        /// <returns>buffer数据</returns>
+        private byte[] TransByte(float[] values)
+        {
+            if (values == null) return null;
+
+            byte[] buffer = new byte[values.Length * 4];
+            for (int i = 0; i < values.Length; i++)
+            {
+                ByteTransDataFormat4(BitConverter.GetBytes(values[i])).CopyTo(buffer, 4 * i);
+            }
+
+            return buffer;
+        }
+        /// <summary>
+        /// double数组变量转化缓存数据
+        /// </summary>
+        /// <param name="values">等待转化的数组</param>
+        /// <returns>buffer数据</returns>
+        private byte[] TransByte(double[] values)
+        {
+            if (values == null) return null;
+
+            byte[] buffer = new byte[values.Length * 8];
+            for (int i = 0; i < values.Length; i++)
+            {
+                ByteTransDataFormat8(BitConverter.GetBytes(values[i])).CopyTo(buffer, 8 * i);
+            }
+
+            return buffer;
+        }
+        /// <summary>
+        /// 使用指定的编码字符串转化缓存数据
+        /// </summary>
+        /// <param name="value">等待转化的数据</param>
+        /// <param name="encoding">字符串的编码方式</param>
+        /// <returns>buffer数据</returns>
+        private byte[] TransByte(string value, Encoding encoding)
+        {
+            if (value == null) return null;
+
+            return encoding.GetBytes(value);
+        }
+        #endregion Common method Helper
+
+
+        #region Write Bool
+        /// <summary>
+        /// 向PLC中位软元件写入bool数组,返回值说明,比如你写入M100,values[0]对应M100
+        /// </summary>
+        /// <param name="address">要写入的数据地址</param>
+        /// <param name="values">要写入的实际数据,可以指定任意的长度</param>
+        /// <returns>返回写入结果</returns>
+        public OperateResult Write(string address, bool[] values)
+        {
+            // 分析地址
+            OperateResult<McAddressData> addressResult = McAnalysisAddress(address, 0);
+            if (!addressResult.IsSuccess) return addressResult;
+
+            byte[] coreResult = MelsecHelper.BuildWriteBitCoreCommand(addressResult.Content, values);
+
+            // 核心交互
+            OperateResult<byte[]> read = ReadFromCoreServer(PackMcCommand(coreResult, NetworkNumber, NetworkStationNumber));
+            if (!read.IsSuccess) return read;
+
+            // 错误码校验
+            ushort ErrorCode = BitConverter.ToUInt16(read.Content, 9);
+            if (ErrorCode != 0) return new OperateResult<byte[]>(ErrorCode, StringResources.Language.MelsecPleaseReferToManulDocument);
+
+            // 成功
+            return OperateResult.CreateSuccessResult();
+        }
+        public OperateResult Write(string address, bool value)
+        {
+            return Write(address, new bool[1] { value });
+        }
+        #endregion Write Bool
+
+        #region Write short
+        /// <summary>
+        /// 向设备中写入short数组,返回是否写入成功
+        /// </summary>
+        /// <param name="address">数据地址</param>
+        /// <param name="values">实际数据</param>
+        /// <returns>是否写入成功的结果对象</returns>
+        public OperateResult Write(string address, short[] values)
+        {
+            return Write(address, TransByte(values));
+        }
+
+        /// <summary>
+        /// 向设备中写入short数据,返回是否写入成功
+        /// </summary>
+        /// <param name="address">数据地址</param>
+        /// <param name="value">实际数据</param>
+        /// <returns>是否写入成功的结果对象</returns>
+        public OperateResult Write(string address, short value)
+        {
+            return Write(address, new short[1] { value });
+        }
+        #endregion Write short
+
+        #region Write ushort
+        /// <summary>
+        /// 向设备中写入ushort数组,返回是否写入成功
+        /// </summary>
+        /// <param name="address">要写入的数据地址</param>
+        /// <param name="values">要写入的实际数据</param>
+        /// <returns>是否写入成功的结果对象</returns>
+        public OperateResult Write(string address, ushort[] values)
+        {
+            return Write(address, TransByte(values));
+        }
+
+
+        /// <summary>
+        /// 向设备中写入ushort数据,返回是否写入成功
+        /// </summary>
+        /// <param name="address">数据地址</param>
+        /// <param name="value">实际数据</param>
+        /// <returns>是否写入成功的结果对象</returns>
+        public OperateResult Write(string address, ushort value)
+        {
+            return Write(address, new ushort[] { value });
+        }
+        #endregion Write ushort
+
+        #region Write int
+        /// <summary>
+        /// 向设备中写入int数组,返回是否写入成功
+        /// </summary>
+        /// <param name="address">数据地址</param>
+        /// <param name="values">实际数据</param>
+        /// <returns>是否写入成功的结果对象</returns>
+        public OperateResult Write(string address, int[] values)
+        {
+            return Write(address, TransByte(values));
+        }
+
+        /// <summary>
+        /// 向设备中写入int数据,返回是否写入成功
+        /// </summary>
+        /// <param name="address">数据地址</param>
+        /// <param name="value">实际数据</param>
+        /// <returns>是否写入成功的结果对象</returns>
+        public OperateResult Write(string address, int value)
+        {
+            return Write(address, new int[] { value });
+        }
+        #endregion Write int
+
+        #region Write uint
+        /// <summary>
+        /// 向设备中写入uint数组,返回是否写入成功
+        /// </summary>
+        /// <param name="address">数据地址</param>
+        /// <param name="values">实际数据</param>
+        /// <returns>是否写入成功的结果对象</returns>
+        public OperateResult Write(string address, uint[] values)
+        {
+            return Write(address, TransByte(values));
+        }
+
+        /// <summary>
+        /// 向设备中写入uint数据,返回是否写入成功
+        /// </summary>
+        /// <param name="address">数据地址</param>
+        /// <param name="value">实际数据</param>
+        /// <returns>是否写入成功的结果对象</returns>
+        public OperateResult Write(string address, uint value)
+        {
+            return Write(address, new uint[] { value });
+        }
+        #endregion Write uint
+
+        #region Write long
+        /// <summary>
+        /// 向设备中写入long数组,返回是否写入成功
+        /// </summary>
+        /// <param name="address">数据地址</param>
+        /// <param name="values">实际数据</param>
+        /// <returns>是否写入成功的结果对象</returns>
+        public OperateResult Write(string address, long[] values)
+        {
+            return Write(address, TransByte(values));
+        }
+
+        /// <summary>
+        /// 向设备中写入long数据,返回是否写入成功
+        /// </summary>
+        /// <param name="address">数据地址</param>
+        /// <param name="value">实际数据</param>
+        /// <returns>是否写入成功的结果对象</returns>
+        public OperateResult Write(string address, long value)
+        {
+            return Write(address, new long[] { value });
+        }
+        #endregion Write long
+
+        #region Write ulong
+        /// <summary>
+        /// 向P设备中写入ulong数组,返回是否写入成功
+        /// </summary>
+        /// <param name="address">数据地址</param>
+        /// <param name="values">实际数据</param>
+        /// <returns>是否写入成功的结果对象</returns>
+        public OperateResult Write(string address, ulong[] values)
+        {
+            return Write(address, TransByte(values));
+        }
+
+        /// <summary>
+        /// 向设备中写入ulong数据,返回是否写入成功
+        /// </summary>
+        /// <param name="address">数据地址</param>
+        /// <param name="value">实际数据</param>
+        /// <returns>是否写入成功的结果对象</returns>
+        public OperateResult Write(string address, ulong value)
+        {
+            return Write(address, new ulong[] { value });
+        }
+        #endregion Write ulong
+
+        #region Write float
+        /// <summary>
+        /// 向设备中写入float数组,返回是否写入成功
+        /// </summary>
+        /// <param name="address">数据地址</param>
+        /// <param name="values">实际数据</param>
+        /// <returns>返回写入结果</returns>
+        public OperateResult Write(string address, float[] values)
+        {
+            return Write(address, TransByte(values));
+        }
+
+        /// <summary>
+        /// 向设备中写入float数据,返回是否写入成功
+        /// </summary>
+        /// <param name="address">数据地址</param>
+        /// <param name="value">实际数据</param>
+        /// <returns>返回写入结果</returns>
+        public OperateResult Write(string address, float value)
+        {
+            return Write(address, new float[] { value });
+        }
+        #endregion Write float
+
+        #region Write double
+        /// <summary>
+        /// 向设备中写入double数组,返回是否写入成功
+        /// </summary>
+        /// <param name="address">数据地址</param>
+        /// <param name="values">实际数据</param>
+        /// <returns>是否写入成功的结果对象</returns>
+        public OperateResult Write(string address, double[] values)
+        {
+            return Write(address, TransByte(values));
+        }
+
+        /// <summary>
+        /// 向设备中写入double数据,返回是否写入成功
+        /// </summary>
+        /// <param name="address">数据地址</param>
+        /// <param name="value">实际数据</param>
+        /// <returns>是否写入成功的结果对象</returns>
+        public OperateResult Write(string address, double value)
+        {
+            return Write(address, new double[] { value });
+        }
+        #endregion Write double
+
+        #region Write string
+        /// <summary>
+        /// 向设备中写入字符串,编码格式为ASCII
+        /// </summary>
+        /// <param name="address">数据地址</param>
+        /// <param name="value">字符串数据</param>
+        /// <returns>是否写入成功的结果对象</returns>
+        public OperateResult Write(string address, string value)
+        {
+            return Write(address, value, Encoding.ASCII);
+        }
+
+        /// <summary>
+        /// 向设备中写入指定编码的字符串
+        /// </summary>
+        /// <param name="address">数据地址</param>
+        /// <param name="value">字符串数据</param>
+        /// <param name="encoding">字节编码</param>
+        /// <returns>是否写入成功的结果对象</returns>
+        public OperateResult Write(string address, string value, Encoding encoding)
+        {
+            byte[] temp = TransByte(value, encoding);
+            if (WordLength == 1) temp = SoftBasic.ArrayExpandToLengthEven(temp);
+            return Write(address, temp);
+        }
+
+        /// <summary>
+        /// 向设备中写入指定长度的字符串,超出截断,不够补0,编码格式为ASCII
+        /// </summary>
+        /// <param name="address">数据地址</param>
+        /// <param name="value">字符串数据</param>
+        /// <param name="length">指定的字符串长度,必须大于0</param>
+        /// <returns>是否写入成功的结果对象 -> Whether to write a successful result object</returns>
+        public OperateResult Write(string address, string value, int length)
+        {
+            return Write(address, value, length, Encoding.ASCII);
+        }
+
+        /// <summary>
+        /// 向设备中写入指定长度并且指定编码的字符串,超出截断,不够补0
+        /// </summary>
+        /// <param name="address">数据地址</param>
+        /// <param name="value">字符串数据</param>
+        /// <param name="length">指定的长度,按照转换后的字节计算</param>
+        /// <param name="encoding">字符编码</param>
+        /// <returns>是否写入成功的结果对象 -> Whether to write a successful result object</returns>
+        public OperateResult Write(string address, string value, int length, Encoding encoding)
+        {
+            byte[] temp = TransByte(value, encoding);
+            if (WordLength == 1) temp = SoftBasic.ArrayExpandToLengthEven(temp);
+            temp = SoftBasic.ArrayExpandToLength(temp, length);
+            return Write(address, temp);
+        }
+
+        /// <summary>
+        /// 向设备中写入字符串,编码格式为Unicode
+        /// </summary>
+        /// <param name="address">数据地址</param>
+        /// <param name="value">字符串数据</param>
+        /// <returns>是否写入成功的结果对象</returns>
+        private OperateResult WriteUnicodeString(string address, string value)
+        {
+            byte[] temp = TransByte(value, Encoding.Unicode);
+            return Write(address, temp);
+        }
+
+        /// <summary>
+        /// 向设备中写入指定长度的字符串,超出截断,不够补0,编码格式为Unicode
+        /// </summary>
+        /// <param name="address">数据地址</param>
+        /// <param name="value">字符串数据</param>
+        /// <param name="length">指定的字符串长度,必须大于0</param>
+        /// <returns>是否写入成功的结果对象 -> Whether to write a successful result object</returns>
+        private OperateResult WriteUnicodeString(string address, string value, int length)
+        {
+            byte[] temp = TransByte(value, Encoding.Unicode);
+            temp = SoftBasic.ArrayExpandToLength(temp, length * 2);
+            return Write(address, temp);
+        }
+        #endregion Write string
+
+        #region Write byte array 向PLC写入数据 核心代码
+        /// <summary>
+        /// 向PLC写入数据,数据格式为原始的字节类型
+        /// </summary>
+        /// <param name="address">初始地址</param>
+        /// <param name="value">原始的字节数据</param>
+        /// <returns>结果</returns>
+        public OperateResult Write(string address, byte[] value)
+        {
+            // 分析地址
+            OperateResult<McAddressData> addressResult = McAnalysisAddress(address, 0);
+            if (!addressResult.IsSuccess) return OperateResult.CreateFailedResult<byte[]>(addressResult);
+
+            return WriteAddressData(addressResult.Content, value);
+        }
+        public OperateResult Write(string address, byte value)
+        {
+            return Write(address, new byte[] { value });
+        }
+
+        private OperateResult WriteAddressData(McAddressData addressData, byte[] value)
+        {
+            // 创建核心报文
+            byte[] coreResult = MelsecHelper.BuildWriteWordCoreCommand(addressData, value);
+
+            // 核心交互
+            OperateResult<byte[]> read = ReadFromCoreServer(PackMcCommand(coreResult, NetworkNumber, NetworkStationNumber));
+            if (!read.IsSuccess) return read;
+
+            // 错误码校验
+            ushort ErrorCode = BitConverter.ToUInt16(read.Content, 9);
+            if (ErrorCode != 0) return new OperateResult<byte[]>(ErrorCode, StringResources.Language.MelsecPleaseReferToManulDocument);
+
+            // 成功
+            return OperateResult.CreateSuccessResult();
+        }
+        #endregion Write byte array 向PLC写入数据 核心代码
+
+        #endregion Read Write Support
+    }
+
+    /// <summary>
+    /// 应用于多字节数据的解析或是生成格式
+    /// </summary>
+    public enum DataFormatEnum
+    {
+        /// <summary>
+        /// 按照顺序排序
+        /// </summary>
+        ABCD = 0,
+        /// <summary>
+        /// 按照单字反转
+        /// </summary>
+        BADC = 1,
+        /// <summary>
+        /// 按照双字反转
+        /// </summary>
+        CDAB = 2,
+        /// <summary>
+        /// 按照倒序排序
+        /// </summary>
+        DCBA = 3,
+    }
+}

+ 84 - 0
BlankApp1/TFT-MelsecMcNet/MelsecQnA3EBinaryMessage.cs

@@ -0,0 +1,84 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TFT_MelsecMcNet
+{
+    /// <summary>
+    /// 三菱的Qna兼容3E帧协议解析规则
+    /// </summary>
+    public class MelsecQnA3EBinaryMessage : INetMessage
+    {
+
+        /// <summary>
+        /// 消息头的指令长度
+        /// </summary>
+        public int ProtocolHeadBytesLength
+        {
+            get
+            {
+                return 9;
+            }
+        }
+
+
+        /// <summary>
+        /// 从当前的头子节文件中提取出接下来需要接收的数据长度
+        /// </summary>
+        /// <returns>返回接下来的数据内容长度</returns>
+        public int GetContentLengthByHeadBytes()
+        {
+            return BitConverter.ToUInt16(HeadBytes, 7);
+        }
+
+
+        /// <summary>
+        /// 检查头子节的合法性
+        /// </summary>
+        /// <param name="token">特殊的令牌,有些特殊消息的验证</param>
+        /// <returns>是否成功的结果</returns>
+        public bool CheckHeadBytesLegal(byte[] token)
+        {
+            if (HeadBytes == null) return false;
+
+            if (HeadBytes[0] == 0xD0 && HeadBytes[1] == 0x00)
+            {
+                return true;
+            }
+            else
+            {
+                return false;
+            }
+        }
+
+
+        /// <summary>
+        /// 获取头子节里的消息标识
+        /// </summary>
+        /// <returns>消息标识</returns>
+        public int GetHeadBytesIdentity()
+        {
+            return 0;
+        }
+
+
+        /// <summary>
+        /// 消息头字节
+        /// </summary>
+        public byte[] HeadBytes { get; set; }
+
+
+        /// <summary>
+        /// 消息内容字节
+        /// </summary>
+        public byte[] ContentBytes { get; set; }
+
+
+        /// <summary>
+        /// 发送的字节信息
+        /// </summary>
+        public byte[] SendBytes { get; set; }
+
+
+    }
+}

+ 1318 - 0
BlankApp1/TFT-MelsecMcNet/OperateResult.cs

@@ -0,0 +1,1318 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TFT_MelsecMcNet
+{
+    /// <summary>
+    /// 操作结果的类,只带有成功标志和错误信息 -> The class that operates the result, with only success flags and error messages
+    /// </summary>
+    /// <remarks>
+    /// 当 <see cref="IsSuccess"/> 为 True 时,忽略 <see cref="Message"/> 及 <see cref="ErrorCode"/> 的值
+    /// </remarks>
+    public class OperateResult
+    {
+        #region Constructor
+
+        /// <summary>
+        /// 实例化一个默认的结果对象
+        /// </summary>
+        public OperateResult()
+        {
+        }
+
+        /// <summary>
+        /// 使用指定的消息实例化一个默认的结果对象
+        /// </summary>
+        /// <param name="msg">错误消息</param>
+        public OperateResult(string msg)
+        {
+            this.Message = msg;
+        }
+
+        /// <summary>
+        /// 使用错误代码,消息文本来实例化对象
+        /// </summary>
+        /// <param name="err">错误代码</param>
+        /// <param name="msg">错误消息</param>
+        public OperateResult(int err, string msg)
+        {
+            this.ErrorCode = err;
+            this.Message = msg;
+        }
+
+        #endregion
+
+        /// <summary>
+        /// 指示本次访问是否成功
+        /// </summary>
+        public bool IsSuccess { get; set; }
+
+        /// <summary>
+        /// 具体的错误描述
+        /// </summary>
+        public string Message { get; set; } = StringResources.Language.UnknownError;
+
+        /// <summary>
+        /// 具体的错误代码
+        /// </summary>
+        public int ErrorCode { get; set; } = 10000;
+
+        /// <summary>
+        /// 获取错误代号及文本描述
+        /// </summary>
+        /// <returns>包含错误码及错误消息</returns>
+        public string ToMessageShowString()
+        {
+            return $"{StringResources.Language.ErrorCode}:{ErrorCode}{Environment.NewLine}{StringResources.Language.TextDescription}:{Message}";
+        }
+
+
+        /// <summary>
+        /// 从另一个结果类中拷贝错误信息
+        /// </summary>
+        /// <typeparam name="TResult">支持结果类及派生类</typeparam>
+        /// <param name="result">结果类及派生类的对象</param>
+        public void CopyErrorFromOther<TResult>(TResult result) where TResult : OperateResult
+        {
+            if (result != null)
+            {
+                ErrorCode = result.ErrorCode;
+                Message = result.Message;
+            }
+
+        }
+
+        #region Static Method
+
+        /*****************************************************************************************************
+         * 
+         *    主要是方便获取到一些特殊状态的结果对象
+         * 
+         ******************************************************************************************************/
+
+        /// <summary>
+        /// 创建并返回一个失败的结果对象,该对象复制另一个结果对象的错误信息
+        /// </summary>
+        /// <typeparam name="T">目标数据类型</typeparam>
+        /// <param name="result">之前的结果对象</param>
+        /// <returns>带默认泛型对象的失败结果类</returns>
+        public static OperateResult<T> CreateFailedResult<T>(OperateResult result)
+        {
+            return new OperateResult<T>()
+            {
+                ErrorCode = result.ErrorCode,
+                Message = result.Message,
+            };
+        }
+
+        /// <summary>
+        /// 创建并返回一个失败的结果对象,该对象复制另一个结果对象的错误信息
+        /// </summary>
+        /// <typeparam name="T1">目标数据类型一</typeparam>
+        /// <typeparam name="T2">目标数据类型二</typeparam>
+        /// <param name="result">之前的结果对象</param>
+        /// <returns>带默认泛型对象的失败结果类</returns>
+        public static OperateResult<T1, T2> CreateFailedResult<T1, T2>(OperateResult result)
+        {
+            return new OperateResult<T1, T2>()
+            {
+                ErrorCode = result.ErrorCode,
+                Message = result.Message,
+            };
+        }
+
+
+        /// <summary>
+        /// 创建并返回一个失败的结果对象,该对象复制另一个结果对象的错误信息
+        /// </summary>
+        /// <typeparam name="T1">目标数据类型一</typeparam>
+        /// <typeparam name="T2">目标数据类型二</typeparam>
+        /// <typeparam name="T3">目标数据类型三</typeparam>
+        /// <param name="result">之前的结果对象</param>
+        /// <returns>带默认泛型对象的失败结果类</returns>
+        public static OperateResult<T1, T2, T3> CreateFailedResult<T1, T2, T3>(OperateResult result)
+        {
+            return new OperateResult<T1, T2, T3>()
+            {
+                ErrorCode = result.ErrorCode,
+                Message = result.Message,
+            };
+        }
+
+
+        /// <summary>
+        /// 创建并返回一个失败的结果对象,该对象复制另一个结果对象的错误信息
+        /// </summary>
+        /// <typeparam name="T1">目标数据类型一</typeparam>
+        /// <typeparam name="T2">目标数据类型二</typeparam>
+        /// <typeparam name="T3">目标数据类型三</typeparam>
+        /// <typeparam name="T4">目标数据类型四</typeparam>
+        /// <param name="result">之前的结果对象</param>
+        /// <returns>带默认泛型对象的失败结果类</returns>
+        public static OperateResult<T1, T2, T3, T4> CreateFailedResult<T1, T2, T3, T4>(OperateResult result)
+        {
+            return new OperateResult<T1, T2, T3, T4>()
+            {
+                ErrorCode = result.ErrorCode,
+                Message = result.Message,
+            };
+        }
+
+
+        /// <summary>
+        /// 创建并返回一个失败的结果对象,该对象复制另一个结果对象的错误信息
+        /// </summary>
+        /// <typeparam name="T1">目标数据类型一</typeparam>
+        /// <typeparam name="T2">目标数据类型二</typeparam>
+        /// <typeparam name="T3">目标数据类型三</typeparam>
+        /// <typeparam name="T4">目标数据类型四</typeparam>
+        /// <typeparam name="T5">目标数据类型五</typeparam>
+        /// <param name="result">之前的结果对象</param>
+        /// <returns>带默认泛型对象的失败结果类</returns>
+        public static OperateResult<T1, T2, T3, T4, T5> CreateFailedResult<T1, T2, T3, T4, T5>(OperateResult result)
+        {
+            return new OperateResult<T1, T2, T3, T4, T5>()
+            {
+                ErrorCode = result.ErrorCode,
+                Message = result.Message,
+            };
+        }
+
+
+        /// <summary>
+        /// 创建并返回一个失败的结果对象,该对象复制另一个结果对象的错误信息
+        /// </summary>
+        /// <typeparam name="T1">目标数据类型一</typeparam>
+        /// <typeparam name="T2">目标数据类型二</typeparam>
+        /// <typeparam name="T3">目标数据类型三</typeparam>
+        /// <typeparam name="T4">目标数据类型四</typeparam>
+        /// <typeparam name="T5">目标数据类型五</typeparam>
+        /// <typeparam name="T6">目标数据类型六</typeparam>
+        /// <param name="result">之前的结果对象</param>
+        /// <returns>带默认泛型对象的失败结果类</returns>
+        public static OperateResult<T1, T2, T3, T4, T5, T6> CreateFailedResult<T1, T2, T3, T4, T5, T6>(OperateResult result)
+        {
+            return new OperateResult<T1, T2, T3, T4, T5, T6>()
+            {
+                ErrorCode = result.ErrorCode,
+                Message = result.Message,
+            };
+        }
+
+        /// <summary>
+        /// 创建并返回一个失败的结果对象,该对象复制另一个结果对象的错误信息
+        /// </summary>
+        /// <typeparam name="T1">目标数据类型一</typeparam>
+        /// <typeparam name="T2">目标数据类型二</typeparam>
+        /// <typeparam name="T3">目标数据类型三</typeparam>
+        /// <typeparam name="T4">目标数据类型四</typeparam>
+        /// <typeparam name="T5">目标数据类型五</typeparam>
+        /// <typeparam name="T6">目标数据类型六</typeparam>
+        /// <typeparam name="T7">目标数据类型七</typeparam>
+        /// <param name="result">之前的结果对象</param>
+        /// <returns>带默认泛型对象的失败结果类</returns>
+        public static OperateResult<T1, T2, T3, T4, T5, T6, T7> CreateFailedResult<T1, T2, T3, T4, T5, T6, T7>(OperateResult result)
+        {
+            return new OperateResult<T1, T2, T3, T4, T5, T6, T7>()
+            {
+                ErrorCode = result.ErrorCode,
+                Message = result.Message,
+            };
+        }
+
+        /// <summary>
+        /// 创建并返回一个失败的结果对象,该对象复制另一个结果对象的错误信息
+        /// </summary>
+        /// <typeparam name="T1">目标数据类型一</typeparam>
+        /// <typeparam name="T2">目标数据类型二</typeparam>
+        /// <typeparam name="T3">目标数据类型三</typeparam>
+        /// <typeparam name="T4">目标数据类型四</typeparam>
+        /// <typeparam name="T5">目标数据类型五</typeparam>
+        /// <typeparam name="T6">目标数据类型六</typeparam>
+        /// <typeparam name="T7">目标数据类型七</typeparam>
+        /// <typeparam name="T8">目标数据类型八</typeparam>
+        /// <param name="result">之前的结果对象</param>
+        /// <returns>带默认泛型对象的失败结果类</returns>
+        public static OperateResult<T1, T2, T3, T4, T5, T6, T7, T8> CreateFailedResult<T1, T2, T3, T4, T5, T6, T7, T8>(OperateResult result)
+        {
+            return new OperateResult<T1, T2, T3, T4, T5, T6, T7, T8>()
+            {
+                ErrorCode = result.ErrorCode,
+                Message = result.Message,
+            };
+        }
+
+
+        /// <summary>
+        /// 创建并返回一个失败的结果对象,该对象复制另一个结果对象的错误信息
+        /// </summary>
+        /// <typeparam name="T1">目标数据类型一</typeparam>
+        /// <typeparam name="T2">目标数据类型二</typeparam>
+        /// <typeparam name="T3">目标数据类型三</typeparam>
+        /// <typeparam name="T4">目标数据类型四</typeparam>
+        /// <typeparam name="T5">目标数据类型五</typeparam>
+        /// <typeparam name="T6">目标数据类型六</typeparam>
+        /// <typeparam name="T7">目标数据类型七</typeparam>
+        /// <typeparam name="T8">目标数据类型八</typeparam>
+        /// <typeparam name="T9">目标数据类型九</typeparam>
+        /// <param name="result">之前的结果对象</param>
+        /// <returns>带默认泛型对象的失败结果类</returns>
+        public static OperateResult<T1, T2, T3, T4, T5, T6, T7, T8, T9> CreateFailedResult<T1, T2, T3, T4, T5, T6, T7, T8, T9>(OperateResult result)
+        {
+            return new OperateResult<T1, T2, T3, T4, T5, T6, T7, T8, T9>()
+            {
+                ErrorCode = result.ErrorCode,
+                Message = result.Message,
+            };
+        }
+
+
+        /// <summary>
+        /// 创建并返回一个失败的结果对象,该对象复制另一个结果对象的错误信息
+        /// </summary>
+        /// <typeparam name="T1">目标数据类型一</typeparam>
+        /// <typeparam name="T2">目标数据类型二</typeparam>
+        /// <typeparam name="T3">目标数据类型三</typeparam>
+        /// <typeparam name="T4">目标数据类型四</typeparam>
+        /// <typeparam name="T5">目标数据类型五</typeparam>
+        /// <typeparam name="T6">目标数据类型六</typeparam>
+        /// <typeparam name="T7">目标数据类型七</typeparam>
+        /// <typeparam name="T8">目标数据类型八</typeparam>
+        /// <typeparam name="T9">目标数据类型九</typeparam>
+        /// <typeparam name="T10">目标数据类型十</typeparam>
+        /// <param name="result">之前的结果对象</param>
+        /// <returns>带默认泛型对象的失败结果类</returns>
+        public static OperateResult<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> CreateFailedResult<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(OperateResult result)
+        {
+            return new OperateResult<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>()
+            {
+                ErrorCode = result.ErrorCode,
+                Message = result.Message,
+            };
+        }
+
+
+
+        /// <summary>
+        /// 创建并返回一个成功的结果对象
+        /// </summary>
+        /// <returns>成功的结果对象</returns>
+        public static OperateResult CreateSuccessResult()
+        {
+            return new OperateResult()
+            {
+                IsSuccess = true,
+                ErrorCode = 0,
+                Message = StringResources.Language.SuccessText,
+            };
+        }
+
+        /// <summary>
+        /// 创建并返回一个成功的结果对象,并带有一个参数对象
+        /// </summary>
+        /// <typeparam name="T">参数类型</typeparam>
+        /// <param name="value">类型的值对象</param>
+        /// <returns>成功的结果对象</returns>
+        public static OperateResult<T> CreateSuccessResult<T>(T value)
+        {
+            return new OperateResult<T>()
+            {
+                IsSuccess = true,
+                ErrorCode = 0,
+                Message = StringResources.Language.SuccessText,
+                Content = value
+            };
+        }
+
+
+        /// <summary>
+        /// 创建并返回一个成功的结果对象,并带有两个参数对象
+        /// </summary>
+        /// <typeparam name="T1">第一个参数类型</typeparam>
+        /// <typeparam name="T2">第二个参数类型</typeparam>
+        /// <param name="value1">类型一对象</param>
+        /// <param name="value2">类型二对象</param>
+        /// <returns>成的结果对象</returns>
+        public static OperateResult<T1, T2> CreateSuccessResult<T1, T2>(T1 value1, T2 value2)
+        {
+            return new OperateResult<T1, T2>()
+            {
+                IsSuccess = true,
+                ErrorCode = 0,
+                Message = StringResources.Language.SuccessText,
+                Content1 = value1,
+                Content2 = value2,
+            };
+        }
+
+
+        /// <summary>
+        /// 创建并返回一个成功的结果对象,并带有三个参数对象
+        /// </summary>
+        /// <typeparam name="T1">第一个参数类型</typeparam>
+        /// <typeparam name="T2">第二个参数类型</typeparam>
+        /// <typeparam name="T3">第三个参数类型</typeparam>
+        /// <param name="value1">类型一对象</param>
+        /// <param name="value2">类型二对象</param>
+        /// <param name="value3">类型三对象</param>
+        /// <returns>成的结果对象</returns>
+        public static OperateResult<T1, T2, T3> CreateSuccessResult<T1, T2, T3>(T1 value1, T2 value2, T3 value3)
+        {
+            return new OperateResult<T1, T2, T3>()
+            {
+                IsSuccess = true,
+                ErrorCode = 0,
+                Message = StringResources.Language.SuccessText,
+                Content1 = value1,
+                Content2 = value2,
+                Content3 = value3,
+            };
+        }
+
+        /// <summary>
+        /// 创建并返回一个成功的结果对象,并带有四个参数对象
+        /// </summary>
+        /// <typeparam name="T1">第一个参数类型</typeparam>
+        /// <typeparam name="T2">第二个参数类型</typeparam>
+        /// <typeparam name="T3">第三个参数类型</typeparam>
+        /// <typeparam name="T4">第四个参数类型</typeparam>
+        /// <param name="value1">类型一对象</param>
+        /// <param name="value2">类型二对象</param>
+        /// <param name="value3">类型三对象</param>
+        /// <param name="value4">类型四对象</param>
+        /// <returns>成的结果对象</returns>
+        public static OperateResult<T1, T2, T3, T4> CreateSuccessResult<T1, T2, T3, T4>(T1 value1, T2 value2, T3 value3, T4 value4)
+        {
+            return new OperateResult<T1, T2, T3, T4>()
+            {
+                IsSuccess = true,
+                ErrorCode = 0,
+                Message = StringResources.Language.SuccessText,
+                Content1 = value1,
+                Content2 = value2,
+                Content3 = value3,
+                Content4 = value4,
+            };
+        }
+
+
+        /// <summary>
+        /// 创建并返回一个成功的结果对象,并带有五个参数对象
+        /// </summary>
+        /// <typeparam name="T1">第一个参数类型</typeparam>
+        /// <typeparam name="T2">第二个参数类型</typeparam>
+        /// <typeparam name="T3">第三个参数类型</typeparam>
+        /// <typeparam name="T4">第四个参数类型</typeparam>
+        /// <typeparam name="T5">第五个参数类型</typeparam>
+        /// <param name="value1">类型一对象</param>
+        /// <param name="value2">类型二对象</param>
+        /// <param name="value3">类型三对象</param>
+        /// <param name="value4">类型四对象</param>
+        /// <param name="value5">类型五对象</param>
+        /// <returns>成的结果对象</returns>
+        public static OperateResult<T1, T2, T3, T4, T5> CreateSuccessResult<T1, T2, T3, T4, T5>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5)
+        {
+            return new OperateResult<T1, T2, T3, T4, T5>()
+            {
+                IsSuccess = true,
+                ErrorCode = 0,
+                Message = StringResources.Language.SuccessText,
+                Content1 = value1,
+                Content2 = value2,
+                Content3 = value3,
+                Content4 = value4,
+                Content5 = value5,
+            };
+        }
+
+        /// <summary>
+        /// 创建并返回一个成功的结果对象,并带有六个参数对象
+        /// </summary>
+        /// <typeparam name="T1">第一个参数类型</typeparam>
+        /// <typeparam name="T2">第二个参数类型</typeparam>
+        /// <typeparam name="T3">第三个参数类型</typeparam>
+        /// <typeparam name="T4">第四个参数类型</typeparam>
+        /// <typeparam name="T5">第五个参数类型</typeparam>
+        /// <typeparam name="T6">第六个参数类型</typeparam>
+        /// <param name="value1">类型一对象</param>
+        /// <param name="value2">类型二对象</param>
+        /// <param name="value3">类型三对象</param>
+        /// <param name="value4">类型四对象</param>
+        /// <param name="value5">类型五对象</param>
+        /// <param name="value6">类型六对象</param>
+        /// <returns>成的结果对象</returns>
+        public static OperateResult<T1, T2, T3, T4, T5, T6> CreateSuccessResult<T1, T2, T3, T4, T5, T6>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6)
+        {
+            return new OperateResult<T1, T2, T3, T4, T5, T6>()
+            {
+                IsSuccess = true,
+                ErrorCode = 0,
+                Message = StringResources.Language.SuccessText,
+                Content1 = value1,
+                Content2 = value2,
+                Content3 = value3,
+                Content4 = value4,
+                Content5 = value5,
+                Content6 = value6,
+            };
+        }
+
+        /// <summary>
+        /// 创建并返回一个成功的结果对象,并带有七个参数对象
+        /// </summary>
+        /// <typeparam name="T1">第一个参数类型</typeparam>
+        /// <typeparam name="T2">第二个参数类型</typeparam>
+        /// <typeparam name="T3">第三个参数类型</typeparam>
+        /// <typeparam name="T4">第四个参数类型</typeparam>
+        /// <typeparam name="T5">第五个参数类型</typeparam>
+        /// <typeparam name="T6">第六个参数类型</typeparam>
+        /// <typeparam name="T7">第七个参数类型</typeparam>
+        /// <param name="value1">类型一对象</param>
+        /// <param name="value2">类型二对象</param>
+        /// <param name="value3">类型三对象</param>
+        /// <param name="value4">类型四对象</param>
+        /// <param name="value5">类型五对象</param>
+        /// <param name="value6">类型六对象</param>
+        /// <param name="value7">类型七对象</param>
+        /// <returns>成的结果对象</returns>
+        public static OperateResult<T1, T2, T3, T4, T5, T6, T7> CreateSuccessResult<T1, T2, T3, T4, T5, T6, T7>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7)
+        {
+            return new OperateResult<T1, T2, T3, T4, T5, T6, T7>()
+            {
+                IsSuccess = true,
+                ErrorCode = 0,
+                Message = StringResources.Language.SuccessText,
+                Content1 = value1,
+                Content2 = value2,
+                Content3 = value3,
+                Content4 = value4,
+                Content5 = value5,
+                Content6 = value6,
+                Content7 = value7,
+            };
+        }
+
+
+        /// <summary>
+        /// 创建并返回一个成功的结果对象,并带有八个参数对象
+        /// </summary>
+        /// <typeparam name="T1">第一个参数类型</typeparam>
+        /// <typeparam name="T2">第二个参数类型</typeparam>
+        /// <typeparam name="T3">第三个参数类型</typeparam>
+        /// <typeparam name="T4">第四个参数类型</typeparam>
+        /// <typeparam name="T5">第五个参数类型</typeparam>
+        /// <typeparam name="T6">第六个参数类型</typeparam>
+        /// <typeparam name="T7">第七个参数类型</typeparam>
+        /// <typeparam name="T8">第八个参数类型</typeparam>
+        /// <param name="value1">类型一对象</param>
+        /// <param name="value2">类型二对象</param>
+        /// <param name="value3">类型三对象</param>
+        /// <param name="value4">类型四对象</param>
+        /// <param name="value5">类型五对象</param>
+        /// <param name="value6">类型六对象</param>
+        /// <param name="value7">类型七对象</param>
+        /// <param name="value8">类型八对象</param>
+        /// <returns>成的结果对象</returns>
+        public static OperateResult<T1, T2, T3, T4, T5, T6, T7, T8> CreateSuccessResult<T1, T2, T3, T4, T5, T6, T7, T8>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7, T8 value8)
+        {
+            return new OperateResult<T1, T2, T3, T4, T5, T6, T7, T8>()
+            {
+                IsSuccess = true,
+                ErrorCode = 0,
+                Message = StringResources.Language.SuccessText,
+                Content1 = value1,
+                Content2 = value2,
+                Content3 = value3,
+                Content4 = value4,
+                Content5 = value5,
+                Content6 = value6,
+                Content7 = value7,
+                Content8 = value8,
+            };
+        }
+
+
+        /// <summary>
+        /// 创建并返回一个成功的结果对象,并带有九个参数对象
+        /// </summary>
+        /// <typeparam name="T1">第一个参数类型</typeparam>
+        /// <typeparam name="T2">第二个参数类型</typeparam>
+        /// <typeparam name="T3">第三个参数类型</typeparam>
+        /// <typeparam name="T4">第四个参数类型</typeparam>
+        /// <typeparam name="T5">第五个参数类型</typeparam>
+        /// <typeparam name="T6">第六个参数类型</typeparam>
+        /// <typeparam name="T7">第七个参数类型</typeparam>
+        /// <typeparam name="T8">第八个参数类型</typeparam>
+        /// <typeparam name="T9">第九个参数类型</typeparam>
+        /// <param name="value1">类型一对象</param>
+        /// <param name="value2">类型二对象</param>
+        /// <param name="value3">类型三对象</param>
+        /// <param name="value4">类型四对象</param>
+        /// <param name="value5">类型五对象</param>
+        /// <param name="value6">类型六对象</param>
+        /// <param name="value7">类型七对象</param>
+        /// <param name="value8">类型八对象</param>
+        /// <param name="value9">类型九对象</param>
+        /// <returns>成的结果对象</returns>
+        public static OperateResult<T1, T2, T3, T4, T5, T6, T7, T8, T9> CreateSuccessResult<T1, T2, T3, T4, T5, T6, T7, T8, T9>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7, T8 value8, T9 value9)
+        {
+            return new OperateResult<T1, T2, T3, T4, T5, T6, T7, T8, T9>()
+            {
+                IsSuccess = true,
+                ErrorCode = 0,
+                Message = StringResources.Language.SuccessText,
+                Content1 = value1,
+                Content2 = value2,
+                Content3 = value3,
+                Content4 = value4,
+                Content5 = value5,
+                Content6 = value6,
+                Content7 = value7,
+                Content8 = value8,
+                Content9 = value9,
+            };
+        }
+
+        /// <summary>
+        /// 创建并返回一个成功的结果对象,并带有十个参数对象
+        /// </summary>
+        /// <typeparam name="T1">第一个参数类型</typeparam>
+        /// <typeparam name="T2">第二个参数类型</typeparam>
+        /// <typeparam name="T3">第三个参数类型</typeparam>
+        /// <typeparam name="T4">第四个参数类型</typeparam>
+        /// <typeparam name="T5">第五个参数类型</typeparam>
+        /// <typeparam name="T6">第六个参数类型</typeparam>
+        /// <typeparam name="T7">第七个参数类型</typeparam>
+        /// <typeparam name="T8">第八个参数类型</typeparam>
+        /// <typeparam name="T9">第九个参数类型</typeparam>
+        /// <typeparam name="T10">第十个参数类型</typeparam>
+        /// <param name="value1">类型一对象</param>
+        /// <param name="value2">类型二对象</param>
+        /// <param name="value3">类型三对象</param>
+        /// <param name="value4">类型四对象</param>
+        /// <param name="value5">类型五对象</param>
+        /// <param name="value6">类型六对象</param>
+        /// <param name="value7">类型七对象</param>
+        /// <param name="value8">类型八对象</param>
+        /// <param name="value9">类型九对象</param>
+        /// <param name="value10">类型十对象</param>
+        /// <returns>成的结果对象</returns>
+        public static OperateResult<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> CreateSuccessResult<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7, T8 value8, T9 value9, T10 value10)
+        {
+            return new OperateResult<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>()
+            {
+                IsSuccess = true,
+                ErrorCode = 0,
+                Message = StringResources.Language.SuccessText,
+                Content1 = value1,
+                Content2 = value2,
+                Content3 = value3,
+                Content4 = value4,
+                Content5 = value5,
+                Content6 = value6,
+                Content7 = value7,
+                Content8 = value8,
+                Content9 = value9,
+                Content10 = value10,
+            };
+        }
+
+        #endregion
+
+    }
+
+    /// <summary>
+    /// 操作结果的泛型类,允许带一个用户自定义的泛型对象,推荐使用这个类
+    /// </summary>
+    /// <typeparam name="T">泛型类</typeparam>
+    public class OperateResult<T> : OperateResult
+    {
+        #region Constructor
+
+        /// <summary>
+        /// 实例化一个默认的结果对象
+        /// </summary>
+        public OperateResult() : base()
+        {
+        }
+
+        /// <summary>
+        /// 使用指定的消息实例化一个默认的结果对象
+        /// </summary>
+        /// <param name="msg">错误消息</param>
+        public OperateResult(string msg) : base(msg)
+        {
+
+        }
+
+        /// <summary>
+        /// 使用错误代码,消息文本来实例化对象
+        /// </summary>
+        /// <param name="err">错误代码</param>
+        /// <param name="msg">错误消息</param>
+        public OperateResult(int err, string msg) : base(err, msg)
+        {
+
+        }
+
+        #endregion
+
+        /// <summary>
+        /// 用户自定义的泛型数据
+        /// </summary>
+        public T Content { get; set; }
+    }
+
+    /// <summary>
+    /// 操作结果的泛型类,允许带两个用户自定义的泛型对象,推荐使用这个类
+    /// </summary>
+    /// <typeparam name="T1">泛型类</typeparam>
+    /// <typeparam name="T2">泛型类</typeparam>
+    public class OperateResult<T1, T2> : OperateResult
+    {
+        #region Constructor
+
+        /// <summary>
+        /// 实例化一个默认的结果对象
+        /// </summary>
+        public OperateResult() : base()
+        {
+        }
+
+        /// <summary>
+        /// 使用指定的消息实例化一个默认的结果对象
+        /// </summary>
+        /// <param name="msg">错误消息</param>
+        public OperateResult(string msg) : base(msg)
+        {
+
+        }
+
+        /// <summary>
+        /// 使用错误代码,消息文本来实例化对象
+        /// </summary>
+        /// <param name="err">错误代码</param>
+        /// <param name="msg">错误消息</param>
+        public OperateResult(int err, string msg) : base(err, msg)
+        {
+
+        }
+
+        #endregion
+
+        /// <summary>
+        /// 用户自定义的泛型数据1
+        /// </summary>
+        public T1 Content1 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据2
+        /// </summary>
+        public T2 Content2 { get; set; }
+    }
+
+    /// <summary>
+    /// 操作结果的泛型类,允许带三个用户自定义的泛型对象,推荐使用这个类
+    /// </summary>
+    /// <typeparam name="T1">泛型类</typeparam>
+    /// <typeparam name="T2">泛型类</typeparam>
+    /// <typeparam name="T3">泛型类</typeparam>
+    public class OperateResult<T1, T2, T3> : OperateResult
+    {
+        #region Constructor
+
+        /// <summary>
+        /// 实例化一个默认的结果对象
+        /// </summary>
+        public OperateResult() : base()
+        {
+        }
+
+        /// <summary>
+        /// 使用指定的消息实例化一个默认的结果对象
+        /// </summary>
+        /// <param name="msg">错误消息</param>
+        public OperateResult(string msg) : base(msg)
+        {
+
+        }
+
+        /// <summary>
+        /// 使用错误代码,消息文本来实例化对象
+        /// </summary>
+        /// <param name="err">错误代码</param>
+        /// <param name="msg">错误消息</param>
+        public OperateResult(int err, string msg) : base(err, msg)
+        {
+
+        }
+
+        #endregion
+
+        /// <summary>
+        /// 用户自定义的泛型数据1
+        /// </summary>
+        public T1 Content1 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据2
+        /// </summary>
+        public T2 Content2 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据3
+        /// </summary>
+        public T3 Content3 { get; set; }
+    }
+
+    /// <summary>
+    /// 操作结果的泛型类,允许带四个用户自定义的泛型对象,推荐使用这个类
+    /// </summary>
+    /// <typeparam name="T1">泛型类</typeparam>
+    /// <typeparam name="T2">泛型类</typeparam>
+    /// <typeparam name="T3">泛型类</typeparam>
+    /// <typeparam name="T4">泛型类</typeparam>
+    public class OperateResult<T1, T2, T3, T4> : OperateResult
+    {
+        #region Constructor
+
+        /// <summary>
+        /// 实例化一个默认的结果对象
+        /// </summary>
+        public OperateResult() : base()
+        {
+        }
+
+        /// <summary>
+        /// 使用指定的消息实例化一个默认的结果对象
+        /// </summary>
+        /// <param name="msg">错误消息</param>
+        public OperateResult(string msg) : base(msg)
+        {
+
+        }
+
+        /// <summary>
+        /// 使用错误代码,消息文本来实例化对象
+        /// </summary>
+        /// <param name="err">错误代码</param>
+        /// <param name="msg">错误消息</param>
+        public OperateResult(int err, string msg) : base(err, msg)
+        {
+
+        }
+
+        #endregion
+
+        /// <summary>
+        /// 用户自定义的泛型数据1
+        /// </summary>
+        public T1 Content1 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据2
+        /// </summary>
+        public T2 Content2 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据3
+        /// </summary>
+        public T3 Content3 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据4
+        /// </summary>
+        public T4 Content4 { get; set; }
+    }
+
+    /// <summary>
+    /// 操作结果的泛型类,允许带五个用户自定义的泛型对象,推荐使用这个类
+    /// </summary>
+    /// <typeparam name="T1">泛型类</typeparam>
+    /// <typeparam name="T2">泛型类</typeparam>
+    /// <typeparam name="T3">泛型类</typeparam>
+    /// <typeparam name="T4">泛型类</typeparam>
+    /// <typeparam name="T5">泛型类</typeparam>
+    public class OperateResult<T1, T2, T3, T4, T5> : OperateResult
+    {
+        #region Constructor
+
+        /// <summary>
+        /// 实例化一个默认的结果对象
+        /// </summary>
+        public OperateResult() : base()
+        {
+        }
+
+        /// <summary>
+        /// 使用指定的消息实例化一个默认的结果对象
+        /// </summary>
+        /// <param name="msg">错误消息</param>
+        public OperateResult(string msg) : base(msg)
+        {
+
+        }
+
+        /// <summary>
+        /// 使用错误代码,消息文本来实例化对象
+        /// </summary>
+        /// <param name="err">错误代码</param>
+        /// <param name="msg">错误消息</param>
+        public OperateResult(int err, string msg) : base(err, msg)
+        {
+
+        }
+
+        #endregion
+
+        /// <summary>
+        /// 用户自定义的泛型数据1
+        /// </summary>
+        public T1 Content1 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据2
+        /// </summary>
+        public T2 Content2 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据3
+        /// </summary>
+        public T3 Content3 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据4
+        /// </summary>
+        public T4 Content4 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据5
+        /// </summary>
+        public T5 Content5 { get; set; }
+
+    }
+
+    /// <summary>
+    /// 操作结果的泛型类,允许带六个用户自定义的泛型对象,推荐使用这个类
+    /// </summary>
+    /// <typeparam name="T1">泛型类</typeparam>
+    /// <typeparam name="T2">泛型类</typeparam>
+    /// <typeparam name="T3">泛型类</typeparam>
+    /// <typeparam name="T4">泛型类</typeparam>
+    /// <typeparam name="T5">泛型类</typeparam>
+    /// <typeparam name="T6">泛型类</typeparam>
+    public class OperateResult<T1, T2, T3, T4, T5, T6> : OperateResult
+    {
+        #region Constructor
+
+        /// <summary>
+        /// 实例化一个默认的结果对象
+        /// </summary>
+        public OperateResult() : base()
+        {
+        }
+
+        /// <summary>
+        /// 使用指定的消息实例化一个默认的结果对象
+        /// </summary>
+        /// <param name="msg">错误消息</param>
+        public OperateResult(string msg) : base(msg)
+        {
+
+        }
+
+        /// <summary>
+        /// 使用错误代码,消息文本来实例化对象
+        /// </summary>
+        /// <param name="err">错误代码</param>
+        /// <param name="msg">错误消息</param>
+        public OperateResult(int err, string msg) : base(err, msg)
+        {
+
+        }
+
+        #endregion
+
+        /// <summary>
+        /// 用户自定义的泛型数据1
+        /// </summary>
+        public T1 Content1 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据2
+        /// </summary>
+        public T2 Content2 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据3
+        /// </summary>
+        public T3 Content3 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据4
+        /// </summary>
+        public T4 Content4 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据5
+        /// </summary>
+        public T5 Content5 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据5
+        /// </summary>
+        public T6 Content6 { get; set; }
+
+    }
+
+    /// <summary>
+    /// 操作结果的泛型类,允许带七个用户自定义的泛型对象,推荐使用这个类
+    /// </summary>
+    /// <typeparam name="T1">泛型类</typeparam>
+    /// <typeparam name="T2">泛型类</typeparam>
+    /// <typeparam name="T3">泛型类</typeparam>
+    /// <typeparam name="T4">泛型类</typeparam>
+    /// <typeparam name="T5">泛型类</typeparam>
+    /// <typeparam name="T6">泛型类</typeparam>
+    /// <typeparam name="T7">泛型类</typeparam>
+    public class OperateResult<T1, T2, T3, T4, T5, T6, T7> : OperateResult
+    {
+        #region Constructor
+
+        /// <summary>
+        /// 实例化一个默认的结果对象
+        /// </summary>
+        public OperateResult() : base()
+        {
+        }
+
+        /// <summary>
+        /// 使用指定的消息实例化一个默认的结果对象
+        /// </summary>
+        /// <param name="msg">错误消息</param>
+        public OperateResult(string msg) : base(msg)
+        {
+
+        }
+
+        /// <summary>
+        /// 使用错误代码,消息文本来实例化对象
+        /// </summary>
+        /// <param name="err">错误代码</param>
+        /// <param name="msg">错误消息</param>
+        public OperateResult(int err, string msg) : base(err, msg)
+        {
+
+        }
+
+        #endregion
+
+        /// <summary>
+        /// 用户自定义的泛型数据1
+        /// </summary>
+        public T1 Content1 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据2
+        /// </summary>
+        public T2 Content2 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据3
+        /// </summary>
+        public T3 Content3 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据4
+        /// </summary>
+        public T4 Content4 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据5
+        /// </summary>
+        public T5 Content5 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据6
+        /// </summary>
+        public T6 Content6 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据7
+        /// </summary>
+        public T7 Content7 { get; set; }
+
+
+    }
+
+    /// <summary>
+    /// 操作结果的泛型类,允许带八个用户自定义的泛型对象,推荐使用这个类
+    /// </summary>
+    /// <typeparam name="T1">泛型类</typeparam>
+    /// <typeparam name="T2">泛型类</typeparam>
+    /// <typeparam name="T3">泛型类</typeparam>
+    /// <typeparam name="T4">泛型类</typeparam>
+    /// <typeparam name="T5">泛型类</typeparam>
+    /// <typeparam name="T6">泛型类</typeparam>
+    /// <typeparam name="T7">泛型类</typeparam>
+    /// <typeparam name="T8">泛型类</typeparam>
+    public class OperateResult<T1, T2, T3, T4, T5, T6, T7, T8> : OperateResult
+    {
+        #region Constructor
+
+        /// <summary>
+        /// 实例化一个默认的结果对象
+        /// </summary>
+        public OperateResult() : base()
+        {
+        }
+
+        /// <summary>
+        /// 使用指定的消息实例化一个默认的结果对象
+        /// </summary>
+        /// <param name="msg">错误消息</param>
+        public OperateResult(string msg) : base(msg)
+        {
+
+        }
+
+        /// <summary>
+        /// 使用错误代码,消息文本来实例化对象
+        /// </summary>
+        /// <param name="err">错误代码</param>
+        /// <param name="msg">错误消息</param>
+        public OperateResult(int err, string msg) : base(err, msg)
+        {
+
+        }
+
+        #endregion
+
+        /// <summary>
+        /// 用户自定义的泛型数据1
+        /// </summary>
+        public T1 Content1 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据2
+        /// </summary>
+        public T2 Content2 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据3
+        /// </summary>
+        public T3 Content3 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据4
+        /// </summary>
+        public T4 Content4 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据5
+        /// </summary>
+        public T5 Content5 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据6
+        /// </summary>
+        public T6 Content6 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据7
+        /// </summary>
+        public T7 Content7 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据8
+        /// </summary>
+        public T8 Content8 { get; set; }
+    }
+
+    /// <summary>
+    /// 操作结果的泛型类,允许带九个用户自定义的泛型对象,推荐使用这个类
+    /// </summary>
+    /// <typeparam name="T1">泛型类</typeparam>
+    /// <typeparam name="T2">泛型类</typeparam>
+    /// <typeparam name="T3">泛型类</typeparam>
+    /// <typeparam name="T4">泛型类</typeparam>
+    /// <typeparam name="T5">泛型类</typeparam>
+    /// <typeparam name="T6">泛型类</typeparam>
+    /// <typeparam name="T7">泛型类</typeparam>
+    /// <typeparam name="T8">泛型类</typeparam>
+    /// <typeparam name="T9">泛型类</typeparam>
+    public class OperateResult<T1, T2, T3, T4, T5, T6, T7, T8, T9> : OperateResult
+    {
+        #region Constructor
+
+        /// <summary>
+        /// 实例化一个默认的结果对象
+        /// </summary>
+        public OperateResult() : base()
+        {
+        }
+
+        /// <summary>
+        /// 使用指定的消息实例化一个默认的结果对象
+        /// </summary>
+        /// <param name="msg">错误消息</param>
+        public OperateResult(string msg) : base(msg)
+        {
+
+        }
+
+        /// <summary>
+        /// 使用错误代码,消息文本来实例化对象
+        /// </summary>
+        /// <param name="err">错误代码</param>
+        /// <param name="msg">错误消息</param>
+        public OperateResult(int err, string msg) : base(err, msg)
+        {
+
+        }
+
+        #endregion
+
+        /// <summary>
+        /// 用户自定义的泛型数据1
+        /// </summary>
+        public T1 Content1 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据2
+        /// </summary>
+        public T2 Content2 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据3
+        /// </summary>
+        public T3 Content3 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据4
+        /// </summary>
+        public T4 Content4 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据5
+        /// </summary>
+        public T5 Content5 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据6
+        /// </summary>
+        public T6 Content6 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据7
+        /// </summary>
+        public T7 Content7 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据8
+        /// </summary>
+        public T8 Content8 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据9
+        /// </summary>
+        public T9 Content9 { get; set; }
+    }
+
+    /// <summary>
+    /// 操作结果的泛型类,允许带十个用户自定义的泛型对象,推荐使用这个类
+    /// </summary>
+    /// <typeparam name="T1">泛型类</typeparam>
+    /// <typeparam name="T2">泛型类</typeparam>
+    /// <typeparam name="T3">泛型类</typeparam>
+    /// <typeparam name="T4">泛型类</typeparam>
+    /// <typeparam name="T5">泛型类</typeparam>
+    /// <typeparam name="T6">泛型类</typeparam>
+    /// <typeparam name="T7">泛型类</typeparam>
+    /// <typeparam name="T8">泛型类</typeparam>
+    /// <typeparam name="T9">泛型类</typeparam>
+    /// <typeparam name="T10">泛型类</typeparam>
+    public class OperateResult<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> : OperateResult
+    {
+        #region Constructor
+
+        /// <summary>
+        /// 实例化一个默认的结果对象
+        /// </summary>
+        public OperateResult() : base()
+        {
+        }
+
+        /// <summary>
+        /// 使用指定的消息实例化一个默认的结果对象
+        /// </summary>
+        /// <param name="msg">错误消息</param>
+        public OperateResult(string msg) : base(msg)
+        {
+
+        }
+
+        /// <summary>
+        /// 使用错误代码,消息文本来实例化对象
+        /// </summary>
+        /// <param name="err">错误代码</param>
+        /// <param name="msg">错误消息</param>
+        public OperateResult(int err, string msg) : base(err, msg)
+        {
+
+        }
+
+        #endregion
+
+        /// <summary>
+        /// 用户自定义的泛型数据1
+        /// </summary>
+        public T1 Content1 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据2
+        /// </summary>
+        public T2 Content2 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据3
+        /// </summary>
+        public T3 Content3 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据4
+        /// </summary>
+        public T4 Content4 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据5
+        /// </summary>
+        public T5 Content5 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据6
+        /// </summary>
+        public T6 Content6 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据7
+        /// </summary>
+        public T7 Content7 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据8
+        /// </summary>
+        public T8 Content8 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据9
+        /// </summary>
+        public T9 Content9 { get; set; }
+
+        /// <summary>
+        /// 用户自定义的泛型数据10
+        /// </summary>
+        public T10 Content10 { get; set; }
+    }
+}

+ 86 - 0
BlankApp1/TFT-MelsecMcNet/SimpleHybirdLock.cs

@@ -0,0 +1,86 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+
+namespace TFT_MelsecMcNet
+{
+    /// <summary>
+    /// 一个简单的混合线程同步锁,采用了基元用户加基元内核同步构造实现
+    /// </summary>
+    public sealed class SimpleHybirdLock : IDisposable
+    {
+
+        #region IDisposable Support
+        private bool disposedValue = false; // 要检测冗余调用
+
+        void Dispose(bool disposing)
+        {
+            if (!disposedValue)
+            {
+                if (disposing)
+                {
+                    // TODO: 释放托管状态(托管对象)。
+                }
+
+                // TODO: 释放未托管的资源(未托管的对象)并在以下内容中替代终结器。
+                // TODO: 将大型字段设置为 null。
+                m_waiterLock.Close();
+
+                disposedValue = true;
+            }
+        }
+
+        // TODO: 仅当以上 Dispose(bool disposing) 拥有用于释放未托管资源的代码时才替代终结器。
+        // ~SimpleHybirdLock() {
+        //   // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
+        //   Dispose(false);
+        // }
+
+        // 添加此代码以正确实现可处置模式。
+        /// <summary>
+        /// 释放资源
+        /// </summary>
+        public void Dispose()
+        {
+            // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
+            Dispose(true);
+            // TODO: 如果在以上内容中替代了终结器,则取消注释以下行。
+            // GC.SuppressFinalize(this);
+        }
+        #endregion
+
+        /// <summary>
+        /// 基元用户模式构造同步锁
+        /// </summary>
+        private int m_waiters = 0;
+        /// <summary>
+        /// 基元内核模式构造同步锁
+        /// </summary>
+        private readonly AutoResetEvent m_waiterLock = new AutoResetEvent(false);
+
+        /// <summary>
+        /// 获取锁
+        /// </summary>
+        public void Enter()
+        {
+            if (Interlocked.Increment(ref m_waiters) == 1) return;//用户锁可以使用的时候,直接返回,第一次调用时发生
+            //当发生锁竞争时,使用内核同步构造锁
+            m_waiterLock.WaitOne();
+        }
+
+        /// <summary>
+        /// 离开锁
+        /// </summary>
+        public void Leave()
+        {
+            if (Interlocked.Decrement(ref m_waiters) == 0) return;//没有可用的锁的时候
+            m_waiterLock.Set();
+        }
+
+        /// <summary>
+        /// 获取当前锁是否在等待当中
+        /// </summary>
+        public bool IsWaitting => m_waiters != 0;
+    }
+}

+ 953 - 0
BlankApp1/TFT-MelsecMcNet/SoftBasic.cs

@@ -0,0 +1,953 @@
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using System.Runtime.Serialization.Formatters.Binary;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace TFT_MelsecMcNet
+{
+    /// <summary>
+    /// 一个软件基础类,提供常用的一些静态方法 ->
+    /// A software-based class that provides some common static methods
+    /// </summary>
+    public class SoftBasic
+    {
+        #region MD5 Calculate
+
+
+        /// <summary>
+        /// 获取文件的md5码 -> Get the MD5 code of the file
+        /// </summary>
+        /// <param name="filePath">文件的路径,既可以是完整的路径,也可以是相对的路径 -> The path to the file</param>
+        /// <returns>Md5字符串</returns>
+        public static string CalculateFileMD5(string filePath)
+        {
+            string str_md5 = string.Empty;
+            using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
+            {
+                str_md5 = CalculateStreamMD5(fs);
+            }
+            return str_md5;
+        }
+
+        /// <summary>
+        /// 获取数据流的md5码 -> Get the MD5 code for the data stream
+        /// </summary>
+        /// <param name="stream">数据流,可以是内存流,也可以是文件流</param>
+        /// <returns>Md5字符串</returns>
+        public static string CalculateStreamMD5(Stream stream)
+        {
+            byte[] bytes_md5 = null;
+            using (MD5 md5 = new MD5CryptoServiceProvider())
+            {
+                bytes_md5 = md5.ComputeHash(stream);
+            }
+            return BitConverter.ToString(bytes_md5).Replace("-", "");
+        }
+
+        /// <summary>
+        /// 获取文本字符串信息的Md5码,编码为UTF8
+        /// </summary>
+        /// <param name="data">文本数据信息</param>
+        /// <returns>Md5字符串</returns>
+        public static string CalculateStreamMD5(string data)
+        {
+            return CalculateStreamMD5(data, Encoding.UTF8);
+        }
+
+        /// <summary>
+        /// 获取文本字符串信息的Md5码,使用指定的编码
+        /// </summary>
+        /// <param name="data">文本数据信息</param>
+        /// <param name="encode">编码信息</param>
+        /// <returns>Md5字符串</returns>
+        public static string CalculateStreamMD5(string data, Encoding encode)
+        {
+            string str_md5 = string.Empty;
+            using (MD5 md5 = new MD5CryptoServiceProvider())
+            {
+                byte[] bytes_md5 = md5.ComputeHash(encode.GetBytes(data));
+                str_md5 = BitConverter.ToString(bytes_md5).Replace("-", "");
+            }
+            return str_md5;
+        }
+
+        #if !NETSTANDARD2_0
+        /// <summary>
+        /// 获取内存图片的md5码 -> Get the MD5 code of the memory picture
+        /// </summary>
+        /// <param name="bitmap">内存图片</param>
+        /// <returns>Md5字符串</returns>
+        public static string CalculateStreamMD5(Bitmap bitmap)
+        {
+            MemoryStream ms = new MemoryStream();
+            bitmap.Save(ms, bitmap.RawFormat);
+            MD5 md5 = new MD5CryptoServiceProvider();
+            byte[] bytes_md5 = md5.ComputeHash(ms);
+            ms.Dispose();
+            return BitConverter.ToString(bytes_md5).Replace("-", "");
+        }
+        #endif
+
+        #endregion
+
+        #region DataSize Format
+
+        /// <summary>
+        /// 从一个字节大小返回带单位的描述
+        /// </summary>
+        /// <param name="size">实际的大小值</param>
+        /// <returns>最终的字符串值</returns>
+        public static string GetSizeDescription(long size)
+        {
+            if (size < 1000)
+            {
+                return size + " B";
+            }
+            else if (size < 1000 * 1000)
+            {
+                float data = (float)size / 1024;
+                return data.ToString("F2") + " Kb";
+            }
+            else if (size < 1000 * 1000 * 1000)
+            {
+                float data = (float)size / 1024 / 1024;
+                return data.ToString("F2") + " Mb";
+            }
+            else
+            {
+                float data = (float)size / 1024 / 1024 / 1024;
+                return data.ToString("F2") + " Gb";
+            }
+        }
+
+        #endregion
+
+        #region TimeSpan Format
+
+        /// <summary>
+        /// 从一个时间差返回带单位的描述
+        /// </summary>
+        /// <param name="ts">实际的时间差</param>
+        /// <returns>最终的字符串值</returns>
+        public static string GetTimeSpanDescription(TimeSpan ts)
+        {
+            if (ts.TotalSeconds <= 60)
+            {
+                return (int)ts.TotalSeconds + " 秒";
+            }
+            else if (ts.TotalMinutes <= 60)
+            {
+                return ts.TotalMinutes.ToString("F1") + " 分钟";
+            }
+            else if (ts.TotalHours <= 24)
+            {
+                return ts.TotalHours.ToString("F1") + " 小时";
+            }
+            else
+            {
+                return ts.TotalDays.ToString("F1") + " 天";
+            }
+        }
+
+        #endregion
+
+        #region Array Expaned
+
+        /// <summary>
+        /// 一个通用的数组新增个数方法,会自动判断越界情况,越界的情况下,会自动的截断或是填充 -> 
+        /// A common array of new methods, will automatically determine the cross-border situation, in the case of cross-border, will be automatically truncated or filled
+        /// </summary>
+        /// <typeparam name="T">数据类型</typeparam>
+        /// <param name="array">原数据</param>
+        /// <param name="data">等待新增的数据</param>
+        /// <param name="max">原数据的最大值</param>
+        public static void AddArrayData<T>(ref T[] array, T[] data, int max)
+        {
+            if (data == null) return;           // 数据为空
+            if (data.Length == 0) return;       // 数据长度为空
+
+            if (array.Length == max)
+            {
+                Array.Copy(array, data.Length, array, 0, array.Length - data.Length);
+                Array.Copy(data, 0, array, array.Length - data.Length, data.Length);
+            }
+            else
+            {
+                if ((array.Length + data.Length) > max)
+                {
+                    T[] tmp = new T[max];
+                    for (int i = 0; i < (max - data.Length); i++)
+                    {
+                        tmp[i] = array[i + (array.Length - max + data.Length)];
+                    }
+                    for (int i = 0; i < data.Length; i++)
+                    {
+                        tmp[tmp.Length - data.Length + i] = data[i];
+                    }
+                    // 更新数据
+                    array = tmp;
+                }
+                else
+                {
+                    T[] tmp = new T[array.Length + data.Length];
+                    for (int i = 0; i < array.Length; i++)
+                    {
+                        tmp[i] = array[i];
+                    }
+                    for (int i = 0; i < data.Length; i++)
+                    {
+                        tmp[tmp.Length - data.Length + i] = data[i];
+                    }
+
+                    array = tmp;
+                }
+            }
+        }
+
+        /// <summary>
+        /// 将一个数组进行扩充到指定长度,或是缩短到指定长度 ->
+        /// Extend an array to a specified length, or shorten to a specified length or fill
+        /// </summary>
+        /// <typeparam name="T">数组的类型</typeparam>
+        /// <param name="data">原先数据的数据</param>
+        /// <param name="length">新数组的长度</param>
+        /// <returns>新数组长度信息</returns>
+        public static T[] ArrayExpandToLength<T>(T[] data, int length)
+        {
+            if (data == null) return new T[length];
+
+            if (data.Length == length) return data;
+
+            T[] buffer = new T[length];
+
+            Array.Copy(data, buffer, Math.Min(data.Length, buffer.Length));
+
+            return buffer;
+        }
+
+
+        /// <summary>
+        /// 将一个数组进行扩充到偶数长度 ->
+        /// Extend an array to even lengths
+        /// </summary>
+        /// <typeparam name="T">数组的类型</typeparam>
+        /// <param name="data">原先数据的数据</param>
+        /// <returns>新数组长度信息</returns>
+        public static T[] ArrayExpandToLengthEven<T>(T[] data)
+        {
+            if (data == null) return new T[0];
+
+            if (data.Length % 2 == 1)
+            {
+                return ArrayExpandToLength(data, data.Length + 1);
+            }
+            else
+            {
+                return data;
+            }
+        }
+
+        /// <summary>
+        /// 将指定的数据按照指定长度进行分割,例如int[10],指定长度4,就分割成int[4],int[4],int[2],然后拼接list
+        /// </summary>
+        /// <typeparam name="T">数组的类型</typeparam>
+        /// <param name="array">等待分割的数组</param>
+        /// <param name="length">指定的长度信息</param>
+        /// <returns>分割后结果内容</returns>
+        public static List<T[]> ArraySplitByLength<T>(T[] array, int length)
+        {
+            if (array == null) return new List<T[]>();
+
+            List<T[]> result = new List<T[]>();
+            int index = 0;
+            while (index < array.Length)
+            {
+                if (index + length < array.Length)
+                {
+                    T[] tmp = new T[length];
+                    Array.Copy(array, index, tmp, 0, length);
+                    index += length;
+                    result.Add(tmp);
+                }
+                else
+                {
+                    T[] tmp = new T[array.Length - index];
+                    Array.Copy(array, index, tmp, 0, tmp.Length);
+                    index += length;
+                    result.Add(tmp);
+                }
+            }
+            return result;
+        }
+
+
+        /// <summary>
+        /// 将整数进行有效的拆分成数组
+        /// </summary>
+        /// <param name="integer">整数信息</param>
+        /// <param name="everyLength">单个的数组长度</param>
+        /// <returns>拆分后的数组长度</returns>
+        public static int[] SplitIntegerToArray(int integer, int everyLength)
+        {
+            int[] result = new int[(integer / everyLength) + ((integer % everyLength) == 0 ? 0 : 1)];
+            for (int i = 0; i < result.Length; i++)
+            {
+                if (i == result.Length - 1)
+                {
+                    result[i] = (integer % everyLength) == 0 ? everyLength : (integer % everyLength);
+                }
+                else
+                {
+                    result[i] = everyLength;
+                }
+            }
+            return result;
+        }
+
+        #endregion
+
+        #region Byte Array compare
+
+        /// <summary>
+        /// 判断两个字节的指定部分是否相同 ->
+        /// Determines whether the specified portion of a two-byte is the same
+        /// </summary>
+        /// <param name="b1">第一个字节</param>
+        /// <param name="start1">第一个字节的起始位置</param>
+        /// <param name="b2">第二个字节</param>
+        /// <param name="start2">第二个字节的起始位置</param>
+        /// <param name="length">校验的长度</param>
+        /// <returns>返回是否相等</returns>
+        /// <exception cref="IndexOutOfRangeException"></exception>
+        public static bool IsTwoBytesEquel(byte[] b1, int start1, byte[] b2, int start2, int length)
+        {
+            if (b1 == null || b2 == null) return false;
+            for (int i = 0; i < length; i++)
+            {
+                if (b1[i + start1] != b2[i + start2])
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        /// <summary>
+        /// 判断两个字节的指定部分是否相同 ->
+        /// Determines whether the specified portion of a two-byte is the same
+        /// </summary>
+        /// <param name="b1">第一个字节</param>
+        /// <param name="b2">第二个字节</param>
+        /// <returns>返回是否相等</returns>
+        public static bool IsTwoBytesEquel(byte[] b1, byte[] b2)
+        {
+            if (b1 == null || b2 == null) return false;
+            if (b1.Length != b2.Length) return false;
+            return IsTwoBytesEquel(b1, 0, b2, 0, b1.Length);
+        }
+
+
+        /// <summary>
+        /// 判断两个数据的令牌是否相等 ->
+        /// Determines whether the tokens of two data are equal
+        /// </summary>
+        /// <param name="head">字节数据</param>
+        /// <param name="token">GUID数据</param>
+        /// <returns>返回是否相等</returns>
+        public static bool IsByteTokenEquel(byte[] head, Guid token)
+        {
+            return IsTwoBytesEquel(head, 12, token.ToByteArray(), 0, 16);
+        }
+
+
+        /// <summary>
+        /// 判断两个数据的令牌是否相等 ->
+        /// Determines whether the tokens of two data are equal
+        /// </summary>
+        /// <param name="token1">第一个令牌</param>
+        /// <param name="token2">第二个令牌</param>
+        /// <returns>返回是否相等</returns>
+        public static bool IsTwoTokenEquel(Guid token1, Guid token2)
+        {
+            return IsTwoBytesEquel(token1.ToByteArray(), 0, token2.ToByteArray(), 0, 16);
+        }
+
+
+
+        #endregion
+
+        #region Enum About
+
+        /// <summary>
+        /// 获取一个枚举类型的所有枚举值,可直接应用于组合框数据 ->
+        /// Gets all the enumeration values of an enumeration type that can be applied directly to the combo box data
+        /// </summary>
+        /// <typeparam name="TEnum">枚举的类型值</typeparam>
+        /// <returns>枚举值数组</returns>
+        public static TEnum[] GetEnumValues<TEnum>() where TEnum : struct
+        {
+            return (TEnum[])Enum.GetValues(typeof(TEnum));
+        }
+
+        /// <summary>
+        /// 从字符串的枚举值数据转换成真实的枚举值数据 ->
+        /// Convert enumeration value data from strings to real enumeration value data
+        /// </summary>
+        /// <typeparam name="TEnum">枚举的类型值</typeparam>
+        /// <param name="value">枚举的字符串的数据值</param>
+        /// <returns>真实的枚举值</returns>
+        public static TEnum GetEnumFromString<TEnum>(string value) where TEnum : struct
+        {
+            return (TEnum)Enum.Parse(typeof(TEnum), value);
+        }
+
+        #endregion
+
+        #region JSON Data Get
+
+        /// <summary>
+        /// 一个泛型方法,提供json对象的数据读取 ->
+        /// A generic method that provides data read for a JSON object
+        /// </summary>
+        /// <typeparam name="T">读取的泛型</typeparam>
+        /// <param name="json">json对象</param>
+        /// <param name="value_name">值名称</param>
+        /// <param name="default_value">默认值</param>
+        /// <returns>值对象</returns>
+        public static T GetValueFromJsonObject<T>(JObject json, string value_name, T default_value)
+        {
+            if (json.Property(value_name) != null)
+            {
+                return json.Property(value_name).Value.Value<T>();
+            }
+            else
+            {
+                return default_value;
+            }
+        }
+
+
+
+        /// <summary>
+        /// 一个泛型方法,提供json对象的数据写入 ->
+        /// A generic method that provides data writing to a JSON object
+        /// </summary>
+        /// <typeparam name="T">写入的泛型</typeparam>
+        /// <param name="json">json对象</param>
+        /// <param name="property">值名称</param>
+        /// <param name="value">值数据</param>
+        public static void JsonSetValue<T>(JObject json, string property, T value)
+        {
+            if (json.Property(property) != null)
+            {
+                json.Property(property).Value = new JValue(value);
+            }
+            else
+            {
+                json.Add(property, new JValue(value));
+            }
+        }
+
+
+        #endregion
+
+        #region Exception Message Format
+
+        #if !NETSTANDARD2_0
+
+        /// <summary>
+        /// 显示一个完整的错误信息 ->
+        /// Displays a complete error message
+        /// </summary>
+        /// <param name="ex">异常对象</param>
+        /// <remarks>调用本方法可以显示一个异常的详细信息</remarks>
+        /// <exception cref="NullReferenceException"></exception>
+        public static void ShowExceptionMessage(Exception ex)
+        {
+            //MessageBox.Show(GetExceptionMessage(ex));
+        }
+
+
+        /// <summary>
+        /// 显示一个完整的错误信息,和额外的字符串描述信息 ->
+        /// Displays a complete error message, and additional string description information
+        /// </summary>
+        /// <param name="extraMsg">额外的描述信息</param>
+        /// <remarks>调用本方法可以显示一个异常的详细信息</remarks>
+        /// <param name="ex">异常对象</param>
+        /// <exception cref="NullReferenceException"></exception>
+        public static void ShowExceptionMessage(string extraMsg, Exception ex)
+        {
+            //MessageBox.Show(GetExceptionMessage(extraMsg, ex));
+        }
+
+        #endif
+
+        /// <summary>
+        /// 获取一个异常的完整错误信息 ->
+        /// Gets the complete error message for an exception
+        /// </summary>
+        /// <param name="ex">异常对象</param>
+        /// <returns>完整的字符串数据</returns>
+        /// <remarks>获取异常的完整信息</remarks>
+        /// <exception cref="NullReferenceException">ex不能为空</exception>
+        public static string GetExceptionMessage(Exception ex)
+        {
+            return StringResources.Language.ExceptionMessage + ex.Message + Environment.NewLine +
+                StringResources.Language.ExceptionStackTrace + ex.StackTrace + Environment.NewLine +
+                StringResources.Language.ExceptopnTargetSite + ex.TargetSite;
+        }
+
+        /// <summary>
+        /// 获取一个异常的完整错误信息,和额外的字符串描述信息 ->
+        /// Gets the complete error message for an exception, and additional string description information
+        /// </summary>
+        /// <param name="extraMsg">额外的信息</param>
+        /// <param name="ex">异常对象</param>
+        /// <returns>完整的字符串数据</returns>
+        /// <exception cref="NullReferenceException"></exception>
+        public static string GetExceptionMessage(string extraMsg, Exception ex)
+        {
+            if (string.IsNullOrEmpty(extraMsg))
+            {
+                return GetExceptionMessage(ex);
+            }
+            else
+            {
+                return extraMsg + Environment.NewLine + GetExceptionMessage(ex);
+            }
+        }
+
+
+        #endregion
+
+        #region Hex string and Byte[] transform
+
+
+        /// <summary>
+        /// 字节数据转化成16进制表示的字符串 ->
+        /// Byte data into a string of 16 binary representations
+        /// </summary>
+        /// <param name="InBytes">字节数组</param>
+        /// <returns>返回的字符串</returns>
+        /// <exception cref="NullReferenceException"></exception>
+        public static string ByteToHexString(byte[] InBytes)
+        {
+            return ByteToHexString(InBytes, (char)0);
+        }
+
+        /// <summary>
+        /// 字节数据转化成16进制表示的字符串 ->
+        /// Byte data into a string of 16 binary representations
+        /// </summary>
+        /// <param name="InBytes">字节数组</param>
+        /// <param name="segment">分割符</param>
+        /// <returns>返回的字符串</returns>
+        /// <exception cref="NullReferenceException"></exception>
+        public static string ByteToHexString(byte[] InBytes, char segment)
+        {
+            StringBuilder sb = new StringBuilder();
+            foreach (byte InByte in InBytes)
+            {
+                if (segment == 0) sb.Append(string.Format("{0:X2}", InByte));
+                else sb.Append(string.Format("{0:X2}{1}", InByte, segment));
+            }
+
+            if (segment != 0 && sb.Length > 1 && sb[sb.Length - 1] == segment)
+            {
+                sb.Remove(sb.Length - 1, 1);
+            }
+            return sb.ToString();
+        }
+
+
+
+        /// <summary>
+        /// 字符串数据转化成16进制表示的字符串 ->
+        /// String data into a string of 16 binary representations
+        /// </summary>
+        /// <param name="InString">输入的字符串数据</param>
+        /// <returns>返回的字符串</returns>
+        /// <exception cref="NullReferenceException"></exception>
+        public static string ByteToHexString(string InString)
+        {
+            return ByteToHexString(Encoding.Unicode.GetBytes(InString));
+        }
+
+
+        private static List<char> hexCharList = new List<char>()
+        {
+            '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
+        };
+
+        /// <summary>
+        /// 将16进制的字符串转化成Byte数据,将检测每2个字符转化,也就是说,中间可以是任意字符 ->
+        /// Converts a 16-character string into byte data, which will detect every 2 characters converted, that is, the middle can be any character
+        /// </summary>
+        /// <param name="hex">十六进制的字符串,中间可以是任意的分隔符</param>
+        /// <returns>转换后的字节数组</returns>
+        /// <remarks>参数举例:AA 01 34 A8</remarks>
+        public static byte[] HexStringToBytes(string hex)
+        {
+            hex = hex.ToUpper();
+
+            MemoryStream ms = new MemoryStream();
+
+            for (int i = 0; i < hex.Length; i++)
+            {
+                if ((i + 1) < hex.Length)
+                {
+                    if (hexCharList.Contains(hex[i]) && hexCharList.Contains(hex[i + 1]))
+                    {
+                        // 这是一个合格的字节数据
+                        ms.WriteByte((byte)(hexCharList.IndexOf(hex[i]) * 16 + hexCharList.IndexOf(hex[i + 1])));
+                        i++;
+                    }
+                }
+            }
+
+            byte[] result = ms.ToArray();
+            ms.Dispose();
+            return result;
+        }
+
+        #endregion
+
+        #region Byte Reverse By Word
+
+        /// <summary>
+        /// 将byte数组按照双字节进行反转,如果为单数的情况,则自动补齐 ->
+        /// Reverses the byte array by double byte, or if the singular is the case, automatically
+        /// </summary>
+        /// <param name="inBytes">输入的字节信息</param>
+        /// <returns>反转后的数据</returns>
+        public static byte[] BytesReverseByWord(byte[] inBytes)
+        {
+            if (inBytes == null) return null;
+            byte[] buffer = ArrayExpandToLengthEven(inBytes);
+
+            for (int i = 0; i < buffer.Length / 2; i++)
+            {
+                byte tmp = buffer[i * 2 + 0];
+                buffer[i * 2 + 0] = buffer[i * 2 + 1];
+                buffer[i * 2 + 1] = tmp;
+            }
+
+            return buffer;
+        }
+
+        #endregion
+
+        #region Byte[] and AsciiByte[] transform
+
+        /// <summary>
+        /// 将原始的byte数组转换成ascii格式的byte数组 ->
+        /// Converts the original byte array to an ASCII-formatted byte array
+        /// </summary>
+        /// <param name="inBytes">等待转换的byte数组</param>
+        /// <returns>转换后的数组</returns>
+        public static byte[] BytesToAsciiBytes(byte[] inBytes)
+        {
+            return Encoding.ASCII.GetBytes(ByteToHexString(inBytes));
+        }
+
+        /// <summary>
+        /// 将ascii格式的byte数组转换成原始的byte数组 ->
+        /// Converts an ASCII-formatted byte array to the original byte array
+        /// </summary>
+        /// <param name="inBytes">等待转换的byte数组</param>
+        /// <returns>转换后的数组</returns>
+        public static byte[] AsciiBytesToBytes(byte[] inBytes)
+        {
+            return HexStringToBytes(Encoding.ASCII.GetString(inBytes));
+        }
+
+        /// <summary>
+        /// 从字节构建一个ASCII格式的数据内容
+        /// </summary>
+        /// <param name="value">数据</param>
+        /// <returns>ASCII格式的字节数组</returns>
+        public static byte[] BuildAsciiBytesFrom(byte value)
+        {
+            return Encoding.ASCII.GetBytes(value.ToString("X2"));
+        }
+
+        /// <summary>
+        /// 从short构建一个ASCII格式的数据内容
+        /// </summary>
+        /// <param name="value">数据</param>
+        /// <returns>ASCII格式的字节数组</returns>
+        public static byte[] BuildAsciiBytesFrom(short value)
+        {
+            return Encoding.ASCII.GetBytes(value.ToString("X4"));
+        }
+
+        /// <summary>
+        /// 从ushort构建一个ASCII格式的数据内容
+        /// </summary>
+        /// <param name="value">数据</param>
+        /// <returns>ASCII格式的字节数组</returns>
+        public static byte[] BuildAsciiBytesFrom(ushort value)
+        {
+            return Encoding.ASCII.GetBytes(value.ToString("X4"));
+        }
+
+        /// <summary>
+        /// 从字节数组构建一个ASCII格式的数据内容
+        /// </summary>
+        /// <param name="value">字节信息</param>
+        /// <returns>ASCII格式的地址</returns>
+        public static byte[] BuildAsciiBytesFrom(byte[] value)
+        {
+            byte[] buffer = new byte[value.Length * 2];
+            for (int i = 0; i < value.Length; i++)
+            {
+                SoftBasic.BuildAsciiBytesFrom(value[i]).CopyTo(buffer, 2 * i);
+            }
+            return buffer;
+        }
+
+        #endregion
+
+        #region Bool[] and byte[] transform
+
+        /// <summary>
+        /// 将bool数组转换到byte数组 ->
+        /// Converting a bool array to a byte array
+        /// </summary>
+        /// <param name="array">bool数组</param>
+        /// <returns>转换后的字节数组</returns>
+        public static byte[] BoolArrayToByte(bool[] array)
+        {
+            if (array == null) return null;
+
+            int length = array.Length % 8 == 0 ? array.Length / 8 : array.Length / 8 + 1;
+            byte[] buffer = new byte[length];
+
+            for (int i = 0; i < array.Length; i++)
+            {
+                int index = i / 8;
+                int offect = i % 8;
+
+                byte temp = 0;
+                switch (offect)
+                {
+                    case 0: temp = 0x01; break;
+                    case 1: temp = 0x02; break;
+                    case 2: temp = 0x04; break;
+                    case 3: temp = 0x08; break;
+                    case 4: temp = 0x10; break;
+                    case 5: temp = 0x20; break;
+                    case 6: temp = 0x40; break;
+                    case 7: temp = 0x80; break;
+                    default: break;
+                }
+
+                if (array[i]) buffer[index] += temp;
+            }
+
+            return buffer;
+        }
+
+        /// <summary>
+        /// 从Byte数组中提取位数组,length代表位数 ->
+        /// Extracts a bit array from a byte array, length represents the number of digits
+        /// </summary>
+        /// <param name="InBytes">原先的字节数组</param>
+        /// <param name="length">想要转换的长度,如果超出自动会缩小到数组最大长度</param>
+        /// <returns>转换后的bool数组</returns>
+        public static bool[] ByteToBoolArray(byte[] InBytes, int length)
+        {
+            if (InBytes == null) return null;
+
+            if (length > InBytes.Length * 8) length = InBytes.Length * 8;
+            bool[] buffer = new bool[length];
+
+            for (int i = 0; i < length; i++)
+            {
+                int index = i / 8;
+                int offect = i % 8;
+
+                byte temp = 0;
+                switch (offect)
+                {
+                    case 0: temp = 0x01; break;
+                    case 1: temp = 0x02; break;
+                    case 2: temp = 0x04; break;
+                    case 3: temp = 0x08; break;
+                    case 4: temp = 0x10; break;
+                    case 5: temp = 0x20; break;
+                    case 6: temp = 0x40; break;
+                    case 7: temp = 0x80; break;
+                    default: break;
+                }
+
+                if ((InBytes[index] & temp) == temp)
+                {
+                    buffer[i] = true;
+                }
+            }
+
+            return buffer;
+        }
+
+        /// <summary>
+        /// 从Byte数组中提取所有的位数组 ->
+        /// Extracts a bit array from a byte array, length represents the number of digits
+        /// </summary>
+        /// <param name="InBytes">原先的字节数组</param>
+        /// <returns>转换后的bool数组</returns>
+        public static bool[] ByteToBoolArray(byte[] InBytes)
+        {
+            if (InBytes == null) return null;
+
+            return ByteToBoolArray(InBytes, InBytes.Length * 8);
+        }
+
+        #endregion
+
+        #region Byte[] Splice
+
+        /// <summary>
+        /// 拼接2个字节数组成一个数组 ->
+        /// Splicing 2 bytes to to an array
+        /// </summary>
+        /// <param name="bytes1">数组一</param>
+        /// <param name="bytes2">数组二</param>
+        /// <returns>拼接后的数组</returns>
+        public static byte[] SpliceTwoByteArray(byte[] bytes1, byte[] bytes2)
+        {
+            if (bytes1 == null && bytes2 == null) return null;
+            if (bytes1 == null) return bytes2;
+            if (bytes2 == null) return bytes1;
+
+            byte[] buffer = new byte[bytes1.Length + bytes2.Length];
+            bytes1.CopyTo(buffer, 0);
+            bytes2.CopyTo(buffer, bytes1.Length);
+            return buffer;
+        }
+
+        /// <summary>
+        /// 选择一个byte数组的前面的几个byte数据信息
+        /// </summary>
+        /// <param name="value">原始的数据信息</param>
+        /// <param name="length">数据的长度</param>
+        /// <returns>选择的前面的几个数据信息</returns>
+        public static byte[] BytesArraySelectBegin(byte[] value, int length)
+        {
+            byte[] buffer = new byte[Math.Min(value.Length, length)];
+            Array.Copy(value, 0, buffer, 0, buffer.Length);
+            return buffer;
+        }
+
+        /// <summary>
+        /// 将一个byte数组的前面指定位数移除,返回新的一个数组 ->
+        /// Removes the preceding specified number of bits in a byte array, returning a new array
+        /// </summary>
+        /// <param name="value">字节数组</param>
+        /// <param name="length">等待移除的长度</param>
+        /// <returns>新的数据</returns>
+        public static byte[] BytesArrayRemoveBegin(byte[] value, int length)
+        {
+            return BytesArrayRemoveDouble(value, length, 0);
+        }
+
+        /// <summary>
+        /// 将一个byte数组的后面指定位数移除,返回新的一个数组 ->
+        /// Removes the specified number of digits after a byte array, returning a new array
+        /// </summary>
+        /// <param name="value">字节数组</param>
+        /// <param name="length">等待移除的长度</param>
+        /// <returns>新的数据</returns>
+        public static byte[] BytesArrayRemoveLast(byte[] value, int length)
+        {
+            return BytesArrayRemoveDouble(value, 0, length);
+        }
+
+        /// <summary>
+        /// 将一个byte数组的前后移除指定位数,返回新的一个数组 ->
+        /// Removes a byte array before and after the specified number of bits, returning a new array
+        /// </summary>
+        /// <param name="value">字节数组</param>
+        /// <param name="leftLength">前面的位数</param>
+        /// <param name="rightLength">后面的位数</param>
+        /// <returns>新的数据</returns>
+        public static byte[] BytesArrayRemoveDouble(byte[] value, int leftLength, int rightLength)
+        {
+            if (value == null) return null;
+            if (value.Length <= (leftLength + rightLength)) return new byte[0];
+
+            byte[] buffer = new byte[value.Length - leftLength - rightLength];
+            Array.Copy(value, leftLength, buffer, 0, buffer.Length);
+
+            return buffer;
+        }
+
+        #endregion
+
+        #region Basic Framework
+
+        /// <summary>
+        /// 设置或获取系统框架的版本号 ->
+        /// Set or get the version number of the system framework
+        /// </summary>
+        /// <remarks>
+        /// 当你要显示本组件框架的版本号的时候,就可以用这个属性来显示
+        /// </remarks>
+        //public static SystemVersion FrameworkVersion { get; set; } = new SystemVersion("7.0.0");
+
+
+        #endregion
+
+        #region Deep Clone
+
+        /// <summary>
+        /// 使用序列化反序列化深度克隆一个对象,该对象需要支持序列化特性 ->
+        /// Cloning an object with serialization deserialization depth that requires support for serialization attributes
+        /// </summary>
+        /// <param name="oringinal">源对象,支持序列化</param>
+        /// <returns>新的一个实例化的对象</returns>
+        /// <exception cref="NullReferenceException"></exception>
+        /// <exception cref="NonSerializedAttribute"></exception>
+        /// <remarks>
+        /// <note type="warning">
+        /// <paramref name="oringinal"/> 参数必须实现序列化的特性
+        /// </note>
+        /// </remarks>
+        public static object DeepClone(object oringinal)
+        {
+            using (MemoryStream stream = new MemoryStream())
+            {
+                BinaryFormatter formatter = new BinaryFormatter()
+                {
+                    Context = new System.Runtime.Serialization.StreamingContext(System.Runtime.Serialization.StreamingContextStates.Clone)
+                };
+                formatter.Serialize(stream, oringinal);
+                stream.Position = 0;
+                return formatter.Deserialize(stream);
+            }
+        }
+
+
+        #endregion
+
+        #region Unique String Get
+
+        /// <summary>
+        /// 获取一串唯一的随机字符串,长度为20,由Guid码和4位数的随机数组成,保证字符串的唯一性 ->
+        /// Gets a string of unique random strings with a length of 20, consisting of a GUID code and a 4-digit random number to guarantee the uniqueness of the string
+        /// </summary>
+        /// <returns>随机字符串数据</returns>
+        public static string GetUniqueStringByGuidAndRandom()
+        {
+            Random random = new Random();
+            return Guid.NewGuid().ToString("N") + random.Next(1000, 10000);
+        }
+
+        #endregion
+    }
+}

+ 69 - 0
BlankApp1/TFT-MelsecMcNet/StateObject.cs

@@ -0,0 +1,69 @@
+using System;
+using System.Collections.Generic;
+using System.Net.Sockets;
+using System.Text;
+
+namespace TFT_MelsecMcNet
+{
+    /// <summary>
+    /// 网络中的异步对象
+    /// </summary>
+    internal class StateObject : StateOneBase
+    {
+        #region Constructor
+
+        /// <summary>
+        /// 实例化一个对象
+        /// </summary>
+        public StateObject()
+        {
+
+        }
+
+        /// <summary>
+        /// 实例化一个对象,指定接收或是发送的数据长度
+        /// </summary>
+        /// <param name="length">数据长度</param>
+        public StateObject(int length)
+        {
+            DataLength = length;
+            Buffer = new byte[length];
+        }
+
+        #endregion
+
+        #region Public Member
+
+        /// <summary>
+        /// 唯一的一串信息
+        /// </summary>
+        public string UniqueId { get; set; }
+
+        /// <summary>
+        /// 网络套接字
+        /// </summary>
+        public TcpClient WorkSocket { get; set; }
+
+        /// <summary>
+        /// 是否关闭了通道
+        /// </summary>
+        public bool IsClose { get; set; }
+
+        #endregion
+
+        #region Public Method
+
+        /// <summary>
+        /// 清空旧的数据
+        /// </summary>
+        public void Clear()
+        {
+            IsError = false;
+            IsClose = false;
+            AlreadyDealLength = 0;
+            Buffer = null;
+        }
+
+        #endregion
+    }
+}

+ 45 - 0
BlankApp1/TFT-MelsecMcNet/StateOneBase.cs

@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+
+namespace TFT_MelsecMcNet
+{
+    /// <summary>
+    /// 异步消息的对象
+    /// </summary>
+    internal class StateOneBase
+    {
+        /// <summary>
+        /// 本次接收或是发送的数据长度  默认
+        /// </summary>
+        public int DataLength { get; set; } = 32;
+
+        /// <summary>
+        /// 已经处理的字节长度
+        /// </summary>
+        public int AlreadyDealLength { get; set; }
+
+        /// <summary>
+        /// 操作完成的信号
+        /// </summary>
+        public ManualResetEvent WaitDone { get; set; }
+
+
+        /// <summary>
+        /// 缓存器
+        /// </summary>
+        public byte[] Buffer { get; set; }
+
+
+        /// <summary>
+        /// 是否发生了错误
+        /// </summary>
+        public bool IsError { get; set; }
+
+        /// <summary>
+        /// 错误消息
+        /// </summary>
+        public string ErrerMsg { get; set; }
+    }
+}

+ 64 - 0
BlankApp1/TFT-MelsecMcNet/StringResources.cs

@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TFT_MelsecMcNet
+{
+    /*******************************************************************************
+     * 
+     *    用于显示和保存的数据信息,未来支持中英文
+     *
+     *    Used to the return result class in the synchronize communication and communication for industrial Ethernet
+     * 
+     *******************************************************************************/
+
+
+
+    /// <summary>
+    /// 系统的字符串资源及多语言管理中心 ->
+    /// System string resource and multi-language management Center
+    /// </summary>
+    public static class StringResources
+    {
+        #region Constractor
+
+        static StringResources()
+        {
+            if (System.Globalization.CultureInfo.CurrentCulture.ToString().StartsWith("zh"))
+            {
+                SetLanguageChinese();
+            }
+            else
+            {
+                SeteLanguageEnglish();
+            }
+        }
+
+        #endregion
+
+
+        /// <summary>
+        /// 获取或设置系统的语言选项 ->
+        /// Gets or sets the language options for the system
+        /// </summary>
+        public static DefaultLanguage Language = new();
+
+        /// <summary>
+        /// 将语言设置为中文 ->
+        /// Set the language to Chinese
+        /// </summary>
+        public static void SetLanguageChinese()
+        {
+            Language = new DefaultLanguage();
+        }
+
+        /// <summary>
+        /// 将语言设置为英文 ->
+        /// Set the language to English
+        /// </summary>
+        public static void SeteLanguageEnglish()
+        {
+            Language = new English();
+        }
+    }
+}

+ 56 - 0
BlankApp1/TFT-MelsecMcNet/SylTimeOut.cs

@@ -0,0 +1,56 @@
+/*
+* ***************************************************************************
+* 
+*    应用于一些操作超时请求的判断功能 
+* 
+*    When applied to a network connection request timeouts
+* 
+* **************************************************************************
+*/
+using System;
+using System.Net.Sockets;
+
+namespace TFT_MelsecMcNet
+{
+    /// <summary>
+    /// 自定义 超时操作的类 [a class use to indicate the time-out of the connection]
+    /// </summary>
+    internal class SylTimeOut
+    {
+        /// <summary>
+        /// 实例化对象
+        /// </summary>
+        public SylTimeOut()
+        {
+            StartTime = DateTime.Now;
+            IsSuccessful = false;
+            HybirdLock = new SimpleHybirdLock();
+        }
+
+        /// <summary>
+        /// 操作的开始时间
+        /// </summary>
+        public DateTime StartTime { get; set; }
+        /// <summary>
+        /// 操作是否成功
+        /// </summary>
+        public bool IsSuccessful { get; set; }
+        /// <summary>
+        /// 延时的时间,单位毫秒
+        /// </summary>
+        public int DelayTime { get; set; }
+        /// <summary>
+        /// 连接超时用的Socket
+        /// </summary>
+        public TcpClient WorkSocket { get; set; }
+        /// <summary>
+        /// 用于超时执行的方法
+        /// </summary>
+        public Action Operator { get; set; }
+
+        /// <summary>
+        /// 当前对象判断的同步锁
+        /// </summary>
+        public SimpleHybirdLock HybirdLock { get; set; }
+    }
+}

+ 15 - 0
BlankApp1/TFT-MelsecMcNet/TFT-MelsecMcNet.csproj

@@ -0,0 +1,15 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+	<TargetFrameworks>net6.0;</TargetFrameworks>
+    <RootNamespace>TFT_MelsecMcNet</RootNamespace>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <Nullable>enable</Nullable>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
+    <PackageReference Include="System.Drawing.Common" Version="7.0.0" />
+  </ItemGroup>
+
+</Project>