c# – 将XML数据转换为tsql记录以获取任何XML响应

我不知道它是否已经得到了回答,但是我运气不好或者因为我的狩猎技术无法在stackoverflow中找到它.请忽略我的垃圾邮件

我们需要编写一个适用于任何提供XML输出的API的API解析器.

我们不会事先知道XML结构.

该解决方案应转换XML文件并将其保存在通用tsql表中,并将XML元素/属性名称作为第一行.

所以基本上它是任何API的XML反序列化器.

我们不能将任何第三方dll用于我们的C#类.

我不知道C#所以不知道它是否可能.但我已经能够使用OPENXML在tsql中编写一个genric XML->行转换器. tsql解决方案的问题是我们无法将巨大的XML文件成功导入数据库.

我可以提供所需的任何细节.请在评论/答案中告诉我.

我不希望任何人为我编写代码,任何合适的指针就足够了

资源:
JSON

[
{
        "id" : 21953,"mainReqIdentity" : "xxxx","itemName" : "xxxx","kanbanPhase" : "xxxx","kanbanStatus" : "xxxx","backlogItemType" : "xxxx","identityDomain" : "xxxx","fromDatetime" : "2016-08-05 17:52:34","teams" : [],"releases" : [{
                "id" : 1229,"release_name" : "xxxx","release_connection_type" : "xxxx"
            }
        ],"fpReleases" : [],"sources" : [{
                "sourceName" : "xxxx","sourceRecordUrl" : "xxxx","sourceRecordIdentity" : "xxxx"
            }
        ],"productNumbers" : [],"tags" : [],"productComponents" : [],"ranPlatforms" : [],"subReleases" : [],"requirementAreaId" : xxxx,"requirementArea" : "xxxx","toBeHandledAtxxxx" : "xxxx"
    },{
        "id" : 22014,"releases" : [{
                "id" : xxxx,"f0Date" : "2015-10-01","f1Date" : "2015-10-01","f2Date" : "2016-02-01","f4Date" : "2016-03-31","fgDate" : "2016-04-29","toBeHandledAtxxxx" : "xxxx"
    }
    ]

XML:2个样本

样品1

<root type="array">
    <id type="number">21286</id>
    <mainReqIdentity type="string">xxxxxx</mainReqIdentity>
    <itemName type="string">xxxxxx</itemName>
    <kanbanPhase type="string">xxxxxx</kanbanPhase>
    <kanbanStatus type="string">xxxxxx</kanbanStatus>
    <kanbanNote type="string">xxxxxx</kanbanNote>
    <backlogItemType type="string">xxxxxx</backlogItemType>
    <identityDomain type="string">xxxxxx</identityDomain>
    <fromDatetime type="string">2016-08-23 17:01:52</fromDatetime>
    <teams type="array">
      <item type="object">
        <team_name type="string">xxxxxx</team_name>
        <preliminary type="boolean">xxxxxx</preliminary>
      </item>
    </teams>
    <releases type="array">
      <item type="object">
        <id type="number">xxxxxx</id>
        <release_name type="string">xxxxxx</release_name>
        <release_connection_type type="string">xxxxxx</release_connection_type>
      </item>
    </releases>
    <fpReleases type="array">
    </fpReleases>
    <sources type="array">
      <item type="object">
        <sourceName type="string">xxxxxx</sourceName>
        <sourceRecordUrl type="string">xxxxxx</sourceRecordUrl>
      </item>
    </sources>
    <productNumbers type="array">
    </productNumbers>
    <tags type="array">
    </tags>
    <productComponents type="array">
    </productComponents>
    <ranPlatforms type="array">
    </ranPlatforms>
    <subReleases type="array">
    </subReleases>
    <requirementAreaId type="number">xxxxxx</requirementAreaId>
    <requirementArea type="string">xxxxxx</requirementArea>
    <itemContact type="string">xxxxxx</itemContact>
    <toBeHandledAtxxx type="string">xxxxxx</toBeHandledAtLuca>
  </item>
    <item type="object">
    <id type="number">xxxxxx</id>
    <mainReqIdentity type="string">xxxxxx</mainReqIdentity>
    <itemName type="string">xxxxxx</itemName>
    <kanbanPhase type="string">xxxxxx</kanbanPhase>
    <kanbanStatus type="string">xxxxxx</kanbanStatus>
    <kanbanNote type="string">xxxxxx</kanbanNote>
    <backlogItemType type="string">xxxxxx</backlogItemType>
    <identityDomain type="string">xxxxxx</identityDomain>
    <fromDatetime type="string">2016-08-23 17:01:52</fromDatetime>
    <teams type="array">
      <item type="object">
        <team_name type="string">xxxxxx</team_name>
        <preliminary type="boolean">xxxxxx</preliminary>
      </item>
    </teams>
    <releases type="array">
      <item type="object">
        <id type="number">xxxxxx</id>
        <release_name type="string">xxxxxx</release_name>
        <release_connection_type type="string">xxxxxx</release_connection_type>
      </item>
    </releases>
    <fpReleases type="array">
    </fpReleases>
    <sources type="array">
      <item type="object">
        <sourceName type="string">xxxxxx</sourceName>
        <sourceRecordUrl type="string">xxxxxx</sourceRecordUrl>
      </item>
    </sources>
    <productNumbers type="array">
    </productNumbers>
    <tags type="array">
    </tags>
    <productComponents type="array">
    </productComponents>
    <ranPlatforms type="array">
    </ranPlatforms>
    <subReleases type="array">
    </subReleases>
    <requirementAreaId type="number">xxxxxx</requirementAreaId>
    <requirementArea type="string">xxxxxx</requirementArea>
    <oaResultReference type="string">xxxxxx</oaResultReference>
    <itemContact type="string">xxxxxx</itemContact>
    <f0Date type="string">2014-10-17</f0Date>
    <f1Date type="string">2015-01-16</f1Date>
    <f2Date type="string">2015-02-13</f2Date>
    <f4Date type="string">2015-06-12</f4Date>
    <faDate type="string">2015-06-12</faDate>
    <fgDate type="string">2015-06-12</fgDate>
    <toBeHandledAtxxx type="string">xxxxxx</toBeHandledAtLuca>
  </item>
 </root>

样本2

<ROOT>  
<Customer CustomerID="VINET" ContactName="Paul Henriot">  
   <Order CustomerID="VINET" EmployeeID="5" OrderDate="1996-07-04T00:00:00">  
      <OrderDetail OrderID="10248" ProductID="11" Quantity="12"/>  
      <OrderDetail OrderID="10248" ProductID="42" Quantity="10"/>  
   </Order>  
</Customer>  
<Customer CustomerID="LILAS" ContactName="Carlos Gonzlez">  
   <Order CustomerID="LILAS" EmployeeID="3" OrderDate="1996-08-16T00:00:00">  
      <OrderDetail OrderID="10283" ProductID="72" Quantity="3"/>  
   </Order>  
</Customer>  
</ROOT>

SQL

通用登台表

create table ZZZZZZZZZ
(
api_id int,record_type char(1),record_id INT,last_run_time datetime,last_run_by varchar(500),col1 VARCHAR(500),col2 VARCHAR(500),col3 VARCHAR(500),col4 VARCHAR(500),col5 VARCHAR(500),col6 VARCHAR(500),col7 VARCHAR(500),col8 VARCHAR(500),col9 VARCHAR(500),col10 VARCHAR(500),col11 VARCHAR(500),col12 VARCHAR(500),col13 VARCHAR(500),col14 VARCHAR(500),col15 VARCHAR(500),col16 VARCHAR(500),col17 VARCHAR(500),col18 VARCHAR(500),col19 VARCHAR(500),col20 VARCHAR(500),col21 VARCHAR(500),col22 VARCHAR(500),col23 VARCHAR(500),col24 VARCHAR(500),col25 VARCHAR(500),col26 VARCHAR(500),col27 VARCHAR(500),col28 VARCHAR(500),col29 VARCHAR(500),col30 VARCHAR(500),col31 VARCHAR(500),col32 VARCHAR(500),col33 VARCHAR(500),col34 VARCHAR(500),col35 VARCHAR(500),col36 VARCHAR(500),col37 VARCHAR(500),col38 VARCHAR(500),col39 VARCHAR(500),col40 VARCHAR(500),col41 VARCHAR(500),col42 VARCHAR(500),col43 VARCHAR(500),col44 VARCHAR(500),col45 VARCHAR(500),col46 VARCHAR(500),col47 VARCHAR(500),col48 VARCHAR(500),col49 VARCHAR(500),col50 VARCHAR(500),col51 VARCHAR(500),col52 VARCHAR(500),col53 VARCHAR(500),col54 VARCHAR(500),col55 VARCHAR(500),col56 VARCHAR(500),col57 VARCHAR(500),col58 VARCHAR(500),col59 VARCHAR(500),col60 VARCHAR(500),col61 VARCHAR(500),col62 VARCHAR(500),col63 VARCHAR(500),col64 VARCHAR(500),col65 VARCHAR(500),col66 VARCHAR(500),col67 VARCHAR(500),col68 VARCHAR(500),col69 VARCHAR(500),col70 VARCHAR(500),col71 VARCHAR(500),col72 VARCHAR(500),col73 VARCHAR(500),col74 VARCHAR(500),col75 VARCHAR(500),col76 VARCHAR(500),col77 VARCHAR(500),col78 VARCHAR(500),col79 VARCHAR(500),col80 VARCHAR(500),col81 VARCHAR(500),col82 VARCHAR(500),col83 VARCHAR(500),col84 VARCHAR(500),col85 VARCHAR(500),col86 VARCHAR(500),col87 VARCHAR(500),col88 VARCHAR(500),col89 VARCHAR(500),col90 VARCHAR(500),col91 VARCHAR(500),col92 VARCHAR(500),col93 VARCHAR(500),col94 VARCHAR(500),col95 VARCHAR(500),col96 VARCHAR(500),col97 VARCHAR(500),col98 VARCHAR(500),col99 VARCHAR(500),col100 VARCHAR(500),col101 VARCHAR(500),col102 VARCHAR(500),col103 VARCHAR(500),col104 VARCHAR(500),col105 VARCHAR(500),col106 VARCHAR(500),col107 VARCHAR(500),col108 VARCHAR(500),col109 VARCHAR(500),col110 VARCHAR(500),col111 VARCHAR(500),col112 VARCHAR(500),col113 VARCHAR(500),col114 VARCHAR(500),col115 VARCHAR(500),col116 VARCHAR(500),col117 VARCHAR(500),col118 VARCHAR(500),col119 VARCHAR(500),col120 VARCHAR(500),col121 VARCHAR(500),col122 VARCHAR(500),col123 VARCHAR(500),col124 VARCHAR(500),col125 VARCHAR(500),col126 VARCHAR(500),col127 VARCHAR(500),col128 VARCHAR(500),col129 VARCHAR(500),col130 VARCHAR(500),col131 VARCHAR(500),col132 VARCHAR(500),col133 VARCHAR(500),col134 VARCHAR(500),col135 VARCHAR(500),col136 VARCHAR(500),col137 VARCHAR(500),col138 VARCHAR(500),col139 VARCHAR(500),col140 VARCHAR(500),col141 VARCHAR(500),col142 VARCHAR(500),col143 VARCHAR(500),col144 VARCHAR(500),col145 VARCHAR(500),col146 VARCHAR(500),col147 VARCHAR(500),col148 VARCHAR(500),col149 VARCHAR(500),col150 VARCHAR(500)
)

样本输出

用TSQL编写的通用XML解析器.代码中有很少的hacks和一些需要删除的杂散代码.这很好用.但问题是通过直接调用或通过文件从C#代码发送整个XML文档作为输入参数.

CREATE PROC ZZZZZZZ
(
@in_api_id int,@in_xml_doc XML,@in_xml_root varchar(100),@in_tot_result_col int = 150,@in_need_colnm_result CHAR(1) = 'Y',@in_debug_flg CHAR(1) = 'N'
)
AS
BEGIN
DECLARE 
    @idoc int,@sqlstr nvarchar(max) = '',@param nvarchar(200) = '',@runtime datetime = getdate(),@runby varchar(30) = suser_name(),@cnt int,@pre_stg_col_nm varchar(max) = '',@max_lvl int,@max_node varchar(500)='',@max_node_wo_slash varchar(500)='',@xml_col nvarchar(max) = '',@unq_col nvarchar(max) = '',@unq_xml_col nvarchar(max)=''

--Create an internal representation of the XML document.  
EXEC sp_xml_preparedocument @idoc OUTPUT,@in_xml_doc;  
-- Execute a SELECT statement that uses the OPENXML rowset provider.  
set @in_xml_root = concat('/',@in_xml_root)
SELECT * into #tmp FROM OPENXML (@idoc,@in_xml_root,2) where id <> 0;

--select * from #tmp_xml_nodes
--select * from #tmp
--select * from #tmp_pre_staging

;with xml_cte(id,parentid,nodetype,localname,prefix,namespaceuri,datatype,prev,text,lvl,node,parent_localname)
AS
(
select  id,1 as lvl,cast(CONCAT(@in_xml_root,'/',localname) as varchar(100)) node,cast('' as varchar(200))
from #tmp
where parentid = 0
UNION all
select  t.id,t.parentid,t.nodetype,t.localname,t.prefix,t.namespaceuri,t.datatype,t.prev,t.text,iif(t.nodetype = 1,xc.lvl+1,xc.lvl),cast(
                        CONCAT (
                                        xc.node,CONCAT (
                                                            '/',t.localname
                                                            ),''
                                                )
                                        ) AS VARCHAR(100)
                            ),cast(xc.localname as varchar(200))
from #tmp t
inner join xml_cte xc
on xc.id = t.parentid
)
select * into #xmlcte from xml_cte

--select * from #xmlcte
--v2 change
select @max_lvl = max(lvl)--iif(max(lvl)>=4,1,0) -- the iif condition is just a hack,I dont know why it works
from #xmlcte 

select 
    @max_node = concat(max(node),'/'),@max_node_wo_slash = max(node) 
from #xmlcte 
where lvl = @max_lvl

select *,concat(parent_localname,'_',' varchar(500)') fnl_col_nm,case 
                                when lvl<@max_lvl then concat(replicate('../',@max_lvl-lvl+iif(nodetype=1,0)),iif(nodetype=1,'','@'),localname) --v2 change
                                when lvl>@max_lvl then concat(replace(node,@max_node,''),'/@'),localname)--v2 change
                                else concat('../','/@')),localname)--v2 change
                                end col_Struct,localname) col_unq_nm,ROW_NUMBER() over (order by(select 100)) sno,concat('xmlname.value(''/Names[1]/name[',ROW_NUMBER() over (order by(select 100)),']'',''varchar(500)'') AS ',localname)) col_splt_nm
