本文主要是介绍macad.common解析interop、serialization、types,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
1.intertop(互操作)
using System;
using System.Runtime.InteropServices;namespace Macad.Common.Interop
{/// <summary>/// HRESULT 状态码的包装器。/// </summary>[StructLayout(LayoutKind.Explicit)]public readonly struct HRESULT{[FieldOffset(0)]readonly uint _value;// HRESULT 值的字段声明,通过反射自动由 ToString 方法获取/// <summary>S_OK</summary>public static readonly HRESULT S_OK = new HRESULT(0x00000000);/// <summary>S_FALSE</summary>public static readonly HRESULT S_FALSE = new HRESULT(0x00000001);/// <summary>E_NOTIMPL</summary>public static readonly HRESULT E_NOTIMPL = new HRESULT(0x80004001);// 其他 HRESULT 值的声明.../// <summary>/// 初始化 HRESULT 结构的新实例。/// </summary>/// <param name="i">值。</param>public HRESULT(uint i){_value = i;}/// <summary>/// 指示此实例和指定的对象是否相等。/// </summary>/// <param name="obj">要与当前实例进行比较的对象。</param>/// <returns>如果 <paramref name="obj"/> 和此实例是相同类型并且表示相同的值,则为 true;否则为 false。</returns>public override bool Equals(object obj){try{return ((HRESULT)obj)._value == _value;}catch (InvalidCastException){return false;}}/// <summary>/// 返回此实例的哈希代码。/// </summary>/// <returns>32 位有符号整数哈希代码。</returns>public override int GetHashCode(){return _value.GetHashCode();}/// <summary>/// 指示两个 HRESULT 实例是否相等。/// </summary>/// <param name="errLeft">要比较的第一个 HRESULT。</param>/// <param name="errRight">要比较的第二个 HRESULT。</param>/// <returns>如果 <paramref name="errLeft"/> 和 <paramref name="errRight"/> 表示相同的值,则为 true;否则为 false。</returns>public static bool operator ==(HRESULT errLeft, HRESULT errRight){return errLeft._value == errRight._value;}/// <summary>/// 指示两个 HRESULT 实例是否不相等。/// </summary>/// <param name="errLeft">要比较的第一个 HRESULT。</param>/// <param name="errRight">要比较的第二个 HRESULT。</param>/// <returns>如果 <paramref name="errLeft"/> 和 <paramref name="errRight"/> 表示不同的值,则为 true;否则为 false。</returns>public static bool operator !=(HRESULT errLeft, HRESULT errRight){return !(errLeft == errRight);}}
}
这段代码定义了一个 HRESULT
结构体,用于包装 HRESULT 状态码。通过 FieldOffset
属性将字段偏移量设置为 0,以确保对齐。HRESULT 的常量值在结构体中声明为只读字段,通过这些字段可以轻松地引用各种 HRESULT 状态码。此外,结构体实现了 Equals
、GetHashCode
和相等运算符重载,以便进行相等性比较。
2.
// 禁用 ReSharper 不一致的命名检查
// 在使用 P/Invoke 调用 Windows API 时,通常会采用约定俗成的命名方式,不受 ReSharper 规则限制using System;
using System.Runtime.InteropServices;
using System.Text;namespace Macad.Common.Interop
{public static class Win32Api{#region 常量// 创建具有独立的设备上下文public const int CS_OWNDC = 0x0020;//--------------------------------------------------------------------------------------------------// 窗口风格常量public const uintWS_DISABLED = 0x08000000, // 禁用窗口WS_VISIBLE = 0x10000000, // 显示窗口WS_CHILD = 0x40000000, // 子窗口WS_POPUP = 0x80000000; // 弹出式窗口//--------------------------------------------------------------------------------------------------// 显示窗口的命令public const intSW_SHOWNORMAL = 1, // 正常显示SW_SHOWMINIMIZED = 2; // 最小化显示//--------------------------------------------------------------------------------------------------// 窗口消息常量public const intWM_SETFOCUS = 0x0007, // 设置焦点WM_PAINT = 0x000f, // 绘制消息WM_ENABLE = 0x000a, // 启用窗口WM_SHOWWINDOW = 0x0018, // 显示窗口WM_KEYDOWN = 0x0100, // 键盘按下消息WM_MOUSEMOVE = 0x0200, // 鼠标移动消息WM_LBUTTONDOWN = 0x0201, // 左键按下消息WM_LBUTTONUP = 0x0202, // 左键释放消息WM_RBUTTONDOWN = 0x0204, // 右键按下消息WM_RBUTTONUP = 0x0205, // 右键释放消息WM_MBUTTONDOWN = 0x0207, // 中键按下消息WM_MBUTTONUP = 0x0208, // 中键释放消息WM_MOUSEWHEEL = 0x020a, // 鼠标滚轮消息WM_MOUSELEAVE = 0x02a3, // 鼠标离开消息WM_NCHITTEST = 0x0084, // 非客户区点击测试消息WM_DROPFILES = 0x0233; // 拖放文件消息//--------------------------------------------------------------------------------------------------// 鼠标事件的返回值public const int HTNOWHERE = 0, // 无效区域HTTRANSPARENT = -1; // 透明区域//--------------------------------------------------------------------------------------------------// 全局内存分配标志public const intGMEM_FIXED = 0x0000, // 固定内存GMEM_SHARE = 0x2000, // 共享内存GWL_WNDPROC = -4, // 窗口过程GWL_HWNDPARENT = -8, // 父窗口句柄GWL_STYLE = -16, // 窗口样式GWL_EXSTYLE = -20, // 扩展窗口样式GWL_ID = -12; // 窗口标识符//--------------------------------------------------------------------------------------------------// RedrawWindow 函数的标志位[Flags]public enum RedrawWindowFlags : uint{Invalidate = 0x1, // 使区域无效InternalPaint = 0x2, // 内部绘制Erase = 0x4, // 擦除区域Validate = 0x8, // 验证区域NoInternalPaint = 0x10, // 不使用内部绘制NoErase = 0x20, // 不擦除区域NoChildren = 0x40, // 不包括子窗口AllChildren = 0x80, // 所有子窗口UpdateNow = 0x100, // 立即更新EraseNow = 0x200, // 立即擦除Frame = 0x400, // 框架NoFrame = 0x800 // 无框架}//--------------------------------------------------------------------------------------------------// MiniDumpWriteDump 函数的转储类型[Flags]public enum MINIDUMP_TYPE : uint{MiniDumpNormal = 0x00000000, // 普通转储MiniDumpWithDataSegs = 0x00000001, // 包括数据段MiniDumpWithFullMemory = 0x00000002, // 包括完整内存MiniDumpWithHandleData = 0x00000004, // 包括句柄数据MiniDumpFilterMemory = 0x00000008, // 过滤内存MiniDumpScanMemory = 0x00000010, // 扫描内存MiniDumpWithUnloadedModules = 0x00000020, // 包括未加载模块MiniDumpWithIndirectlyReferencedMemory = 0x00000040, // 包括间接引用的内存MiniDumpFilterModulePaths = 0x00000080, // 过滤模块路径MiniDumpWithProcessThreadData = 0x00000100, // 包括进程线程数据MiniDumpWithPrivateReadWriteMemory = 0x00000200, // 包括私有读写内存MiniDumpWithoutOptionalData = 0x00000400, // 不包括可选数据MiniDumpWithFullMemoryInfo = 0x00000800, // 包括完整内存信息MiniDumpWithThreadInfo = 0x00001000, // 包括线程信息MiniDumpWithCodeSegs = 0x00002000, // 包括代码段MiniDumpWithoutManagedState = 0x00004000, // 不包括托管状态};//--------------------------------------------------------------------------------------------------// 安全描述符的版本public const uint SECURITY_DESCRIPTOR_REVISION = 1;//--------------------------------------------------------------------------------------------------/// <summary>/// 同步对象的访问权限/// </summary>[Flags]public enum SyncObjectAccess : uint{DELETE = 0x00010000, // 删除对象READ_CONTROL = 0x00020000, // 读取控制权限WRITE_DAC = 0x00040000, // 写入访问控制WRITE_OWNER = 0x00080000, // 写入所有者SYNCHRONIZE = 0x00100000, // 同步访问EVENT_ALL_ACCESS = 0x001F0003, // 所有事件访问权限EVENT_MODIFY_STATE = 0x00000002, // 修改事件状态MUTEX_ALL_ACCESS = 0x001F0001, // 所有互斥对象访问权限MUTEX_MODIFY_STATE = 0x00000001, // 修改互斥对象状态SEMAPHORE_ALL_ACCESS = 0x001F0003, // 所有信号量访问权限SEMAPHORE_MODIFY_STATE = 0x00000002, // 修改信号量状态TIMER_ALL_ACCESS = 0x001F0003, // 所有定时器访问权限TIMER_MODIFY_STATE = 0x00000002, // 修改定时器状态TIMER_QUERY_STATE = 0x00000001 // 查询定时器状态}//--------------------------------------------------------------------------------------------------// HTML 帮助命令[Flags]public enum HtmlHelpCommand : uint{HH_DISPLAY_TOPIC = 0, // 显示主题HH_DISPLAY_TOC = 1, // 显示目录HH_DISPLAY_INDEX = 2, // 显示索引HH_DISPLAY_SEARCH = 3, // 显示搜索HH_DISPLAY_TEXT_POPUP = 0x000E, // 显示文本弹出窗口HH_HELP_CONTEXT = 0x000F, // 帮助上下文HH_CLOSE_ALL = 0x0012 // 关闭所有帮助窗口}//--------------------------------------------------------------------------------------------------// 存储对象的访问模式[Flags]public enum Stgm : uint{STGM_READ = 0x0, // 只读模式STGM_WRITE = 0x1, // 只写模式STGM_READWRITE = 0x2, // 读写模式STGM_SHARE_DENY_NONE = 0x40, // 拒绝共享STGM_SHARE_DENY_READ = 0x30, // 拒绝读共享STGM_SHARE_DENY_WRITE = 0x20, // 拒绝写共享STGM_SHARE_EXCLUSIVE = 0x10, // 独占模式STGM_PRIORITY = 0x40000, // 优先模式STGM_CREATE = 0x1000, // 创建模式STGM_CONVERT = 0x20000, // 转换模式STGM_FAILIFTHERE = 0x0, // 如果存在则失败STGM_DIRECT = 0x0, // 直接模式STGM_TRANSACTED = 0x10000, // 事务模式STGM_NOSCRATCH = 0x100000, // 无备份STGM_NOSNAPSHOT = 0x200000, // 无快照STGM_SIMPLE = 0x8000000, // 简单模式STGM_DIRECT_SWMR = 0x400000, // 直接单写多读模式STGM_DELETEONRELEASE = 0x4000000 // 释放时删除}//--------------------------------------------------------------------------------------------------// MapVirtualKey 函数的映射类型public enum MapVirtualKeyMapTypes{MAPVK_VK_TO_VSC = 0x00, // 虚拟键转换为虚拟扫描码MAPVK_VSC_TO_VK = 0x01, // 虚拟扫描码转换为虚拟键MAPVK_VK_TO_CHAR = 0x02, // 虚拟键转换为字符MAPVK_VSC_TO_VK_EX = 0x03, // 扩展虚拟扫描码转换为虚拟键MAPVK_VK_TO_VSC_EX = 0x04 // 扩展虚拟键转换为虚拟扫描码}//--------------------------------------------------------------------------------------------------#endregion#region 结构体[StructLayout(LayoutKind.Sequential)]public struct POINT{public int x;public int y;public POINT(int x, int y){this.x = x;this.y = y;}}//--------------------------------------------------------------------------------------------------[StructLayout(LayoutKind.Sequential)]public struct RECT{public int Left;public int Top;public int Right;public int Bottom;public RECT(int left, int top, int right, int bottom){Left = left;Top = top;Right = right;Bottom = bottom;}}//--------------------------------------------------------------------------------------------------[StructLayout(LayoutKind.Sequential)]public struct WINDOWPLACEMENT{public int length;public int flags;public int showCmd;public POINT minPosition;public POINT maxPosition;public RECT normalPosition;}//--------------------------------------------------------------------------------------------------[StructLayout(LayoutKind.Sequential)]public struct DROPFILES{public int pFiles;public POINT pt;public bool fNC;public bool fWide;}//--------------------------------------------------------------------------------------------------[StructLayout(LayoutKind.Sequential, Pack = 4)]public struct MINIDUMP_EXCEPTION_INFORMATION{public uint ThreadId;public IntPtr ExceptionPointers;public int ClientPointers;}//--------------------------------------------------------------------------------------------------[StructLayout(LayoutKind.Sequential)]public struct SECURITY_DESCRIPTOR{public byte revision;public byte size;public short control;public IntPtr owner;public IntPtr group;public IntPtr sacl;public IntPtr dacl;}//--------------------------------------------------------------------------------------------------[StructLayout(LayoutKind.Sequential)]public struct SECURITY_ATTRIBUTES{public int nLength;public IntPtr lpSecurityDescriptor;public bool bInheritHandle;}//--------------------------------------------------------------------------------------------------#endregion#region 方法[DllImport("kernel32.dll", SetLastError = true)]public static extern IntPtr GlobalLock(IntPtr Handle);[DllImport("kernel32.dll", SetLastError = true)]public static extern int GlobalUnlock(IntPtr Handle);[DllImport("kernel32.dll")]public static extern IntPtr GetCurrentProcess();[DllImport("kernel32.dll")]public static extern uint GetCurrentProcessId();[DllImport("kernel32.dll")]public static extern uint GetCurrentThreadId();[DllImport("kernel32.dll")]public static extern IntPtr CreateMutex(ref SECURITY_ATTRIBUTES lpMutexAttributes, bool bInitialOwner, string lpName);[DllImport("kernel32.dll")]public static extern IntPtr OpenMutex(uint dwDesiredAccess, bool bInheritHandle, string lpName);[DllImport("kernel32.dll")]public static extern bool ReleaseMutex(IntPtr hMutex);[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]public static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPWStr)] string lpFileName);[DllImport("kernel32.dll")]public static extern bool FreeLibrary(IntPtr hLibModule);[DllImport("kernel32.dll", CharSet = CharSet.Ansi)]public static extern IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string lpProcName);[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]public static extern bool SetDllDirectory(string lpPathName);//--------------------------------------------------------------------------------------------------[DllImport("user32.dll")]public static extern bool EnableWindow(HandleRef hWnd, bool bEnable);//SetWindowLong won't work correctly for 64-bit: we should use SetWindowLongPtr instead. On//32-bit, SetWindowLongPtr is just #defined as SetWindowLong. SetWindowLong really should //take/return int instead of IntPtr/HandleRef, but since we're running this only for 32-bit//it'll be OK.public static IntPtr SetWindowLong(HandleRef hWnd, int nIndex, HandleRef dwNewLong) {if (IntPtr.Size == 4){return SetWindowLongPtr32(hWnd, nIndex, dwNewLong);}return SetWindowLongPtr64(hWnd, nIndex, dwNewLong);}[DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "SetWindowLong")]public static extern IntPtr SetWindowLongPtr32(HandleRef hWnd, int nIndex, HandleRef dwNewLong);[DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "SetWindowLongPtr")]public static extern IntPtr SetWindowLongPtr64(HandleRef hWnd, int nIndex, HandleRef dwNewLong);[DllImport("user32.dll")]public static extern IntPtr SetParent(HandleRef hWnd, HandleRef hWndParent);[DllImport("user32.dll")]public static extern bool GetWindowPlacement(HandleRef hWnd, out WINDOWPLACEMENT lpwndpl);[DllImport("user32.dll")]public static extern bool SetWindowPlacement(HandleRef hWnd, [In] ref WINDOWPLACEMENT lpwndpl);[DllImport("user32.dll")]public static extern IntPtr GetForegroundWindow();[DllImport("user32.dll")]public static extern bool SetForegroundWindow(HandleRef hWnd);[DllImport("user32.dll", SetLastError = true)]public static extern IntPtr SetFocus(HandleRef hWnd);[DllImport("user32.dll", SetLastError = true)]public static extern int SetWindowRgn(HandleRef hWnd, IntPtr hRgn, bool bRedraw);[DllImport("user32.dll")]public static extern bool InvalidateRect(HandleRef hWnd, IntPtr lpRect, bool bErase);[DllImport("user32.dll")]public static extern bool UpdateWindow(HandleRef hWnd);[DllImport("user32.dll")]public static extern bool RedrawWindow(HandleRef hWnd, IntPtr lprcUpdate, IntPtr hrgnUpdate, RedrawWindowFlags flags);[DllImport("user32.dll", EntryPoint = "RegisterWindowMessageW", CharSet = CharSet.Unicode, SetLastError = true)]public static extern uint RegisterWindowMessage(string lpString);[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]public static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);[DllImport("user32.dll")]public static extern uint MapVirtualKey(uint uCode, MapVirtualKeyMapTypes uMapType);[DllImport("user32.dll")]public static extern uint MapVirtualKeyEx(uint uCode, MapVirtualKeyMapTypes uMapType, IntPtr dwhkl);[DllImport("user32.dll", CharSet = CharSet.Unicode)]public static extern short VkKeyScan(char ch);[DllImport("user32.dll", CharSet = CharSet.Unicode)]public static extern short VkKeyScanEx(char ch, IntPtr dwhkl);[DllImport("user32.dll")]public static extern int ToAscii(uint uVirtKey, uint uScanCode, byte [] lpKeyState, [Out] StringBuilder lpChar, uint uFlags);[DllImport("user32.dll")]public static extern int ToAsciiEx(uint uVirtKey, uint uScanCode, byte [] lpKeyState, [Out] StringBuilder lpChar, uint uFlags, IntPtr hkl);[DllImport("user32.dll")]public static extern int ToUnicode(uint wVirtKey, uint wScanCode, byte [] lpKeyState, [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszBuff,int cchBuff, uint wFlags);[DllImport("user32.dll")]public static extern int ToUnicodeEx(uint wVirtKey, uint wScanCode, byte [] lpKeyState, [Out, MarshalAs(UnmanagedType.LPWStr, SizeConst = 64)] StringBuilder pwszBuff,int cchBuff, uint wFlags, IntPtr dwhkl);[DllImport("user32.dll")]public static extern bool GetKeyboardState(byte [] lpKeyState);//--------------------------------------------------------------------------------------------------[DllImport("gdi32.dll", SetLastError = true)]public static extern IntPtr CreateRectRgn(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect);[DllImport("gdi32.dll", SetLastError = true)]public static extern bool DeleteObject(IntPtr hObject);[DllImport("gdi32.dll")]public static extern int CombineRgn(IntPtr hrgnDst, IntPtr hrgnSrc1, IntPtr hrgnSrc2, int fnCombineMode);//--------------------------------------------------------------------------------------------------[DllImport("shell32.dll")]public static extern void DragAcceptFiles(HandleRef hWnd, bool fAccept);[DllImport("shell32.dll")]public static extern void DragFinish(IntPtr hDrop);[DllImport("shell32.dll", CharSet = CharSet.Unicode)]public static extern uint DragQueryFile(IntPtr hDrop, uint iFile, StringBuilder lpszFile, uint cch);//--------------------------------------------------------------------------------------------------[DllImport("dbghelp.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, SetLastError = true)]public static extern bool MiniDumpWriteDump(IntPtr hProcess, uint ProcessId, IntPtr hFile, MINIDUMP_TYPE DumpType, ref MINIDUMP_EXCEPTION_INFORMATION ExceptionParam, IntPtr UserStreamParam, IntPtr CallbackParam);//--------------------------------------------------------------------------------------------------[DllImport("advapi32.dll", SetLastError = true)]public static extern bool InitializeSecurityDescriptor(ref SECURITY_DESCRIPTOR pSecurityDescriptor, uint dwRevision);[DllImport("advapi32.dll", SetLastError = true)]public static extern bool SetSecurityDescriptorDacl(ref SECURITY_DESCRIPTOR pSecurityDescriptor, bool bDaclPresent, IntPtr pDacl, bool bDaclDefaulted);//--------------------------------------------------------------------------------------------------[DllImport("hhctrl.ocx", SetLastError = true)]public static extern IntPtr HtmlHelp(HandleRef hwndCaller, string pszFile, HtmlHelpCommand uCommand, IntPtr dwData);//--------------------------------------------------------------------------------------------------[DllImport("shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags);//--------------------------------------------------------------------------------------------------[DllImport("ole32.dll", SetLastError = true, CharSet = CharSet.Unicode)]public static extern int CoInitializeEx(IntPtr pvReserved, uint dwCoInit);[DllImport("ole32.dll", SetLastError = true)]public static extern void CoUninitialize();//--------------------------------------------------------------------------------------------------[DllImport("ole32.dll", SetLastError = true)]public static extern int OleInitialize(IntPtr pvReserved);[DllImport("ole32.dll", SetLastError = true)]public static extern void OleUninitialize();//--------------------------------------------------------------------------------------------------[DllImport("ole32.dll", CharSet = CharSet.Unicode, PreserveSig = false)]public static extern void CreateBindCtx(uint reserved, out IBindCtx ppbc);//--------------------------------------------------------------------------------------------------[DllImport("ole32.dll", CharSet = CharSet.Unicode)]public static extern int CLSIDFromString([MarshalAs(UnmanagedType.LPWStr)] string lpsz, out Guid pclsid);//--------------------------------------------------------------------------------------------------[DllImport("ole32.dll", CharSet = CharSet.Unicode, PreserveSig = false)]public static extern void CoCreateInstance([In, MarshalAs(UnmanagedType.LPStruct)] Guid rclsid,IntPtr pUnkOuter,CLSCTX dwClsContext,[In, MarshalAs(UnmanagedType.LPStruct)] Guid riid,[MarshalAs(UnmanagedType.IUnknown)] out object ppv);//--------------------------------------------------------------------------------------------------[DllImport("user32.dll")]public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);//--------------------------------------------------------------------------------------------------#endregion}
}
这段代码是一个C#类,其中包含了许多与Windows API交互的方法和结构体定义。这些方法和结构体允许C#代码与底层的Windows操作系统进行交互,执行诸如管理窗口、处理消息、调用系统函数等操作。
具体作用包括但不限于:
- 定义常量: 如窗口消息(例如
WM_SETFOCUS
)、窗口样式(例如WS_DISABLED
)等。 - 定义结构体: 如窗口位置信息(
WINDOWPLACEMENT
)、矩形信息(RECT
)等。 - 声明外部方法: 通过
DllImport
特性声明了许多Windows API函数的原型,如CreateMutex
、EnableWindow
等,这些方法允许C#代码调用底层的Windows API函数。 - 定义枚举类型: 如
RedrawWindowFlags
、MINIDUMP_TYPE
等,用于传递参数或标志位。
总的来说,这段代码提供了一个封装的接口,使得C#程序可以与Windows操作系统进行底层交互,从而实现更多样化的功能和操作。
3.
using System;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.InteropServices;
using Macad.Common.Interop;
using Macad.Common;namespace Macad.Common.Serialization
{// 序列化 Win32 API 结构体的类public class Win32ApiSerializer{// POINT 结构体的序列化器class Win32ApiSerializer_POINT : ISerializer{// 将 POINT 结构体写入流public bool Write(Writer writer, object obj, SerializationContext context){var point = (Win32Api.POINT)obj;var values = new int[] {point.x, point.y};return _IntArraySerializer.Write(writer, values, context);}// 从流中读取数据并创建 POINT 结构体public object Read(Reader reader, object obj, SerializationContext context){var values = (int[])_IntArraySerializer.Read(reader, null, context);if ((values != null) && (values.Length == 2)){return new Win32Api.POINT(values[0], values[1]);}return null;}// 尝试从流中读取数据并创建 POINT 结构体public bool TryRead(Reader reader, SerializationContext context, out Win32Api.POINT point){var obj = Read(reader, null, context);if (obj == null){point = new Win32Api.POINT();return false;}point = (Win32Api.POINT) obj;return true;}}//--------------------------------------------------------------------------------------------------// RECT 结构体的序列化器class Win32ApiSerializer_RECT : ISerializer{// 将 RECT 结构体写入流public bool Write(Writer writer, object obj, SerializationContext context){var rect = (Win32Api.RECT)obj;var values = new int[] {rect.Left, rect.Top, rect.Right, rect.Bottom};return _IntArraySerializer.Write(writer, values, context);}// 从流中读取数据并创建 RECT 结构体public object Read(Reader reader, object obj, SerializationContext context){var values = (int[])_IntArraySerializer.Read(reader, null, context);if ((values != null) && (values.Length == 4)){return new Win32Api.RECT(values[0], values[1], values[2], values[3]);}return null;}// 尝试从流中读取数据并创建 RECT 结构体public bool TryRead(Reader reader, SerializationContext context, out Win32Api.RECT rect){var obj = Read(reader, null, context);if (obj == null){rect = new Win32Api.RECT();return false;}rect = (Win32Api.RECT) obj;return true;}}//--------------------------------------------------------------------------------------------------// WINDOWPLACEMENT 结构体的序列化器class Win32ApiSerializer_WINDOWPLACEMENT : ISerializer{// 将 WINDOWPLACEMENT 结构体写入流public bool Write(Writer writer, object obj, SerializationContext context){var placement = (Win32Api.WINDOWPLACEMENT)obj;writer.BeginList();writer.BeginListValue();writer.WriteValueString(placement.showCmd.ToString());writer.BeginListValue();if (!_SerializerPOINT.Write(writer, placement.maxPosition, context))return false;writer.BeginListValue();if (!_SerializerPOINT.Write(writer, placement.minPosition, context))return false;writer.BeginListValue();if (!_SerializerRECT.Write(writer, placement.normalPosition, context))return false;writer.EndList();return true;}// 从流中读取数据并创建 WINDOWPLACEMENT 结构体public object Read(Reader reader, object obj, SerializationContext context){var placement = new Win32Api.WINDOWPLACEMENT();placement.length = Marshal.SizeOf(placement);if (reader.BeginList()&& reader.BeginListValue()&& int.TryParse(reader.ReadValueString(), out placement.showCmd)&& reader.BeginListValue()&& _SerializerPOINT.TryRead(reader, context, out placement.maxPosition)&& reader.BeginListValue()&& _SerializerPOINT.TryRead(reader, context, out placement.minPosition)&& reader.BeginListValue()&& _SerializerRECT.TryRead(reader, context, out placement.normalPosition)&& reader.EndList()){return placement;}return null;}}//--------------------------------------------------------------------------------------------------// 是否已初始化标志static bool _IsInitialized = false;// int 数组序列化器static ISerializer _IntArraySerializer;// POINT 结构体序列化器static readonly Win32ApiSerializer_POINT _SerializerPOINT = new Win32ApiSerializer_POINT();// RECT 结构体序列化器static readonly Win32ApiSerializer_RECT _SerializerRECT = new Win32ApiSerializer_RECT();// WINDOWPLACEMENT 结构体序列化器static readonly Win32ApiSerializer_WINDOWPLACEMENT _SerializerPLACEMENT = new Win32ApiSerializer_WINDOWPLACEMENT();//--------------------------------------------------------------------------------------------------// 初始化方法public static void Init(){Debug.Assert(!_IsInitialized);_IntArraySerializer = Serializer.GetSerializer(typeof(int[]));Serializer.AddSerializer(typeof(Win32Api.POINT), _SerializerPOINT);Serializer.AddSerializer(typeof(Win32Api.RECT), _SerializerRECT);Serializer.AddSerializer(typeof(Win32Api.WINDOWPLACEMENT), _SerializerPLACEMENT);_IsInitialized = true;}//--------------------------------------------------------------------------------------------------}
}
整段代码的作用是定义了一个用于序列化 Win32 API 结构体的类 Win32ApiSerializer
,其中包含了三个内部类,分别用于对 POINT、RECT 和 WINDOWPLACEMENT 结构体进行序列化。此外,还定义了一个静态的初始化方法 Init()
,用于初始化序列化器,并将各个结构体的序列化器添加到全局的序列化器中。
4.
using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security;namespace Macad.Common
{// 封装 Win32 错误码的只读结构体[StructLayout(LayoutKind.Explicit)]public readonly struct Win32Error{[FieldOffset(0)]readonly int _value;//--------------------------------------------------------------------------------------------------// 常见 Win32 错误码的声明/// <summary>The operation completed successfully.</summary>public static readonly Win32Error ERROR_SUCCESS = new Win32Error(0);/// <summary>Incorrect function.</summary>public static readonly Win32Error ERROR_INVALID_FUNCTION = new Win32Error(1);/// <summary>The system cannot find the file specified.</summary>public static readonly Win32Error ERROR_FILE_NOT_FOUND = new Win32Error(2);/// <summary>The system cannot find the path specified.</summary>public static readonly Win32Error ERROR_PATH_NOT_FOUND = new Win32Error(3);/// <summary>The system cannot open the file.</summary>public static readonly Win32Error ERROR_TOO_MANY_OPEN_FILES = new Win32Error(4);/// <summary>Access is denied.</summary>public static readonly Win32Error ERROR_ACCESS_DENIED = new Win32Error(5);/// <summary>The handle is invalid.</summary>public static readonly Win32Error ERROR_INVALID_HANDLE = new Win32Error(6);/// <summary>Not enough storage is available to complete this operation.</summary>public static readonly Win32Error ERROR_OUTOFMEMORY = new Win32Error(14);/// <summary>There are no more files.</summary>public static readonly Win32Error ERROR_NO_MORE_FILES = new Win32Error(18);/// <summary>The process cannot access the file because it is being used by another process.</summary>public static readonly Win32Error ERROR_SHARING_VIOLATION = new Win32Error(32);/// <summary>The parameter is incorrect.</summary>public static readonly Win32Error ERROR_INVALID_PARAMETER = new Win32Error(87);/// <summary>Cannot create a file when that file already exists.</summary>public static readonly Win32Error ERROR_ALREADY_EXISTS = new Win32Error(183);//--------------------------------------------------------------------------------------------------// 构造函数,用于初始化 Win32Error 实例public Win32Error(int i){_value = i;}//--------------------------------------------------------------------------------------------------// 获取最后发生的 Win32 错误码[SecurityCritical]public static Win32Error GetLastError(){return new Win32Error(Marshal.GetLastWin32Error());}//--------------------------------------------------------------------------------------------------// 重写 Equals 方法,用于比较两个 Win32Error 实例是否相等public override bool Equals(object obj){try{return ((Win32Error)obj)._value == _value;}catch (InvalidCastException){return false;}}// 重写 GetHashCode 方法,返回 Win32Error 实例的哈希码public override int GetHashCode(){return _value.GetHashCode();}// 重载相等运算符,用于比较两个 Win32Error 实例是否相等public static bool operator ==(Win32Error errLeft, Win32Error errRight){return errLeft._value == errRight._value;}// 重载不相等运算符,用于比较两个 Win32Error 实例是否不相等public static bool operator !=(Win32Error errLeft, Win32Error errRight){return !(errLeft == errRight);}//--------------------------------------------------------------------------------------------------}
}
整段代码的作用是定义了一个只读结构体 Win32Error
,用于封装 Win32 错误码。该结构体包含了常见的 Win32 错误码,提供了方法来获取最后发生的 Win32 错误码,并实现了相等性比较的功能。
5.serialization(序列化)
using System;
using System.Collections;
using System.Diagnostics;namespace Macad.Common.Serialization
{// 实现数组序列化的类public class ArraySerializer : ISerializer{readonly Type _Type;readonly ISerializer _ItemSerializer;// 构造函数public ArraySerializer(Type type){_Type = type;Type itemType = type.GetElementType();_ItemSerializer = Serializer.GetSerializer(itemType);}// 写入方法,将数组对象序列化为 JSONpublic bool Write(Writer writer, object obj, SerializationContext context){var array = obj as Array;if (array == null){writer.WriteNullReference();return true;}writer.BeginList();foreach (var item in array){writer.BeginListValue();if (!_ItemSerializer.Write(writer, item, context))return false;}writer.EndList();return true;}// 读取方法,将 JSON 反序列化为数组对象public object Read(Reader reader, object obj, SerializationContext context){if (reader.TryGetInstance(out var instance)){// Found instance, should only be nullreturn instance;}// Read items in temp listvar readItems = new ArrayList();if (reader.BeginList()){while (reader.BeginListValue()){readItems.Add(_ItemSerializer.Read(reader, null, context));}reader.EndList();}// Create array if needed and fillvar array = obj as Array;if ((array == null) || (array.Length != readItems.Count)){array = Activator.CreateInstance(_Type, readItems.Count) as Array;}Debug.Assert(array != null, "Cannot create array instance");readItems.CopyTo(array);return array;}// 判断是否可以序列化指定类型的数组public static bool CanSerialize(Type type){return type.IsArray && !ReferenceEquals(type.GetElementType(), typeof(object));}}
}
整段代码定义了一个数组序列化器 ArraySerializer
,用于将数组对象序列化为 JSON 格式并将 JSON 反序列化为数组对象。它实现了 ISerializer
接口,包含了写入方法 Write
和读取方法 Read
。同时,它还包含了一个静态方法 CanSerialize
,用于判断指定类型是否可以被序列化为数组。
6.
using System;namespace Macad.Common.Serialization
{// 序列化类型特性,用于标记可序列化的类、结构体、枚举和接口[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Interface)]public sealed class SerializeTypeAttribute : Attribute{}//--------------------------------------------------------------------------------------------------// 序列化成员特性,用于标记可序列化的属性[AttributeUsage(AttributeTargets.Property)]public sealed class SerializeMemberAttribute : Attribute{// 属性的排序键public int SortKey { get; set; }// 用于自定义读取函数的名称public string ReaderFunc { get; set; }// 用于自定义写入函数的名称public string WriterFunc { get; set; }// 构造函数,初始化排序键为 0public SerializeMemberAttribute(){SortKey = 0;}}//--------------------------------------------------------------------------------------------------// 序列化引用 ID 特性,用于标记可序列化的属性作为引用 ID[AttributeUsage(AttributeTargets.Property)]public sealed class SerializeReferenceIdAttribute : Attribute{}//--------------------------------------------------------------------------------------------------}
这段代码定义了一些用于序列化的特性,包括 SerializeTypeAttribute
用于标记可序列化的类型,SerializeMemberAttribute
用于标记可序列化的属性以及相关设置,以及 SerializeReferenceIdAttribute
用于标记可序列化的属性作为引用 ID。
7.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;namespace Macad.Common.Serialization
{// 类序列化器,实现了 ISerializer 接口public sealed class ClassSerializer : ISerializer{// 定义了用于存储类属性信息的结构体struct ClassPropertyInfo{public PropertyInfo PropertyInfo;public SerializeMemberAttribute MemberAttribute;public ISerializer Serializer;public MethodInfo CustomReaderInfo;public MethodInfo CustomWriterInfo;}//--------------------------------------------------------------------------------------------------// 类型信息readonly Type _Type;// 属性字典,存储属性名和属性信息的映射关系readonly Dictionary<string, ClassPropertyInfo> _Properties = new Dictionary<string, ClassPropertyInfo>();// 类别名readonly string _ClassAlias;// 类是否实现了 ISerializable 接口readonly bool _IsISerializable;// 类是否实现了 ISerializeValue 接口readonly bool _IsISerializeValue;// 类是否可以派生readonly bool _CanBeDerived;// 类是否可引用bool _IsReferencable;// 引用 ID 属性ClassPropertyInfo _ReferenceIdProperty;//--------------------------------------------------------------------------------------------------// 构造函数public ClassSerializer(Type type){_Type = type;var typeInfo = type.GetTypeInfo();_ClassAlias = Serializer.ApplyNamespaceAlias(typeInfo.FullName);_IsISerializable = type.GetInterfaces().Contains(typeof(ISerializable));_IsISerializeValue = type.GetInterfaces().Contains(typeof(ISerializeValue));_CanBeDerived = type.IsClass && !type.IsSealed;_IsReferencable = false;if (!_IsISerializeValue){List<ClassPropertyInfo> propInfos = new List<ClassPropertyInfo>();_AddProperties(type, propInfos);var orderedPropInfos = propInfos.OrderBy(propInfo => propInfo.MemberAttribute.SortKey);foreach (var propInfo in orderedPropInfos){_Properties.Add(propInfo.PropertyInfo.Name, propInfo);}}}//--------------------------------------------------------------------------------------------------// 添加属性信息到列表void _AddProperties(Type type, List<ClassPropertyInfo> propInfos){var basetype = type.BaseType;if(basetype != null)_AddProperties(basetype, propInfos);foreach (var propertyInfo in type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly)){if (!propertyInfo.IsDefined(typeof(SerializeMemberAttribute)))continue;var classPropInfo = new ClassPropertyInfo(){PropertyInfo = propertyInfo,Serializer = propertyInfo.PropertyType == _Type ? this : Serializer.GetSerializer(propertyInfo.PropertyType),MemberAttribute = (SerializeMemberAttribute) propertyInfo.GetCustomAttributes(typeof(SerializeMemberAttribute), false).First()};if (propertyInfo.IsDefined(typeof(SerializeReferenceIdAttribute))){_IsReferencable = true;_ReferenceIdProperty = classPropInfo;continue;}if (!classPropInfo.MemberAttribute.ReaderFunc.IsNullOrEmpty()){var method = type.GetMethod(classPropInfo.MemberAttribute.ReaderFunc, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,null, new[] {typeof(Reader), typeof(SerializationContext)}, null);Debug.Assert(method != null && method.ReturnType == typeof(bool), "ReaderFunc 'bool " + classPropInfo.MemberAttribute.ReaderFunc + "(Reader,SerializationContext)' not found in class " + type.Name);classPropInfo.CustomReaderInfo = method;}if (!classPropInfo.MemberAttribute.WriterFunc.IsNullOrEmpty()){var method = type.GetMethod(classPropInfo.MemberAttribute.WriterFunc, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,null, new[] {typeof(Writer), typeof(SerializationContext)}, null);Debug.Assert(method != null && method.ReturnType == typeof(bool), "WriterFunc 'bool " + classPropInfo.MemberAttribute.WriterFunc + "(Writer,SerializationContext)' not found in class " + type.Name);classPropInfo.CustomWriterInfo = method;}propInfos.Add(classPropInfo);}}//--------------------------------------------------------------------------------------------------// 写入操作[SuppressMessage("ReSharper", "PossibleNullReferenceException")]public bool Write(Writer writer, object obj, SerializationContext context){// 写入空引用if (obj == null){writer.WriteNullReference();return true;}// 检查类型是否被派生if (_CanBeDerived && (obj.GetType() != _Type)){var serializer = Serializer.GetSerializer(obj.GetType());return (serializer != null) && serializer.Write(writer, obj, context);}// 写入引用Guid referenceId = new Guid();if (_IsReferencable){referenceId = (Guid)_ReferenceIdProperty.PropertyInfo.GetValue(obj);if (writer.WriteInstanceReference(obj, referenceId)){// 已写入return true;}}// 如果实现了 ISerializeValue 接口,直接使用其写入方法if (_IsISerializeValue){return ((ISerializeValue)obj).Write(writer, context);}// 实例之前未被序列化writer.WriteChar('!');writer.WriteValueString(_ClassAlias);if (_IsISerializable)((ISerializable)obj).OnBeginSerializing(context);writer.BeginMap();// 首先写入引用 IDif (_IsReferencable){writer.BeginMapKey();writer.WriteValueString(_ReferenceIdProperty.PropertyInfo.Name);writer.BeginMapValue();_ReferenceIdProperty.Serializer.Write(writer, referenceId, context);}// 然后写入其他属性foreach (var kvpProperty in _Properties){writer.BeginMapKey();writer.WriteValueString(kvpProperty.Key);writer.BeginMapValue();if (kvpProperty.Value.CustomWriterInfo != null){if ((bool) kvpProperty.Value.CustomWriterInfo.Invoke(obj, new object[] {writer, context}))continue;}kvpProperty.Value.Serializer.Write(writer, kvpProperty.Value.PropertyInfo.GetValue(obj), context);}writer.EndMap();if (_IsISerializable)((ISerializable)obj).OnSerialized(context);return true;}//--------------------------------------------------------------------------------------------------// 读取操作public object Read(Reader reader, object obj, SerializationContext context){if (reader.TryGetInstance(out var instance)){// 已找到实例return instance;}// 如果实现了 ISerializeValue 接口,直接使用其读取方法if (_IsISerializeValue){instance = Activator.CreateInstance(_Type, true);Debug.Assert(instance != null);((ISerializeValue)instance).Read(reader, context);return instance;}// 检查是否为类值if (reader.PeekChar() == '!'){reader.ReadChar(); // 跳过 !var typestr = reader.ReadValueString();Debug.Assert(!string.IsNullOrEmpty(typestr));if (typestr != _ClassAlias){// 类型为另一个 - 派生的 - 类型var serializer = Serializer.GetSerializer(typestr);if (serializer == null){context?.AddErrors($"No serializer for type \"{typestr}\" found as derived class of {_ClassAlias}.");reader.SkipListOrMapValue();return null;}// 转发到另一个类处理程序return serializer.Read(reader, obj, context);}}instance = Activator.CreateInstance(_Type, true);Debug.Assert(instance != null);if (_IsISerializable)((ISerializable)instance).OnBeginDeserializing(context);// 读取属性if (reader.BeginMap()){while (reader.BeginMapKey()){string propertyName = reader.ReadValueString();if (reader.BeginMapValue()){if (_IsReferencable && propertyName == _ReferenceIdProperty.PropertyInfo.Name){var newGuid = (Guid)_ReferenceIdProperty.Serializer.Read(reader, Guid.NewGuid(), context);reader.AddReadInstance(instance, ref newGuid);_ReferenceIdProperty.PropertyInfo.SetValue(instance, newGuid);continue;}if (!_Properties.TryGetValue(propertyName, out var propInfo)){reader.SkipListOrMapValue();continue; // 属性丢失,可能被重构掉了}if (propInfo.CustomReaderInfo != null){if ((bool) propInfo.CustomReaderInfo.Invoke(instance, new object[] {reader, context}))continue;}var oldValue = propInfo.PropertyInfo.GetValue(instance);var newValue = propInfo.Serializer.Read(reader, oldValue, context);if(!ReferenceEquals(oldValue, newValue))propInfo.PropertyInfo.SetValue(instance, newValue);}}reader.EndMap();}if (_IsISerializable)((ISerializable)instance).OnDeserialized(context);return instance;}//--------------------------------------------------------------------------------------------------// 判断是否可序列化public static bool CanSerialize(Type type){return type.IsDefined(typeof(SerializeTypeAttribute));}//--------------------------------------------------------------------------------------------------#region Static Helper Functions// 预期类型public class AnticipatedType{public readonly Type Type;public readonly Guid Guid;public readonly object Instance;public AnticipatedType(Type type, Guid guid, object instance){Type = type;Guid = guid;Instance = instance;}}//--------------------------------------------------------------------------------------------------// 预期类型public static AnticipatedType AnticipateType(Reader reader, SerializationContext context){// 获取缓存Dictionary<Guid, AnticipatedType> cache = null;if (context != null && !context.TryGetInstance(out cache)){cache = new();context.SetInstance(cache);}Type type = null;Guid guid = Guid.Empty;object instance = null;reader.PushState();char c = reader.ReadChar();if (c == '?') // 检查引用{var valuestr = reader.ReadValueString();if (!valuestr.Equals("null")){guid = new Guid(valuestr);if (reader.TryGetInstance(guid, out var foundObj)){instance = foundObj;type = foundObj.GetType();}else if(cache?.TryGetValue(guid, out var cachedValue) ?? false){reader.PopState();return cachedValue;}}}else if (c == '!') // 检查类型定义{var typestr = reader.ReadValueString();Debug.Assert(!string.IsNullOrEmpty(typestr));var serializer = Serializer.GetSerializer(typestr) as ClassSerializer;Debug.Assert(serializer != null);type = serializer._Type;if (serializer._IsReferencable && reader.BeginMap()){while (reader.BeginMapKey()){string propertyName = reader.ReadValueString();if (propertyName == serializer._ReferenceIdProperty.PropertyInfo.Name){if (reader.BeginMapValue()){guid = (Guid) serializer._ReferenceIdProperty.Serializer.Read(reader, Guid.NewGuid(), null);break;}}}}}reader.PopState();AnticipatedType anticipatedType = new(type, guid, instance);if (guid != Guid.Empty && cache != null){// 保存到缓存if (cache.TryGetValue(guid, out var cachedValue)){return cachedValue;}cache.Add(guid, anticipatedType);}return anticipatedType;}//--------------------------------------------------------------------------------------------------#endregion}
}
这段代码是一个类序列化器,用于序列化和反序列化类的实例。它实现了 ISerializer
接口,允许将对象转换为字符串形式以进行持久化或传输,并将字符串重新转换回对象。
主要功能和结构包括:
ClassSerializer
类:负责序列化和反序列化类的实例。ClassPropertyInfo
结构体:存储类属性的相关信息,如属性名称、序列化器等。- 构造函数:根据给定的类型创建
ClassSerializer
的实例,并初始化相关属性。 _AddProperties
方法:用于递归地获取类及其基类的所有属性,并将其添加到属性列表中。Write
方法:将类的实例转换为字符串形式,以便进行持久化或传输。Read
方法:将字符串形式的数据转换回类的实例。CanSerialize
方法:判断给定类型是否可被序列化。AnticipateType
方法:用于预期将要序列化或反序列化的类型,以便进行必要的操作。
整个类序列化器的设计目的是允许在序列化和反序列化过程中进行自定义操作,并支持类的继承和引用。
8.
using System;
using System.Collections;
using System.Diagnostics;
using System.Linq;namespace Macad.Common.Serialization
{/// <summary>/// 字典类型的序列化器,负责将字典类型的实例序列化为字符串形式,并将字符串形式的数据反序列化为字典类型的实例。/// </summary>public class DictionarySerializer : ISerializer{readonly Type _Type;readonly ISerializer _KeySerializer;readonly ISerializer _ValueSerializer;/// <summary>/// 构造函数,根据给定的字典类型初始化字典序列化器。/// </summary>/// <param name="type">字典类型。</param>public DictionarySerializer(Type type){_Type = type;// 获取字典键的类型并获取相应的键序列化器Type keyType = type.GenericTypeArguments[0];_KeySerializer = Serializer.GetSerializer(keyType);// 获取字典值的类型并获取相应的值序列化器Type valueType = type.GenericTypeArguments[1];_ValueSerializer = Serializer.GetSerializer(valueType);}/// <summary>/// 将字典实例序列化为字符串形式。/// </summary>public bool Write(Writer writer, object obj, SerializationContext context){var dict = obj as IDictionary;if (dict == null){writer.WriteNullReference();return true;}// 开始写入字典内容writer.BeginMap();foreach (var key in dict.Keys){writer.BeginMapKey();if (!_KeySerializer.Write(writer, key, context)) // 写入键return false;writer.BeginMapValue();if (!_ValueSerializer.Write(writer, dict[key], context)) // 写入值return false;}writer.EndMap();return true;}/// <summary>/// 将字符串形式的数据反序列化为字典实例。/// </summary>public object Read(Reader reader, object obj, SerializationContext context){if (reader.TryGetInstance(out var instance)){// 已存在实例,应为 nullreturn instance;}// 创建字典实例var dict = (obj ?? Activator.CreateInstance(_Type)) as IDictionary;Debug.Assert(dict != null, "Cannot create dictionary instance");dict.Clear();// 直接读取字典内容并填充字典if (reader.BeginMap()){while (reader.BeginMapKey()){var key = _KeySerializer.Read(reader, null, context); // 读取键if (!reader.BeginMapValue())return false;var value = _ValueSerializer.Read(reader, null, context); // 读取值dict.Add(key, value);}reader.EndMap();}return dict;}/// <summary>/// 判断给定类型是否为字典类型,并且是构造泛型类型。/// </summary>/// <param name="type">待判断类型。</param>/// <returns>如果给定类型是字典类型并且是构造泛型类型,则为 true;否则为 false。</returns>public static bool CanSerialize(Type type){// 判断类型是否为实现了 IDictionary 接口的泛型类型return (type.GetInterfaces().Contains(typeof(IDictionary)) && type.IsConstructedGenericType);}}
}
这段代码实现了字典类型的序列化和反序列化功能,主要包括以下部分:
DictionarySerializer
类:负责序列化和反序列化字典类型的实例。- 构造函数:根据给定的字典类型,获取字典的键和值的类型,并使用相应的序列化器进行序列化。
Write
方法:将字典的内容写入字符串形式,以便进行持久化或传输。Read
方法:将字符串形式的数据转换回字典的实例。CanSerialize
方法:判断给定类型是否为字典类型,且为构造泛型类型。
整个字典序列化器的设计目的是允许在序列化和反序列化过程中使用不同的键和值类型,并支持各种类型的字典对象。
9.
using System;
using System.Linq;namespace Macad.Common.Serialization
{/// <summary>/// 枚举类型的序列化器,负责将枚举类型的实例序列化为字符串形式,并将字符串形式的数据反序列化为枚举类型的实例。/// </summary>public class EnumSerializer : ISerializer{readonly Type _Type;readonly bool _HasFlagsAttribute;readonly Enum[] _Values;/// <summary>/// 构造函数,根据给定的枚举类型初始化枚举序列化器。/// </summary>/// <param name="type">枚举类型。</param>public EnumSerializer(Type type){_Type = type;_HasFlagsAttribute = _Type.GetCustomAttributes(typeof(FlagsAttribute), false).Length > 0;_Values = Enum.GetValues(type).Cast<Enum>().ToArray();}/// <summary>/// 将枚举实例序列化为字符串形式。/// </summary>public bool Write(Writer writer, object obj, SerializationContext context){if (_HasFlagsAttribute){bool isFirst = true;var e = Convert.ToInt32((Enum)obj);var flaggedValues = _Values.Where(m => (e & Convert.ToInt32(m)) != 0);foreach (var flaggedValue in flaggedValues){if (isFirst)isFirst = false;elsewriter.WriteChar('|');writer.WriteValueString(Enum.GetName(_Type, flaggedValue));}if (isFirst){// No flagswriter.WriteChar('0');}}else{writer.WriteValueString(Enum.GetName(_Type, obj));}return true;}/// <summary>/// 将字符串形式的数据反序列化为枚举实例。/// </summary>public object Read(Reader reader, object obj, SerializationContext context){if (_HasFlagsAttribute){var valueString = reader.ReadValueString();if (valueString.IsEmpty() || valueString.Equals("0")){return Enum.ToObject(_Type, 0);}Int32 result = 0;var flagStrings = valueString.Split('|');foreach (var flagString in flagStrings){result |= Convert.ToInt32(Enum.Parse(_Type, flagString, true));}return Enum.ToObject(_Type, result);}else{return Enum.Parse(_Type, reader.ReadValueString(), true);}}}
}
这段代码定义了一个名为 EnumSerializer
的类,用于序列化和反序列化枚举类型的实例。
-
构造函数
EnumSerializer(Type type)
:初始化枚举序列化器,接受一个Type
参数,用于指定要序列化的枚举类型。在构造函数中,它确定了是否带有[Flags]
特性,并获取了枚举类型的所有值。 -
Write 方法
bool Write(Writer writer, object obj, SerializationContext context)
:将枚举实例序列化为字符串形式。如果枚举类型带有[Flags]
特性,则将其按位进行序列化,将包含的标志以管道符号分隔。如果不带[Flags]
特性,则直接将枚举的名称写入。 -
Read 方法
object Read(Reader reader, object obj, SerializationContext context)
:将字符串形式的数据反序列化为枚举实例。如果是带有[Flags]
特性的枚举类型,则根据管道符号分隔的字符串恢复枚举的值,否则直接使用Enum.Parse
将字符串转换为枚举值。
这样,通过 EnumSerializer
类,可以方便地序列化和反序列化枚举类型的实例,支持带有 [Flags]
特性的枚举类型。
10.
namespace Macad.Common.Serialization
{#region Interfaces// 定义了序列化器接口,用于序列化对象public interface ISerializer{bool Write(Writer writer, object obj, SerializationContext context); // 写入方法,将对象序列化为数据流object Read(Reader reader, object obj, SerializationContext context); // 读取方法,将数据流反序列化为对象}// 定义了可序列化值接口,用于自定义对象的序列化和反序列化public interface ISerializeValue{bool Write(Writer writer, SerializationContext context); // 写入方法,将对象的值序列化为数据流bool Read(Reader reader, SerializationContext context); // 读取方法,将数据流反序列化为对象的值}// 定义了可序列化接口,用于自定义对象的序列化和反序列化过程中的回调方法public interface ISerializable{void OnBeginSerializing(SerializationContext context); // 在序列化过程开始时调用的方法void OnSerialized(SerializationContext context); // 在对象序列化完成后调用的方法void OnBeginDeserializing(SerializationContext context); // 在反序列化过程开始时调用的方法void OnDeserialized(SerializationContext context); // 在对象反序列化完成后调用的方法}// 定义了序列化属性接口,用于自定义对象属性的序列化和反序列化过程public interface ISerializeProperty{bool ReadProperty(string propertyName, Reader reader, SerializationContext context); // 读取属性值的方法bool WriteProperty(string propertyName, Writer writer, SerializationContext context); // 写入属性值的方法}// 定义了二进制存档接口,用于管理大型数据的序列化和反序列化public interface IBlobArchive{int WriteBlob(byte[] data); // 写入数据块并返回其引用byte[] ReadBlob(int reference); // 根据引用读取数据块}#endregion
}
这段代码定义了一系列接口,用于实现序列化和反序列化的不同功能和需求,包括对象的序列化、自定义对象的序列化、对象序列化和反序列化的回调、对象属性的序列化和反序列化以及管理大型数据的序列化和反序列化。
11.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;namespace Macad.Common.Serialization
{public sealed class InterfaceSerializer : ISerializer{readonly string _Alias;//--------------------------------------------------------------------------------------------------// 构造函数,初始化接口序列化器public InterfaceSerializer(Type type){var typeInfo = type.GetTypeInfo();// 应用命名空间别名_Alias = Serializer.ApplyNamespaceAlias(typeInfo.FullName);}//--------------------------------------------------------------------------------------------------// 写入方法,将接口对象序列化为数据流public bool Write(Writer writer, object obj, SerializationContext context){if (obj == null){// 写入空引用标记writer.WriteRawString("?null");return true;}// 转到派生类型var serializer = Serializer.GetSerializer(obj.GetType());return serializer != null && serializer.Write(writer, obj, context);}//--------------------------------------------------------------------------------------------------// 读取方法,从数据流反序列化接口对象public object Read(Reader reader, object obj, SerializationContext context){object instance;if (reader.TryGetInstance(out instance)){// 找到实例return instance;}// 必须有一个类值Debug.Assert(reader.PeekChar() == '!');reader.ReadChar(); // 跳过 !var typestr = reader.ReadValueString();Debug.Assert(!string.IsNullOrEmpty(typestr));// 类必须是另一个 - 派生的 - 类型Debug.Assert(typestr != _Alias);var serializer = Serializer.GetSerializer(typestr);Debug.Assert(serializer != null);// 转发到另一个类处理程序return serializer.Read(reader, obj, context);}//--------------------------------------------------------------------------------------------------// 判断是否可以序列化指定类型的接口public static bool CanSerialize(Type type){return type.IsDefined(typeof(SerializeTypeAttribute));}//--------------------------------------------------------------------------------------------------}
}
这段代码实现了接口的序列化和反序列化功能。通过 InterfaceSerializer
类,可以将实现了指定接口的对象序列化为数据流,并在反序列化时还原为相应的对象。
12.
using System;
using System.Collections;
using System.Diagnostics;
using System.Linq;namespace Macad.Common.Serialization
{public class ListSerializer : ISerializer{readonly Type _Type;readonly ISerializer _ItemSerializer;// 构造函数,初始化列表序列化器public ListSerializer(Type type){_Type = type;Type itemType = type.GenericTypeArguments[0];_ItemSerializer = Serializer.GetSerializer(itemType);}// 写入方法,将列表对象序列化为数据流public bool Write(Writer writer, object obj, SerializationContext context){var list = obj as IList;if (list == null){// 写入空引用标记writer.WriteNullReference();return true;}// 开始写入列表writer.BeginList();foreach (var item in list){writer.BeginListValue();if (!_ItemSerializer.Write(writer, item, context))return false;}writer.EndList();return true;}// 读取方法,从数据流反序列化列表对象public object Read(Reader reader, object obj, SerializationContext context){if (reader.TryGetInstance(out var instance)){// 找到实例,应该只是空引用return instance;}// 读取项到临时列表中IList list = (obj ?? Activator.CreateInstance(_Type)) as IList;Debug.Assert(list != null, "Cannot create list instance");list.Clear();if (reader.BeginList()){while (reader.BeginListValue()){list.Add(_ItemSerializer.Read(reader, null, context));}reader.EndList();}return list;}// 判断是否可以序列化指定类型的列表public static bool CanSerialize(Type type){return type.GetInterfaces().Contains(typeof(IList)) && type.IsConstructedGenericType;}}
}
这段代码实现了列表的序列化和反序列化功能。通过 ListSerializer
类,可以将实现了 IList
接口的列表对象序列化为数据流,并在反序列化时还原为相应的列表对象。
13.
using System;
using System.Diagnostics;namespace Macad.Common.Serialization
{public class NullableSerializer : ISerializer{readonly Type _ValueType;readonly ISerializer _Serializer;// 构造函数,初始化可空类型序列化器public NullableSerializer(Type type){Debug.Assert(type.GenericTypeArguments.Length == 1);_ValueType = type.GenericTypeArguments[0];_Serializer = Serializer.GetSerializer(_ValueType);}// 写入方法,将可空类型对象序列化为数据流public bool Write(Writer writer, object obj, SerializationContext context){if (obj == null){// 写入空引用标记writer.WriteRawString("?null");return true;}return _Serializer.Write(writer, obj, context);}// 读取方法,从数据流反序列化可空类型对象public object Read(Reader reader, object obj, SerializationContext context){if (reader.PeekChar() == '?'){// 读取空值标记var nullString = reader.ReadValueString();Debug.Assert(nullString.Equals("?null"));return null;}return _Serializer.Read(reader, obj, context);}}
}
这段代码实现了可空类型的序列化和反序列化功能。通过 NullableSerializer
类,可以将可空类型对象序列化为数据流,并在反序列化时还原为相应的可空类型对象。
14.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;namespace Macad.Common.Serialization
{[Flags]public enum ReadOptions{None = 0,RecreateGuids = 1 << 0}//--------------------------------------------------------------------------------------------------public class Reader{#region Memberspublic struct State{internal int Position;internal bool IsFirstElement;}//--------------------------------------------------------------------------------------------------readonly Dictionary<Guid, object> _ReadInstances = new Dictionary<Guid, object>();readonly Stack<State> _StateStack = new Stack<State>();Dictionary<Guid, Guid> _RecreatedGuids;readonly string _Source;readonly int _Length;readonly ReadOptions _Options;State _State;static readonly char[] _ValueStringLimiter = {' ', '\r', '\n', '\0', ':', ',', '{', '}', '[', ']'};static readonly char[] _WhiteSpaceChars = {' ', '\r', '\n', '\t'};//--------------------------------------------------------------------------------------------------public delegate void RecreatedGuidHandler(Reader reader, Guid oldGuid, Guid newGuid);public event RecreatedGuidHandler RecreatedGuid;//--------------------------------------------------------------------------------------------------#endregion#region Reader functions// 获取是否还有剩余内容public bool AnyLeft{get { return _State.Position < _Length; }}//--------------------------------------------------------------------------------------------------// 构造函数,初始化 Readerpublic Reader(in string source, ReadOptions options = ReadOptions.None){_Source = source;_Length = source.Length;_Options = options;if(options.HasFlag(ReadOptions.RecreateGuids))_RecreatedGuids = new Dictionary<Guid, Guid>();}//--------------------------------------------------------------------------------------------------// 预览当前字符public char PeekChar(){return _State.Position < _Length ? _Source[_State.Position] : '\0';}//--------------------------------------------------------------------------------------------------// 读取一个字符public char ReadChar(){if (_State.Position >= _Length)return '\0';var c = _Source[_State.Position];_State.Position++;return c;}//--------------------------------------------------------------------------------------------------// 读取一个带引号的字符串public string ReadQuotedString(){if (PeekChar() != '"')return null;_State.Position++; // Skip "var sb = new StringBuilder();var c = ReadChar();while ((c != '"') && (c != '\0')){if (c == '\\'){c = ReadChar(); // should only be \ or "}sb.Append(c);c = ReadChar();}EatWhiteSpaces();return sb.ToString();}//--------------------------------------------------------------------------------------------------// 读取一个值类型字符串public string ReadValueString(){if (_ValueStringLimiter.Contains(PeekChar()))return null;var sb = new StringBuilder();var c = PeekChar();while (!_ValueStringLimiter.Contains(c)){if (c == '\\'){_State.Position++;c = ReadChar();}else{_State.Position++;}sb.Append(c);c = PeekChar();}EatWhiteSpaces();return (sb.Length > 0) ? sb.ToString() : null;}//--------------------------------------------------------------------------------------------------// 读取指定类型的对象public T ReadType<T>(object obj, SerializationContext context){var serializer = Serializer.GetSerializer(typeof(T));Debug.Assert(serializer != null);T result = (T)serializer.Read(this, obj, context);EatWhiteSpaces();return result;}//--------------------------------------------------------------------------------------------------// 忽略空格字符public void EatWhiteSpaces(){var c = PeekChar();while (_WhiteSpaceChars.Contains(c)){_State.Position++;c = PeekChar();}}//--------------------------------------------------------------------------------------------------// 将当前状态压入栈public void PushState(){_StateStack.Push(_State);}//--------------------------------------------------------------------------------------------------// 弹出栈顶状态public void PopState(){_State = _StateStack.Pop();}//--------------------------------------------------------------------------------------------------// 获取当前状态public State GetState(){return _State;}//--------------------------------------------------------------------------------------------------// 重置状态public void ResetState(State state = default){_State = state;}//--------------------------------------------------------------------------------------------------#endregion#region Map// 开始读取映射类型的内容public bool BeginMap(){if (PeekChar() != '{')return false;_State.Position++; // Skip {_State.IsFirstElement = true;EatWhiteSpaces();return true;}//--------------------------------------------------------------------------------------------------// 结束读取映射类型的内容public bool EndMap(){if (PeekChar() != '}')return false;_State.Position++; // Skip {_State.IsFirstElement = false;EatWhiteSpaces();return true;}//--------------------------------------------------------------------------------------------------// 开始读取映射类型的键public bool BeginMapKey(){if (!_State.IsFirstElement){if (PeekChar() != ',')return false;_State.Position++; // Skip ,}else{_State.IsFirstElement = false;}EatWhiteSpaces();return AnyLeft && (PeekChar() != '}');}//--------------------------------------------------------------------------------------------------// 开始读取映射类型的值public bool BeginMapValue(){if (PeekChar() != ':')return false;_State.Position++; // Skip :EatWhiteSpaces();return AnyLeft;}//--------------------------------------------------------------------------------------------------// 跳过列表或映射类型的值public void SkipListOrMapValue(){int openMaps = 0;int openLists = 0;while (AnyLeft){char c = PeekChar();if (c == '"'){ReadQuotedString();}else{switch (c){case '{':openMaps++;break;case '}':if (openMaps == 0){return;}openMaps--;break;case '[':openLists++;break;case ']':if (openLists == 0){return;}openLists--;break;case ',':if ((openMaps == 0) && (openLists == 0)){return;}break;}_State.Position++;}}}//--------------------------------------------------------------------------------------------------#endregion#region List// 开始读取列表类型的内容public bool BeginList(){if (PeekChar() != '[')return false;_State.Position++; // Skip {_State.IsFirstElement = true;EatWhiteSpaces();return true;}//--------------------------------------------------------------------------------------------------// 结束读取列表类型的内容public bool EndList(){if (PeekChar() != ']')return false;_State.Position++; // Skip {_State.IsFirstElement = false;EatWhiteSpaces();return true;}//--------------------------------------------------------------------------------------------------// 开始读取列表类型的值public bool BeginListValue(){if (!_State.IsFirstElement){if (PeekChar() != ',')return false;_State.Position++; // Skip ,}else{_State.IsFirstElement = false;}EatWhiteSpaces();return AnyLeft && (PeekChar() != ']');}//--------------------------------------------------------------------------------------------------#endregion#region Read Instances// 添加读取到的实例public void AddReadInstance(object instance, ref Guid guid){_ReadInstances.Add(guid, instance);if (_Options.Has(ReadOptions.RecreateGuids)){var newGuid = Guid.NewGuid();_RecreatedGuids.Add(guid, newGuid);RecreatedGuid?.Invoke(this, guid, newGuid);guid = newGuid;}}//--------------------------------------------------------------------------------------------------// 尝试从已读取实例中获取对象public bool TryGetInstance(out object instance){instance = null;// Check for referenceif (PeekChar() != '?'){return false;}ReadChar(); // Skip !var valuestr = ReadValueString();if (valuestr.Equals("null")){return true;}var guid = new Guid(valuestr);EatWhiteSpaces();if (_ReadInstances.TryGetValue(guid, out var foundObj)){instance = foundObj;}return true;}//--------------------------------------------------------------------------------------------------// 尝试从已读取实例中获取对象public bool TryGetInstance(in Guid guid, out object instance){return _ReadInstances.TryGetValue(guid, out instance);}//--------------------------------------------------------------------------------------------------#endregion}}
这段代码定义了一个 Reader
类,用于从字符串中读取数据并进行解析。它包含了一系列方法用于读取字符、字符串、类型等信息,并支持映射类型和列表类型的解析。同时,它还具有管理已读取实例的功能,可以通过 GUID 查找已读取的对象。
15.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;namespace Macad.Common.Serialization
{#region Enums// 序列化作用域public enum SerializationScope{Storage, // 存储UndoRedo, // 撤销重做CopyPaste, // 复制粘贴}//--------------------------------------------------------------------------------------------------// 序列化结果public enum SerializationResult{None, // 无VersionMismatch // 版本不匹配}//--------------------------------------------------------------------------------------------------#endregion// 序列化上下文public class SerializationContext{#region Propertiespublic IBlobArchive BlobArchive { get; set; } // 二进制存档//--------------------------------------------------------------------------------------------------public SerializationScope Scope { get; } // 作用域//--------------------------------------------------------------------------------------------------public SerializationResult Result { get; set; } // 结果//--------------------------------------------------------------------------------------------------public Version Version { get; set; } // 版本//--------------------------------------------------------------------------------------------------#endregion#region Members / n'torsreadonly Dictionary<object, object> _Parameters = new Dictionary<object, object>(); // 参数readonly List<string> _Errors = new List<string>(); // 错误消息列表//--------------------------------------------------------------------------------------------------// 构造函数public SerializationContext(SerializationScope scope = SerializationScope.Storage){Scope = scope;Result = SerializationResult.None;}//--------------------------------------------------------------------------------------------------#endregion#region Messages// 添加错误消息public void AddErrors(string message){_Errors.Add(message);}//--------------------------------------------------------------------------------------------------// 是否有错误public bool HasErrors{get { return _Errors.Count > 0; }}//--------------------------------------------------------------------------------------------------// 获取错误消息列表public IEnumerable<string> Errors{get { return _Errors; }}//--------------------------------------------------------------------------------------------------#endregion#region Parameter// 获取参数值public T GetParameter<T>(string key){if (_Parameters.TryGetValue(key, out var value))return value is T ? (T) value : default(T);return default(T);}//--------------------------------------------------------------------------------------------------// 尝试获取参数值public bool TryGetParameter<T>(string key, out T value){if (_Parameters.TryGetValue(key, out var result)){value = (T) result;return true;}value = default(T);return false;}//--------------------------------------------------------------------------------------------------// 设置参数值public void SetParameter(string key, object parameter){_Parameters[key] = parameter;}//--------------------------------------------------------------------------------------------------// 移除参数public void RemoveParameter(string key){if(_Parameters.ContainsKey(key))_Parameters.Remove(key);}//--------------------------------------------------------------------------------------------------#endregion#region Instances// 获取实例public T GetInstance<T>(){if (_Parameters.TryGetValue(typeof(T), out var result))return (T)result;return default(T);}//--------------------------------------------------------------------------------------------------// 尝试获取实例public bool TryGetInstance<T>(out T instance){if (_Parameters.TryGetValue(typeof(T), out var result)){instance = (T) result;return true;}instance = default(T);return false;}//--------------------------------------------------------------------------------------------------// 设置实例public void SetInstance(object instance){_Parameters[instance.GetType()] = instance;}//--------------------------------------------------------------------------------------------------// 设置实例public void SetInstance<T>(object instance){_Parameters[typeof(T)] = instance;}//--------------------------------------------------------------------------------------------------// 移除实例public void RemoveInstance<T>(){if(_Parameters.ContainsKey(typeof(T)))_Parameters.Remove(typeof(T));}//--------------------------------------------------------------------------------------------------// 获取实例列表public List<T> GetInstanceList<T>(){if (_Parameters.TryGetValue(typeof(List<T>), out var result))return (List<T>)result;var list = new List<T>();_Parameters.Add(typeof(List<T>), list);return list;}//--------------------------------------------------------------------------------------------------// 获取实例堆栈public Stack<T> GetInstanceStack<T>(){if (_Parameters.TryGetValue(typeof(Stack<T>), out var result))return (Stack<T>)result;var stack = new Stack<T>();_Parameters.Add(typeof(Stack<T>), stack);return stack;}//--------------------------------------------------------------------------------------------------#endregion}}
这段代码定义了一个 SerializationContext
类,用于存储序列化过程中的上下文信息,包括存档、作用域、结果、版本等属性。它还包含了管理参数和实例的功能,可以用于在序列化过程中传递和存储额外的信息。
16.
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;namespace Macad.Common.Serialization
{public static class Serializer{#region Serializer Repository// 存储序列化器的字典,按类型存储static readonly Dictionary<Type, ISerializer> _SerializersByType = new Dictionary<Type, ISerializer>();// 存储序列化器的字典,按别名存储static readonly Dictionary<string, ISerializer> _SerializersByAlias = new Dictionary<string, ISerializer>();// 获取类型对应的序列化器public static ISerializer GetSerializer(Type type){ISerializer serializer = null;if (!_SerializersByType.TryGetValue(type, out serializer)){serializer = _CreateSerializer(type);Debug.Assert(serializer != null);}return serializer;}// 根据别名获取序列化器internal static ISerializer GetSerializer(string alias){ISerializer serializer = null;if (_SerializersByAlias.TryGetValue(alias, out serializer)){return serializer;}// 解析别名var typeFullName = ResolveNamespaceAlias(alias);Type type = null;foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()){type = assembly.GetType(typeFullName);if (type != null)break;}if (type == null){Console.WriteLine("Type not found for type " + typeFullName);return null;}if (_SerializersByType.TryGetValue(type, out serializer)){return serializer;}serializer = _CreateSerializer(type);if (serializer == null){Console.WriteLine("Serializer not found for type " + typeFullName);return null;}return serializer;}// 创建序列化器static ISerializer _CreateSerializer(Type type){ISerializer serializer = null;if (type.IsClass){if (DictionarySerializer.CanSerialize(type)){serializer = new DictionarySerializer(type);}else if (ListSerializer.CanSerialize(type)){serializer = new ListSerializer(type);}else if (ArraySerializer.CanSerialize(type)){serializer = new ArraySerializer(type);}else if (ClassSerializer.CanSerialize(type)){serializer = new ClassSerializer(type);}}else if (type.IsEnum){serializer = new EnumSerializer(type);}else if (type.IsInterface){serializer = new InterfaceSerializer(type);}else if (type.IsValueType && !type.IsPrimitive){// Nullableif (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)){serializer = new NullableSerializer(type);}// Structif (ClassSerializer.CanSerialize(type)){serializer = new ClassSerializer(type);}}if (serializer == null){throw new Exception("No serializer for type " + type.FullName);}AddSerializer(type, serializer);return serializer;}// 添加序列化器public static void AddSerializer(Type type, ISerializer serializer){_SerializersByType.Add(type, serializer);var alias = ApplyNamespaceAlias(type.FullName);if (alias != type.FullName){_SerializersByAlias.Add(alias, serializer);}}#endregion#region Namespace Aliases// 命名空间别名字典static readonly Dictionary<string, string> _namespaceAliases = new Dictionary<string, string>();// 注册命名空间别名public static void RegisterNamespaceAlias(string alias, string ns){_namespaceAliases[alias] = ns;}// 应用命名空间别名public static string ApplyNamespaceAlias(string fullName){int length = 0;string alias = fullName;foreach (var kvp in _namespaceAliases){if (fullName.StartsWith(kvp.Value) && (length < kvp.Value.Length)){alias = kvp.Key;length = kvp.Value.Length;}}if (length == 0){return fullName;}return alias + "." + fullName.Remove(0, length + 1);}// 解析命名空间别名public static string ResolveNamespaceAlias(string alias){var index = alias.IndexOf('.');if (index > 0){string aliasNS = alias.Substring(0, index);string ns;if (_namespaceAliases.TryGetValue(aliasNS, out ns)){return ns + alias.Substring(index);}}return alias;}// 写入命名空间别名static void _WriteNamespaceAliases(Writer w){w.WriteValueString("Namespaces");w.BeginMap();foreach (var kvp in _namespaceAliases){w.BeginMapKey();w.WriteValueString(kvp.Key);w.BeginMapValue();w.WriteValueString(kvp.Value);}w.EndMap();}// 初始化命名空间别名static void _InitNamespaceAliases(){RegisterNamespaceAlias("Common", "Macad.Common");}#endregion#region Formatting// 格式化序列化文本public static string Format(string serializedText){if (string.IsNullOrEmpty(serializedText)) return null;var tabCount = 0;var sb = new StringBuilder();var firstKeySeparator = true;var inString = false;var inInlineList = false;var inType = false;for (var i = 0; i < serializedText.Length; i++){var current = serializedText[i];var previous = i - 1 >= 0 ? serializedText[i - 1] : 0;var next = i < serializedText.Length - 1 ? serializedText[i + 1] : 0;if (current == '"'){sb.Append(current);inString = !inString;continue;}if (inString){sb.Append(current);continue;}if (current == '{' || current == '['){if (inType){inType = false;_AppendTabLine(sb, tabCount);}if (previous == ':'){if (next == '}' || next == ']'){sb.Append(current);sb.Append(serializedText[++i]); //eat nextcontinue;}if (current == '['){int nextMapChar = serializedText.IndexOf('{', i);if ((nextMapChar == -1)||(serializedText.IndexOf(']', i) < nextMapChar)){inInlineList = true;sb.Append(current);firstKeySeparator = true;continue;}}_AppendTabLine(sb, tabCount);}sb.Append(current);_AppendTabLine(sb, ++tabCount);firstKeySeparator = true;continue;}if (current == '}' || current == ']'){if (!inInlineList){_AppendTabLine(sb, --tabCount);}sb.Append(current);firstKeySeparator = true;inInlineList = false;continue;}if (current == ',' && !inString){sb.Append(current);if (inInlineList){sb.Append(" ");}else{_AppendTabLine(sb, tabCount);}firstKeySeparator = true;continue;}sb.Append(current);if (current == ':' && firstKeySeparator && !inType){sb.Append(" ");firstKeySeparator = false;}if (current == '!'){inType = true;}}return sb.ToString();}// 添加制表符和换行符static void _AppendTabLine(StringBuilder sb, int tabCount){sb.AppendLine();if (tabCount > 0){sb.Append(new string('\t', tabCount));}}#endregion#region Serialize// 初始化序列化器static Serializer(){_InitNamespaceAliases();StandardSerializers.Init();Win32ApiSerializer.Init();}// 序列化对象为字符串public static string Serialize(object rootObject, SerializationContext context=null){var writer = new Writer();if(Serialize(writer, rootObject, context))return writer.ToString();return null;}// 序列化对象到 Writerpublic static bool Serialize(Writer writer, object rootObject, SerializationContext context=null){if (rootObject == null){writer.WriteRawString("?null");return true;}var serializer = GetSerializer(rootObject.GetType());Debug.Assert(serializer != null);return serializer.Write(writer, rootObject, context ?? new SerializationContext()) && writer.IsValid();}// 反序列化字符串为对象public static T Deserialize<T>(string source, SerializationContext context=null){var readerFlags = context?.GetInstance<ReadOptions>() ?? ReadOptions.None;var reader = new Reader(source, readerFlags);return Deserialize<T>(reader, context);}// 从 Reader 中反序列化对象public static T Deserialize<T>(Reader reader, SerializationContext context=null){var serializer = GetSerializer(typeof(T));Debug.Assert(serializer != null);var obj = serializer.Read(reader, null, context ?? new SerializationContext());return obj is T ? (T) obj : default;}#endregion}}
这是一个静态类 Serializer
,提供了序列化和反序列化对象的功能。它包含了管理序列化器的功能,可以根据对象的类型获取相应的序列化器。另外,它还提供了命名空间别名的注册和解析功能,以及序列化文本的格式化功能。
17.
using System;
using System.Diagnostics;
using System.Globalization;namespace Macad.Common.Serialization
{public class StandardSerializers{// 字符串序列化器class StandardSerializerString : ISerializer{public bool Write(Writer writer, object obj, SerializationContext context){var stringValue = obj as string;if (obj == null){writer.WriteValueString("?null"); // 写入空值标记}else{writer.WriteQuotedString(stringValue); // 写入带引号的字符串值}return true;}public object Read(Reader reader, object obj, SerializationContext context){if (reader.PeekChar() == '?'){reader.ReadChar();var valueString = reader.ReadValueString();Debug.Assert(valueString.Equals("null")); // 断言确认值为 nullreturn null;}else{return reader.ReadQuotedString(); // 读取带引号的字符串}}}//--------------------------------------------------------------------------------------------------// 字符序列化器class StandardSerializerChar : ISerializer{public bool Write(Writer writer, object obj, SerializationContext context){writer.WriteQuotedString(obj.ToString()); // 写入带引号的字符return true;}public object Read(Reader reader, object obj, SerializationContext context){return reader.ReadQuotedString()[0]; // 读取带引号的字符,返回第一个字符}}//--------------------------------------------------------------------------------------------------// 字节序列化器class StandardSerializerByte : ISerializer{public bool Write(Writer writer, object obj, SerializationContext context){writer.WriteValueString(obj.ToString()); // 写入字节值return true;}public object Read(Reader reader, object obj, SerializationContext context){return byte.Parse(reader.ReadValueString(), CultureInfo.InvariantCulture); // 读取字节值}}// 其他基本类型的序列化器(Int16、UInt16、Int32、UInt32、Int64、UInt64、float、double、bool、Guid、byte[]、DateTime),类似上述类的实现//--------------------------------------------------------------------------------------------------static bool _IsInitialized = false;//--------------------------------------------------------------------------------------------------// 初始化标准序列化器public static void Init(){Debug.Assert(!_IsInitialized);// 向 Serializer 类中添加标准类型的序列化器Serializer.AddSerializer(typeof(string), new StandardSerializerString());Serializer.AddSerializer(typeof(char), new StandardSerializerChar());Serializer.AddSerializer(typeof(byte), new StandardSerializerByte());// 添加其他基本类型的序列化器_IsInitialized = true; // 标记已经初始化过}//--------------------------------------------------------------------------------------------------}
}
这段代码定义了一系列标准的序列化器,用于将常见的基本类型序列化为字符串形式以便进行持久化存储或传输。这些序列化器包括字符串、字符、字节、整数、浮点数、布尔值、Guid、字节数组和日期时间。在初始化过程中,这些序列化器被注册到了 Serializer 类中,以供后续使用。
18.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;namespace Macad.Common.Serialization
{public class Writer{// 已写入实例的字典,用于跟踪已经写入的对象以避免重复写入readonly Dictionary<Guid, object> _WrittenInstances = new Dictionary<Guid, object>();// 用于构建序列化字符串的 StringBuilderreadonly StringBuilder _Sb = new StringBuilder();// 跟踪当前打开的块数,保证序列化的完整性int _BlocksOpen = 0;// 跟踪当前已写入的映射键值对数量,用于验证映射的完整性int _MapsKeys = 0;// 跟踪当前已写入的映射值数量,用于验证映射的完整性int _MapsValues = 0;// 标记当前是否是第一个元素,用于确定是否需要添加逗号分隔符bool _IsFirstElement = false;//--------------------------------------------------------------------------------------------------// 构造函数public Writer(){}//--------------------------------------------------------------------------------------------------// 验证序列化结果的完整性public bool IsValid(){return (_BlocksOpen == 0) && (_MapsKeys == _MapsValues);}//--------------------------------------------------------------------------------------------------// 将序列化的结果转换为字符串public override string ToString(){return _Sb.ToString();}//--------------------------------------------------------------------------------------------------#region Write Functions// 写入字符public void WriteChar(in char value){_Sb.Append(value);}// 直接写入字符串public void WriteRawString(in string value){_Sb.Append(value);}// 写入带转义的字符串public void WriteValueString(in string value){foreach (var c in value){switch (c){case '"':_Sb.Append(@"\""");break;case '\'':_Sb.Append(@"\'");break;case '\\':_Sb.Append(@"\\");break;case '{':_Sb.Append(@"\{");break;case '}':_Sb.Append(@"\}");break;case ':':_Sb.Append(@"\:");break;case ',':_Sb.Append(@"\,");break;default:_Sb.Append(c);break;}}}// 写入带引号的字符串public void WriteQuotedString(in string value){_Sb.Append(@"""");foreach (var c in value){switch (c){case '"':_Sb.Append(@"\""");break;case '\\':_Sb.Append(@"\\");break;default:_Sb.Append(c);break;}}_Sb.Append(@"""");}// 写入空引用标记public void WriteNullReference(){WriteRawString("?null");}// 写入实例引用public bool WriteInstanceReference(object instance, in Guid guid){if (instance == null){WriteNullReference();return true;}if (guid == Guid.Empty){return false;}if (_WrittenInstances.ContainsKey(guid)){WriteChar('?');WriteValueString(guid.ToString("N"));return true;}_WrittenInstances.Add(guid, instance);return false;}// 写入对象类型public bool WriteType(object instance, SerializationContext context){var serializer = Serializer.GetSerializer(instance.GetType());Debug.Assert(serializer != null);return serializer.Write(this, instance, context);}#endregion#region Map// 开始写入映射public void BeginMap(){_Sb.Append('{');_BlocksOpen++;_IsFirstElement = true;}// 开始写入映射键public void BeginMapKey(){if (!_IsFirstElement){_Sb.Append(',');}_IsFirstElement = false;_MapsKeys++;}// 开始写入映射值public void BeginMapValue(){_Sb.Append(':');_MapsValues++;}// 结束写入映射public void EndMap(){_Sb.Append('}');_BlocksOpen--;_IsFirstElement = false;}#endregion#region List// 开始写入列表public void BeginList(){_Sb.Append('[');_BlocksOpen++;_IsFirstElement = true;}// 开始写入列表元素public void BeginListValue(){if (!_IsFirstElement){_Sb.Append(',');}_IsFirstElement = false;}// 结束写入列表public void EndList(){_Sb.Append(']');_BlocksOpen--;_IsFirstElement = false;}#endregion}
}
这段代码定义了一个 Writer
类,用于将数据序列化为字符串形式。它提供了一系列方法来写入不同类型的数据,包括字符、字符串、空引用、实例引用、对象类型、映射(字典)和列表。在写入过程中,它会跟踪已经写入的实例,避免重复写入;同时,还会记录当前打开的块数以及已经写入的映射键值对数量,以验证序列化结果的完整性。
19.types
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using Macad.Common.Serialization;namespace Macad.Common
{// 在序列化时标记为需要被序列化的类型[SerializeType]public class BaseObject : INotifyPropertyChanged, ISerializable{// 标记属性,用于指示是否抑制属性更改事件public bool SuppressPropertyChangedEvent { get; protected set; }// 属性更改事件public event PropertyChangedEventHandler PropertyChanged;// 引发属性更改事件的方法protected virtual void RaisePropertyChanged([CallerMemberName] String propertyName = ""){// 如果事件有订阅者并且未抑制属性更改事件,则引发事件if ((PropertyChanged != null) && (!SuppressPropertyChangedEvent)){PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));}}// 标记对象是否正在反序列化过程中protected bool IsDeserializing = false;// 在撤销操作之前调用的虚拟方法public virtual void OnBeforeUndo(){ }// 在撤销操作之后调用的虚拟方法public virtual void OnAfterUndo(){ }#region ISerializable// 在开始序列化过程时调用的虚拟方法public virtual void OnBeginSerializing(SerializationContext context){}// 在序列化过程完成时调用的虚拟方法public virtual void OnSerialized(SerializationContext context){}// 在开始反序列化过程时调用的虚拟方法public virtual void OnBeginDeserializing(SerializationContext context){IsDeserializing = true; // 标记对象正在反序列化中}// 在反序列化过程完成时调用的虚拟方法public virtual void OnDeserialized(SerializationContext context){IsDeserializing = false; // 标记对象反序列化已完成}// 获取对象的引用ID,用于对象引用的序列化public virtual Guid? GetReferenceId(){return null;}#endregion}
}
这段代码定义了一个名为 BaseObject
的基类,它实现了 INotifyPropertyChanged
接口用于属性更改通知,并且标记了 [SerializeType]
以指示需要被序列化。同时,它还实现了 ISerializable
接口,提供了一系列虚拟方法,包括在序列化和反序列化过程中的各个阶段的回调方法,以及用于获取对象引用ID的方法。
20.
using System;
using System.Diagnostics;
using System.Globalization;
using System.Text;
using Macad.Common.Serialization;namespace Macad.Common
{// 在序列化时标记为需要被序列化的结构体类型[SerializeType]public struct Color : ISerializeValue, IEquatable<Color>{// 预定义的黑色和白色颜色public static readonly Color Black = new Color(0, 0, 0);public static readonly Color White = new Color(1, 1, 1);//--------------------------------------------------------------------------------------------------// 颜色的红、绿、蓝分量属性public float Red{get { return _Red; }}public float Green{get { return _Green; }}public float Blue{get { return _Blue; }}//--------------------------------------------------------------------------------------------------// 红、绿、蓝分量值float _Red;float _Green;float _Blue;//--------------------------------------------------------------------------------------------------// 构造函数,根据给定的红、绿、蓝分量创建颜色public Color(float r, float g, float b){_Red = r;_Green = g;_Blue = b;}//--------------------------------------------------------------------------------------------------// 根据字符串创建颜色,字符串格式为 #RRGGBB 或 #AARRGGBBpublic Color(string s){if (s.StartsWith("#") && s.Length >= 7){int i = 1;if (s.Length == 9){// 忽略 Alpha 分量i += 2;}_Red = int.Parse(s.Substring(i, 2), NumberStyles.HexNumber) / 255.0f;i += 2;_Green = int.Parse(s.Substring(i, 2), NumberStyles.HexNumber) / 255.0f;i += 2;_Blue = int.Parse(s.Substring(i, 2), NumberStyles.HexNumber) / 255.0f;return;}Debug.Assert(true, "Color can not be decoded.");_Red = _Green = _Blue = 0.0f;}//--------------------------------------------------------------------------------------------------#region Serialization// 实现 ISerializeValue 接口的写方法public bool Write(Writer writer, SerializationContext context){float[] values = { _Red, _Green, _Blue };return writer.WriteType(values, context);}//--------------------------------------------------------------------------------------------------// 实现 ISerializeValue 接口的读方法public bool Read(Reader reader, SerializationContext context){var values = reader.ReadType<float[]>(null, context);if ((values != null) && (values.Length == 3)){_Red = values[0];_Green = values[1];_Blue = values[2];return true;}return false;}//--------------------------------------------------------------------------------------------------#endregion// 重写 Equals 方法public override bool Equals(object obj){if (ReferenceEquals(null, obj)) return false;return obj is Color && ((Color)obj == this);}//--------------------------------------------------------------------------------------------------// 重写 GetHashCode 方法public override int GetHashCode(){unchecked{var hashCode = (int)(_Red * 255.0f) | ((int)(_Green * 255.0f) << 8)| ((int)(_Blue * 255.0f) << 16);return hashCode;}}//--------------------------------------------------------------------------------------------------// 实现 IEquatable<Color> 接口的 Equals 方法public bool Equals(Color other){return other == this;}//--------------------------------------------------------------------------------------------------// 实现相等运算符的重载public static bool operator ==(Color color1, Color color2){return (color1._Red == color2._Red) && (color1._Green == color2._Green) && (color1._Blue == color2._Blue);}//--------------------------------------------------------------------------------------------------// 实现不等运算符的重载public static bool operator !=(Color color1, Color color2){return !(color1 == color2);}//--------------------------------------------------------------------------------------------------// 重写 ToString 方法,返回颜色的字符串表示public override string ToString(){StringBuilder sb = new StringBuilder();sb.AppendFormat(CultureInfo.InvariantCulture, "[{0},{1},{2}]", _Red, Green, _Blue);return sb.ToString();}//--------------------------------------------------------------------------------------------------// 返回缩放后的颜色public Color Scaled(float scale){return new Color(Red*scale, Green*scale, Blue*scale);}//--------------------------------------------------------------------------------------------------// 返回两个颜色之间的插值颜色public Color Lerp(Color other, float f){return new Color(Red.Lerp(other.Red, f), Green.Lerp(other.Green, f), Blue.Lerp(other.Blue, f));}}
}
这段代码定义了一个名为 Color
的结构体,表示颜色。它实现了 ISerializeValue
接口,用于序列化和反序列化颜色对象。同时,它还实现了 IEquatable<Color>
接口,重写了 Equals
和 GetHashCode
方法,以及相等和不等运算符,用于颜色对象的比较。结构体 Color
还提供了一些操作颜色的方法,如缩放和颜色插值。
21.
using Macad.Common.Serialization;namespace Macad.Common
{// 标记为需要被序列化的类类型[SerializeType]public class DocumentHeader{// 序列化成员,表示文档内容类型[SerializeMember]public string ContentType { get; set; }// 序列化成员,表示文档主版本号[SerializeMember]public int MajorVersion { get; set; }// 序列化成员,表示文档次版本号[SerializeMember]public int MinorVersion { get; set; }}
}
这段代码定义了一个名为 DocumentHeader
的类,用于表示文档的头部信息。该类被标记为需要被序列化,其中包含了三个属性:ContentType
表示文档的内容类型,MajorVersion
表示文档的主版本号,MinorVersion
表示文档的次版本号。这些属性都被标记为需要被序列化。
这篇关于macad.common解析interop、serialization、types的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!