into #xml_col_struct
from #xmlcte
where nodetype <= 2--v2 change

--select * from #xml_col_struct
set @cnt = (select count(distinct col_unq_nm) from #xml_col_struct)

select @pre_stg_col_nm =
(
select concat(',',COLUMN_NAME)
from INFORMATION_SCHEMA.COLUMNS
where table_name = 'ZZZZZZ'
and COLUMN_NAME like 'col%'
and ORDINAL_POSITION <= @cnt+5
order by ORDINAL_POSITION
for xml path('')
)

set @sqlstr = concat(
                                        'insert into ZZZZZ(api_id,record_type,record_id,last_run_time,last_run_by',@pre_stg_col_nm,')'
                                        )
select @xml_col =
(
select distinct concat(',fnl_col_nm,' ''',col_Struct,'''',char(10)) 
from #xml_col_struct
order by 1
for xml path('')
)
set @xml_col = stuff(@xml_col,'')

select @unq_col =
(
select distinct concat(',col_unq_nm )
from #xml_col_struct
order by 1
for xml path('')
)
set @unq_col = stuff(@unq_col,'')

select @in_tot_result_col = @in_tot_result_col - count(distinct col_unq_nm)
from #xml_col_struct

select @unq_xml_col =
(
select 
concat(',xmlname.value(''/Names[1]/name[',col_unq_nm,char(10))
from (select distinct col_unq_nm from #xml_col_struct) t
for xml path('')
)
set @unq_xml_col = stuff(@unq_xml_col,'')

set @sqlstr =
                        concat(
                                    iif(@in_need_colnm_result = 'Y',concat('
                                                ;WITH Split_Names (xmlname)
                                                AS
                                                (
                                                        SELECT 
                                                        CONVERT(XML,''<Names><name>''  
                                                        + REPLACE(''',@unq_col,''',''</name><name>'') + ''</name></Names>'') AS xmlname
                                                )
                                                '
                                                --,@sqlstr,char(10),' SELECT ',@in_api_id,''H'',@runtime,@runby,@unq_xml_col,replicate(',NULL',@in_tot_result_col)--v2 change,'FROM Split_Names','union all'
                                                ),''
                                        )
                                    --,iif(@in_need_colnm_result = 'Y',@sqlstr),'
                                    SELECT ',''D'',*','FROM   OPENXML (@idoc_inn,@max_node_wo_slash,2)','WITH (',@xml_col,')'
                                    )

if @in_debug_flg = 'Y'
    begin
        select @max_lvl+1,@max_lvl,@unq_xml_col
        select * from #xml_col_struct--v2 change
    end
else
    begin
        set @param = '@idoc_inn int'
        exec sys.sp_executesql @sqlstr,@param,@idoc_inn = @idoc
    end
EXEC sp_xml_removedocument @idoc

END

用于读取C#类加载的XML文件的SQL代码.这也很好,但问题是所有行都在单独的行中,并且连接在一个点后截断

create table #tmp(data_line nvarchar(max))

bulk insert #tmp
FROM '\\Server\\ZZZZ\\Downloads\\Data.xml'  
   WITH   
      ( 
                --firstrow = 1          
                 ROWTERMINATOR ='\n'  
      );  

select * from #tmp

C#类

Object httpConn = Dts.Connections["HTTP"].AcquireConnection(null);
        HttpClientConnection myConnection = new HttpClientConnection(httpConn);
        myConnection.ServerURL = string.Format(("http://xxxx.com/jjjj"),"userid","password");
        byte[] webdata = myConnection.DownloadData();

        String result_data = Convert.ToBase64String(webdata);
        XmlDocument xd = new XmlDocument();
        XmlDictionaryReader xr = JsonReaderWriterFactory.CreateJsonReader(webdata,XmlDictionaryReaderQuotas.Max);

        xr.Read();
        xd.LoadXml(xr.ReadOuterXml());
        xd.Save("\\Server\\ZZZZ\\Downloads\\Data.xml");

解决方法

如果您获得格式正确的XML.您可以使用数据集.具体使用Dataset.ReadXml().这将在数​​据集对象中加载xml,而与xml标记无关.然后,您可以使用ADO.Net,linq2sql,EF或任何其他通信方法将其放入数据库中.

由于您在服务器上保存文件,因此可以使用以下代码:

DataSet ds = new DataSet();
ds.ReadXml("\\Server\\ZZZZ\\Downloads\\Data.xml");

然后你可以使用foreach循环迭代每个数据集表. xml中的属性将成为数据表中的列.

所以你的最终代码将类似于:

using (DataSet ds = new DataSet())
{
     ds.ReadXml("\\Server\\ZZZZ\\Downloads\\Data.xml");
     int nTableCounts = ds.Tables.Count;
     foreach(DataTable dt in ds.Tables)
     {
          using (dt)
          {
            //Put data in SQL table.
          }
     }
}

如果有什么不清楚,请告诉我.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


项目中经常遇到CSV文件的读写需求,其中的难点主要是CSV文件的解析。本文会介绍CsvHelper、TextFieldParser、正则表达式三种解析CSV文件的方法,顺带也会介绍一下CSV文件的写方法。 CSV文件标准 在介绍CSV文件的读写方法前,我们需要了解一下CSV文件的格式。 文件示例 一
简介 本文的初衷是希望帮助那些有其它平台视觉算法开发经验的人能快速转入Halcon平台下,通过文中的示例开发者能快速了解一个Halcon项目开发的基本步骤,让开发者能把精力完全集中到算法的开发上面。 首先,你需要安装Halcon,HALCON 18.11.0.1的安装包会放在文章末尾。安装包分开发和
这篇文章主要简单记录一下C#项目的dll文件管理方法,以便后期使用。 设置dll路径 参考C#开发奇技淫巧三:把dll放在不同的目录让你的程序更整洁中间的 方法一:配置App.config文件的privatePath : &lt;runtime&gt; &lt;assemblyBinding xml
在C#中的使用JSON序列化及反序列化时,推荐使用Json.NET——NET的流行高性能JSON框架,当然也可以使用.NET自带的 System.Text.Json(.NET5)、DataContractJsonSerializer、JavaScriptSerializer(不推荐)。
事件总线是对发布-订阅模式的一种实现,是一种集中式事件处理机制,允许不同的组件之间进行彼此通信而又不需要相互依赖,达到一种解耦的目的。&#xA;EventBus维护一个事件的字典,发布者、订阅者在事件总线中获取事件实例并执行发布、订阅操作,事件实例负责维护、执行事件处理程序。
通用翻译API的HTTPS 地址为https://fanyi-api.baidu.com/api/trans/vip/translate,使用方法参考通用翻译API接入文档 。&#xA;请求方式可使用 GET 或 POST 方式(Content-Type 请指定为:application/x-www-for
词云”由美国西北大学新闻学副教授、新媒体专业主任里奇·戈登(Rich Gordon)于2006年最先使用,是通过形成“关键词云层”或“关键词渲染”,对文本中出现频率较高的“关键词”的视觉上的突出。词云图过滤掉大量的文本信息,使浏览者只要一眼扫过文本就可以领略文本的主旨。&#xA;网上大部分文章介绍的是使用P
微软在.NET中对串口通讯进行了封装,我们可以在.net2.0及以上版本开发时直接使用SerialPort类对串口进行读写操作。&#xA;为操作方便,本文对SerialPort类做了一些封装,暂时取名为**SerialPortClient**。
简介 管道为进程间通信提供了平台, 管道分为两种类型:匿名管道、命名管道,具体内容参考.NET 中的管道操作。简单来说,匿名管道只能用于本机的父子进程或线程之间,命名管道可用于远程主机或本地的任意两个进程,本文主要介绍命名管道的用法。 匿名管道在本地计算机上提供进程间通信。 与命名管道相比,虽然匿名
目录自定义日志类NLog版本的日志类Serilog版本的日志类 上个月换工作,新项目又要重新搭建基础框架,把日志实现部分单独记录下来方便以后参考。 自定义日志类 代码大部分使用ChatGPT生成,人工进行了测试和优化,主要特点: 线程安全,日志异步写入文件不影响业务逻辑 支持过期文件自动清理,也可自
[TOC] # 原理简介 本文参考[C#/WPF/WinForm/程序实现软件开机自动启动的两种常用方法](https://blog.csdn.net/weixin_42288432/article/details/120059296),将里面中的第一种方法做了封装成**AutoStart**类,使
简介 FTP是FileTransferProtocol(文件传输协议)的英文简称,而中文简称为“文传协议”。用于Internet上的控制文件的双向传输。同时,它也是一个应用程序(Application)。基于不同的操作系统有不同的FTP应用程序,而所有这些应用程序都遵守同一种协议以传输文件。 FTP
使用特性,可以有效地将元数据或声明性信息与代码(程序集、类型、方法、属性等)相关联。 将特性与程序实体相关联后,可以在运行时使用反射这项技术查询特性。&#xA;在 C# 中,通过用方括号 ([]) 将特性名称括起来,并置于应用该特性的实体的声明上方以指定特性。
# 简介 主流的识别库主要有ZXing.NET和ZBar,OpenCV 4.0后加入了QR码检测和解码功能。本文使用的是ZBar,同等条件下ZBar识别率更高,图片和部分代码参考[在C#中使用ZBar识别条形码](https://www.cnblogs.com/w2206/p/7755656.htm
C#中Description特性主要用于枚举和属性,方法比较简单,记录一下以便后期使用。 扩展类DescriptionExtension代码如下: using System; using System.ComponentModel; using System.Reflection; /// &lt;
本文实现一个简单的配置类,原理比较简单,适用于一些小型项目。主要实现以下功能:保存配置到json文件、从文件或实例加载配置类的属性值、数据绑定到界面控件。&#xA;一般情况下,项目都会提供配置的设置界面,很少手动更改配置文件,所以选择以json文件保存配置数据。
前几天用SerialPort类写一个串口的测试程序,关闭串口的时候会让界面卡死。网上大多数方法都是定义2个bool类型的标记Listening和Closing,关闭串口和接受数据前先判断一下。我的方法是DataReceived事件处理程序用this.BeginInvoke()更新界面,不等待UI线程
约束告知编译器类型参数必须具备的功能。 在没有任何约束的情况下,类型参数可以是任何类型。 编译器只能假定 System.Object 的成员,它是任何 .NET 类型的最终基类。 如果客户端代码使用不满足约束的类型,编译器将发出错误。 通过使用 where 上下文关键字指定约束。&#xA;最常用的泛型约束为
protobuf-net是用于.NET代码的基于契约的序列化程序,它以Google设计的“protocol buffers”序列化格式写入数据,适用于大多数编写标准类型并可以使用属性的.NET语言。&#xA;protobuf-net可通过NuGet安装程序包,也可直接访问github下载源码:https:/
工作中经常遇到需要实现TCP客户端或服务端的时候,如果每次都自己写会很麻烦且无聊,使用SuperSocket库又太大了。这时候就可以使用SimpleTCP了,当然仅限于C#语言。&#xA;SimpleTCP是一个简单且非常有用的 .NET 库,用于处理启动和使用 TCP 套接字(客户端和服务器)的重复性任务