关于c#:记Quartz中使用AutoFac依赖注入遇到的问题

背景       最近在做一个需要,就是在Job中捕获异样,而后通过邮件或者音讯的形式推送给指定人员,在需要实现的过程中遇到的一个注入问题,觉得很有意思,特此记录。        如果您看了感觉或者曾经有更好的方法,烦请通知我一下,咱们能够独特探讨,如果有中央不对,也请不吝斧正。 遇到的问题       因为不同性能的Job很多,每一个Job中都要实现对产生异样的音讯发送,现有的Job是这样的        为了实现这个需要,也为了当前更好的保护,我筹备用事件委托的模式去实现,将对异样音讯发送的业务逻辑拆出,保障职责繁多,思路如下: 1. 在Job和IJob两头再加一层IExceptionJobHandler接口作为束缚 2. 接口中定义一个发送异样音讯的事件PushException 3. 而后每一个Job在异样时去触发这个事件,内部只须要对立订阅一个事件即可。        到目前这一步是可行的,尽管不是很完满的设计,然而还是比拟清晰的,然而另外一个问题来了,我如何通过Autofac注入这个Job呢,原来间接继承自Ijob当初加了一层。 问题剖析       这个问题花了我整整大概4个小时的工夫去钻研依赖注入的形式还在网上搜了良久,没什么停顿,而后从新梳理了一下框架依赖注入的代码,发现是走错路了,注入Job应用的是Autofac.Extras.Quartz来实现的,这下晓得方向了。 var builder = new ContainerBuilder(); builder.RegisterModule(new QuartzAutofacFactoryModule { ConfigurationProvider = c => schedulerConfig });       这个QuartzAutofacFactoryModule外面肯定有我想晓得的货色,就在Github上下载了Autofac.Extras.Quartz的源码,关上一看,果然发现了它的真面目        这外面就是对Job依赖注入的,然而没有发现对Job的注册和构建,留神箭头标记的,它有一个AutofacJobFactory类,接管一个ILifetimeScope,而它的作用就是用来构建Job为作用域周期失效的服务实例。 解决的方法       1.下面以及剖析出构建Job服务实例的,是一个叫AutofacJobFactory的工厂,返回一个IJob,那如何把IExceptionJobHandler注入进去,让咱们Job实例领有这个事件呢?       2.因为咱们的IExceptionJobHandler曾经继承了IJob,也就是说这里间接能够把Ijob换成IExceptionJobHandler,那该如何实现呢?继承        3.咱们察看到在AutofacJobFactory构建服务的办法是一个虚办法,所以利用继承咱们新建一个ExtendAutofacJobFactory来重写它将Ijob换成IExceptionJobHandlerpublic class ExtendAutofacJobFactory : AutofacJobFactory { protected override IJob ResolveJobInstance(ILifetimeScope nestedScope, IJobDetail jobDetail) { //验证Job是否派生自IExceptionJobHandler if (typeof(IExceptionJobHandler).IsAssignableFrom(jobDetail.JobType)) { IExceptionJobHandler instance = null; instance = (IExceptionJobHandler)CreateIJob(nestedScope, jobDetail); //注册事件对立解决入口 instance.PushException += pushExceptionMessageManager.Value.ExceptionJobHandler return instance; } else { return base.ResolveJobInstance(nestedScope, jobDetail); } } }       4.咱们须要把重写的结构工厂放入QuartzAutofacFactoryModule,仍然抉择继承的形式去重写QuartzAutofacFactoryModule,而后在加载服务时将服务结构工厂换成咱们本人的ExtendAutofacJobFactory ...

August 15, 2021 · 1 min · jiezi

关于c#:记加载数据慢优化代码的小结

背景开始        故事的开始因为在工作中遇到一个需要去解决加载数据十分慢的问题,要害程序是曾经在生产环境运行了相当长一段时间的,按情理来说是不会有问题,至多从线上运行的稳定性来说。 个人观点        在这里仅作为开发小结记录一下,谁写的和为什么这样写的问题,不在此次记录总结范畴之内,只针对代码做出剖析,如果您看了感觉或者曾经有更好的方法,烦请通知我一下,咱们能够独特探讨,如果有中央不对,也请不吝斧正。 为什么要记录下来?        做任何事件都要有产出,日常开发也一样,除了交付工作,还应有本人的总结,以利于本人后续复盘,产出不在于多少,几行文字、一个表格或者画一幅图。产出也不在于100%能搞懂开发中的每一个问题,把看不懂的总结进去,也是产出。        后续解决的问题或没解决的都在这里总结记录,此前解决过的也会陆续从新总结 找到起因       通过一番调试定位到代码之后,找到了问题次要分2类: 1.反复求值 这个很好了解,就是下面曾经获得雷同操作后果,或者能够获得雷同操作后果存入变量,然而此处并没有这个做而是每一次都执行须要求值的表达式去失去后果,大大的升高了执行效率和进步了资源占用 2.循环嵌套        鉴于波及公司代码,不不便贴出,为了更加活泼的形容具体问题,上面是我依据问题形象出的代码Demo和形容如下: 1).循环500次,对应的list汇合中有50W条数据 2).依据Lambda找到ProductId为213000的数据,而后存入result汇合 依据下面的示例代码能够发现,在循环中,又应用了循环,暂且不思考ForEach是否是多线程或者它和foreach 以及for的执行效率,为什么说又应用了循环呢?通过排查发现导致问题的外围的起因就是外部的Lambda表达式求值,为什么求值慢呢? 特意查看了源码并且查看相干参考资料,因为Lambda就是循环实现的,只不过退出了迭代器和状态机这样一些的提早机制,即便这样它仍然会影响效率。 如果从数据结构的角度形象来剖析,此处工夫复杂度就是O(500*50w) 随着次数增大,执行工夫就是越来越大的增长。3.验证执行工夫 验证执行工夫为:1195毫秒,如果在外层再加一层循环呢? 汇合操作皆可Lambda?       鉴于曾经找到了问题所在,下一步就要着手解决的办法了,第一个问题好解决,扭转一下求值写法就好了。        次要是第二个问题的解决,在解决问题之前失去了一个很重要的的论断 那就是"Lambda并不实用所有中央,反而有时会让你的程序更蹩脚" 看了下面的例子是不是深有体会。 解决方案如何优化lambda(循环)? 咱们要思考问题的实质是在这里对list怎么查找比程序循环快,在数据结构中程序表查找分为三类: 1.程序查找 2.二分查找 3.索引查找        如何抉择对应查找优化,这里的重点就是要将工夫复杂度从O(n)或者O(10x500x50w)转为O(1),毫无疑问在这抉择索引查找,因为依据索引下标拜访元素的工夫复杂度为O(1),那索引查找必然优于程序查找的,接下来如何变为索引查找呢?        咱们不禁会问:"在这里恰好是索引下标跟ProductId对上了能力找到,那如果是乱的呢"? 那就须要变通一下,就是变为字典汇合,依据键找到值 ...

August 15, 2021 · 1 min · jiezi

关于c#:C8中的Range和Index范围和索引

起源:https://note.guoqianfan.com/2...Range-范畴范畴运算符范畴运算符:..,它会生成一个Range对象。语法:{startIndex}..{endIndex}:蕴含startIndex,不蕴含endIndex限度:0 <= startIndex <= endIndex <= arr.Length,其余均会报错! startIndex等于endIndex时,取不出元素,会生成一个空数组。 留神: 默认状况下,..的后面是0,前面是 arr.Length(不含)。..等价于0..arr.Length。所以..的后面和前面均能够为空。所以..也能够独自应用,代表整个索引范畴(0..arr.Length):arr[..]是arr的残缺拷贝。深拷贝还是浅拷贝须要看元素是值类型还是援用类型。值类型复制值,能够认为是深拷贝;援用类型复制援用,就是浅拷贝。 RangeRange用来从汇合中取出 指定索引范畴 的元素来生成新的汇合。 创立Range:Range range = 2..4; var arr = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };Range range = 2..4;int[] slice = arr[range]; // 或 arr[2..4];foreach (var number in slice){// [3, 4] Console.WriteLine(number);}arr[2..4]示意把arr这个序列,从索引为2的元素始终到索引为4(不含4)的元素提取进去组成新的序列。所以后果就是3,4。 Index-索引Index用来指定索引。该索引能够用来从汇合中取出指定索引处的元素,是单个元素。 乍一看,Index与int类型的索引没啥区别。嗯。。的确是这样,因为Index要与^操作符联合起来能力施展更大的作用。对了,还有Range。。 开端运算符^是开端运算符(Hat运算符),它会生成一个Index对象,用来从开端开始往前取数据。 与正向取数据时索引从0开始不同,^取数据时是从1开始的,代表倒数第一个元素。 arr[^1]等于arr[arr.Length-1],最初一个元素arr[^0]等于arr[arr.Length],常与Range组合应用如果应用arr[^0]的话就会抛出IndexOutOfRangeException,arr[^0]和arr[arr.Length]是一个意思。 这的确有点容易让人混同,但其实其它语言也差不多是这样设计的,例如-1这个索引示意最初一个元素。 组合应用 Range 和 Index残缺拷贝数组的3种形式int[] arr = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };int[] arr01 = arr[0..arr.Length];int[] arr02 = arr[0..^0];int[] arr03 = arr[..];留神: ...

August 8, 2021 · 1 min · jiezi

关于c#:你是否学习过你常用框架的源码

写在后面       首先申明这不是分享框架如何应用的教程,也不是作为一个传教者讲授的教程,这只是作为一个一直学习的开发者学习的一个记录,然而这个记录我把他分享进去,如果您看到了,或者有不同的见解,请您提出来咱们进行敌对的探讨,而不是毫无根据的鞭挞。 咱们开始吧        因为做.Net开发工作也曾经好几年了,经验过一些技术的变迁,刚接触的是webform,到前面的mvc以及当初比拟风行的webapi,从开始的一把梭,再到近年来微服务思维的遍及,前后端拆散的劣势从而显现出来,随着工夫往后推移,或者还会出更多优良的框架,然而作为开发人员我感觉除了框架的应用之外,很有必要的去理解一下框架运行的原理和机制,哪怕很少的一部分。         在此总结了下我集体认为须要去学习的观点,仅仅只代表我本人,在此我并没有把.NetFrameWork和.NetCore分为三六九等,在我心中它们都是十分优良的框架,只是侧重点不同而已,如果有不失当或者基本不正确的论证援用,那只能阐明我写总结的程度有余,并不代表我对它们任何一个带有敌意和歧视,大家可能学习过.NetCore,他的特点是什么?以及吸引到你的中央是什么,是纯正为了谋求时尚?还是跨平台?又或者是它的可配置,高性能?         各种中间件的扩大,跟搭积木一样,依照你本人的想法来搭建一个应用程序,是不是更加体现了它的魅力所在,咱们比照.Net framework 他的毛病就显著很多了,你要的不要的都放框架里,你要执行或者不执行的它都给你执行,简称"大杂烩" ,而后益处是开发者只须要关怀业务,因为你不须要操心技术问题,更不须要理解框架帮你做了什么,你只须要写好你负责的那个模块的增删改查。         这尽管在某种程度上进步了生产能力,然而作为程序员的角度来说就很危险了,所以这就是为什么后面说要学习它的机制的起因,你能够不必,然而要理解,因为一个程序员想要晋升本人的技术水平,则必须学习基础知识,在此处的“基础知识”指的是针对现有框架的机制和原理以及框架代码中优良的设计思维以及编码,这对集体技术晋升有很大的帮忙。至于学到什么水平,取决于每个人本人的认知

August 8, 2021 · 1 min · jiezi

关于c#:使用C写脚本

前言应用.NET的同学们可能都会有一个比拟苦楚的体验,就是如果须要写一段测试的代码或者示例代码,也不得不创立一个我的项目去解决,即使是最根底的控制台程序, 应用 dotnet cli,也须要面对如下一段最根底的入口代码。 using System;namespace Demo{ class Program { static void Main(string[] args) { Console.WriteLine("Hello World!"); } }}全然不像python、js之类,关上编辑器/命令行就能够撸代码一样的不便。 作为支流的开发语言,天然是有特定的解决方案的。 老牌的.NET程序员可能相熟的一个开发工具LINQPad,就是一个不错的.NET代码演练工具,同时也提供了F#和SQL语言反对,设置能够间接链接数据库进行查问,不堪称不弱小。 现在LINQPad 6 也反对了.NET 5,也是一个不错的开发辅助工具。尽管LINQPad也提供了免费版的,然而想要应用NuGet包集成、代码提醒、debug等高级性能的话,还是须要购买受权的,如果经济能力富裕的话,尽量间接购买PREMIUM版本即可,体验最残缺的LINQPad。 除了LINQPad,还有其余很多的抉择,其中一个可能获取C#最原生体验的,就是间接应用C# script。早在 VS 2015 update 1的时候,VS就集成了一个 C# REPL Command-Line Interface(csi.exe),能够在命令行中间接执行C#语句,整体的体验和Python REPL和Node.js REPL差不多。于此同时,推出了一种新的脚本文件格式 csx,这样的话就能够应用C#写脚本文件了。 .NET Core时代以来,有了更多开源工具的抉择,其中的 dotnet script就是一个十分不错的C#脚本工具。 联合VS Code 和 OmniSharp ,应用 dotnet script能够给到相当不错的C#脚本开发体验。当然也是反对NuGet包和调试,而且开源收费,得益于相干性能的跨平台个性,根本反对全平台。 装置dotnet script自身的装置绝对容易。 装置dotnet core 2.1+ sdk ,如果应用 C# 8语言个性,须要装置 dotnet core 3.1+ sdk运行dotnet tool install -g dotnet-script 即可dotnet-script 装置实现之后,间接运行dotnet script即可进入RPEL模式中,间接撸C#代码间接运行。 ...

July 31, 2021 · 1 min · jiezi

关于c#:毕业四年我当初是如何走上编程这条路的

题记感慨万千,毕业已达4年之久。 想起在大学期间学习编程的事件,感觉很有意义,在此记录回顾一下。 心愿本人初心未变,勇往向前 现状与过来20210706 目前的我是在天津一家公司做软件开发,次要做C#桌面端开发,有时还写点Android,但主技还是C#、ASP.NET。 从毕业实习到当初始终在这家公司,是不是很吃惊。 毕竟在我同学都曾经换了不下3个单位的时候我还在刚开始的这家公司里,他特比吃惊,感觉不堪设想。 17年在大四第二学期时,咱们班很多同学都曾经离校,这也是学校过后默认的事件。 其实也就是为了进步入职率,让不考研和考公的同学尽早的找工作,尽早的进入职场。 我很感激学校有这样的政策,解决了我大四第二学期在外实习无奈不上课的难题。其实我也很费解,大四为什么还要排课,基本上一天也就一节课,而且很多同学都不在校,每次上课就只剩下考研和考公的同学在,也就不到15人。 可能每所大学在排大四课程的时候,都比拟两难。 我是复读一年才勉强考上大学(中央二本院校)的,高三第一年根本是在网吧打游戏度过的,基本不晓得学习,也没有要为本人未来做打算的信心,每天糊里糊涂的,度日如年。当初回想起来,真想使劲抽本人几个巴掌,那么好的资源,那么多工夫就那样被本人节约掉了。 复读那一年,堪称是惜时如金,晓得了学习,也戒掉了游戏。根本全年都在学习,因为晓得本人和他人的差距。 其实特别感谢我的妈妈和舅舅(还有其余的亲戚),没有她们我是无论如何也不会去复读的。过后考完试我就筹备报考一个大专,学习汽车培修,本人构想当前开一个汽修厂。我感觉本人轻易干些什么都能够,为什么非得去复读,再去学习,还要去考大学呢。(不晓得本人过后哪来那样的自信,再次想抽本人几个巴掌) 高考第一年我考了369分,过后陕西的二本分数线是461。如同刚好能上个三本院校,然而我不想让家外面多花钱就想间接去上大专,学个技能傍身。可是扭不过爸妈和亲戚的相劝,他们语重心长的劝我,劝我去复读,给我列举了各种复读的益处,最初我去复读了。 其实过后本人心里面分明,本人底子太差,即便复读一年也未必能考上二本。次要是差的太多,就拿过后考得问题来说,还差90分呢。 复读那一年,根本没咋劳动过,始终都在学习,记得过后还和几个敌人一起组织建设了学习小组,每天早出晚归的结伴学习。这一年兴许是运气比拟好,兴许是致力有了功效。第二年二本的分数线竟然降到了435分,我也好运的考了455分,比二本分数线高了20分(其实放眼到当初来看和他人比,差距还是特地特地大的,可是对于过后的本人来说,还是比拟侥幸的)。那可是足足进步了86分(替本人快乐)。 填报意愿时,本人特地想去成都,第一意愿就报了成都的一个学校。 对于填报的业余,其实对于过后的本人来说,基本不晓得未来要学什么,可能当初的高中生比拟有主意,网络这么发达,学习路径很多,可能早就确定了本人要学习的业余,可是对于过后的我来说,能想到的就是学机械制造,过后很粗略的理解机械制造具体是干什么的,就报了。其余的几个意愿都报的是陕西省内的,也根本都是机械制造为首的。 我依稀记得过后还特意报了物联网工程这个业余,理解的过程中感觉当前可能会大火(2021年也没火起来,其实也算火了,鸿蒙分布式系统火了)。这个业余是13年新开设的,在全国很火,每个学校都在开设物联网工程,我过后轻易理解了下,就把它填写在了最初一个意愿的第一个业余中。想着反正也不可能录入,毕竟我后面还有4个意愿,那么多业余呢,怎么能到最初一个意愿来呢(啪啪打脸)。 往往造化弄人,最初还是被不经意间抉择的物联网工程业余录取了。(甚是快慰呀,差点滑档了) 咱们学校物联网工程是被调配到计算机系的,因为是学校新开设的业余,没有什么以往教训,大学四年的课程安顿既有软件也有硬件。也就是说毕业后的咱们:既能熬夜加班敲得起代码,也能跃跃欲试焊的起板子。 可是对于本科生的咱们来说,样样通,不如一样精。 从13年刚入校我就理解到过后学校有个政策,大四那年院系会组织学生去西安加入培训,大略破费在2w元左右(达内,传智博播客,华清远见等),经过培训后的学生找工作都特地好,根本不必学校过多放心。 在过后大一的时候,我心里就默默使劲,阿辉呀你这四年可要好好致力,可别到了大四找工作的时候还要再去问家里要2w元来加入培训。 这不起初我的确没有加入培训,凭借本人大学四年在实验室外面学习到的编程技能,也还算顺利的找到了一份对口的工作。(文章前面能够看到过后本人的简历)。 我是17年2月来的天津,没有加入培训,间接进去工作,也算运气比拟好,单位也刚好是做C#方面的开发,也就牵强附会的留了下来,尽管其中也有一些别的起因,也算对口也算不对口(之前在学校次要做BS,来到公司后做CS)。然而也算持续走上了技术这条路,根本和本人在大三时给本人布局的职业门路一样,不一样的是本人来到了天津,而没有去上海(大学期间特地想去上海,感觉只有上海能力干出一番天地)。 我的大学大学四年,我给同学的感觉应该是很怪的,根本没事的时候都泡在实验室里(既有Wifi又有妹子),在宿舍基本看不到人,只有找我在我的项目实验室相对能找到。 我记得过后是大一下学期面试进的我的项目实验室,刚进来的时候感觉B格特地高,我的项目实验室牵头的是咱们信工院的一个日本求学归来的海龟博士申请创立的(很感激徐老师)。次要目地就是想开办一个连贯校外单位和学校学生之间的媒介,让学生通过接触真正落地的我的项目来感触理解里面单位真正须要哪种人才,让学生能够提前的进行筹备学习,为本人当前找工作早做打算。 B格高的起因:徐老师早晨也会偶然给咱们组织培训,平时根本的输入都是日语和国语混合,特地有意思。而且经常性的请大家喝咖啡(我当初爱喝咖啡的习惯可能就是那时候养成的) 刚开始的时候也就是个小罗罗,给搬电脑,打扫卫生,举办活动修电脑等,根本都是这样的活。前面到了大二,大三才缓缓的跟着实验室的室长开始做我的项目,保护学校官网微信(过后官微是室长借助盛派的SDK开发的),加入学校,市区等举办的大学生三创大赛,其中的作品也有获奖的,也有没获奖的,然而过后失去的我的项目教训的确实实在在是属于我的。 其实过后之所以进入实验室目标很单纯,就是想着毕业后不去培训。本人在大学期间多自主学习下,等到了大四简历下面就有我的项目可写了。可是待的工夫越久,越发现自己想做的事件越多,到最初来到时,本人也被老师提拔为实验室室长之一,也率领着学弟学妹们一起加入大创我的项目,带着大家一起学习编程常识。 上面图片是过后我的项目实验室的环境,很适宜学习,而且网速特快,又有空调,偶然老师还给大家说几句日语,请大家喝喝咖啡。 大学四年至今最让我回味无穷的是,学校旁边的鸡肉焖饺子,几乎一绝,每次宿舍聚餐都会去,越看越有感觉。 我是如何走上编程这条路的其实学习编程次要有以下几个方面的起因: 目标过后在大学努力学习编程的目地就只有一个,那就是不想大四毕业时去培训,想着在大学就把技术学好,所以才很致力的学习。(相比于其余同学而言,只是早早的晓得了本人该干什么而已,但和那些一流大学毕业后面试进大厂的同学比起来差的不是一丁半点,差距太大了,还得好好致力)。 趣味专业课程安顿有JAVA、C语言、Android,然而老师上课讲的也都是书本下面最最根本的知识点,实践层面并重,达不到学完后立马能上手做我的项目的水平。 尽管说业余外面学习JAVA和C语言,然而让我感兴趣的却是C#。在过后学完JAVA后,特地不喜爱配置环境,记得应用的IDE还是Eclipse,在环境配置这块就卡了良久才配置好。比照之下简略、疾速上手的C#,还是感觉JAVA太麻烦,过后感觉好简单,缓缓的就对其丢失了趣味,就始终和实验室老师和学长学习C#开发,用C#做我的项目,加入各种较量(当初反过来想,如果当初立志学JAVA,可能本人会走一条不一样的路,毕竟当初最火的是JAVA开发)。 金钱报酬过后做我的项目加入较量是能够挣到钱,尽管不多,但对于过后学生身份的我来说,1000~3000的,也是不错的经济起源,能够买一些本人之前始终舍不得买的货色或者说和舍友们进来大吃一顿好的(鸡肉焖饺子走起)。 鲜为人知的、少一些为什么的保持过后大一下学期和我一起报名在实验室上夜课(老师解说学习C#)的同学很多,可是等到大四快毕业时,还在做C#的就我和隔壁宿舍的哥们(李乾龙)。在一起学习的过程中,有些同学就因为或多或少各种各样的起因缓缓的早晨就不来了,放弃了。其实这都是很失常的,当有些事件得不到反馈或者说短时间内看不到回报时,大家都会有这种情绪呈现的。 也不晓得为什么,我和乾龙就保持了下来,基本上,每天只有没有大课安顿,咱们俩就背着电脑和键盘待在实验室外面学习(看视频、看书、敲代码),当初忽然想起还挺思念过后和好友一起努力奋斗的时光。 如何学习编程其实说起如何学习编程这个话题,本人或多或少还能说点话,毕竟本人也算靠着趣味和致力闯入了编程这道大门,然而也深知功力不是很深,在各个方面的能力还都有待晋升,所以上面就只是总结下过后本人如何去学习编程,可能适宜你也可能不适宜你,毕竟每个人的学习、排汇、总结能力都不一样。 看书和官网文档先看入门书籍,让本人能看懂语法,看懂他人写的代码。 依照编程语言的语法,能写一些简略正确的逻辑代码。比方排序,数组的应用,循环,递归等。这里要留神,刚开始先看那些比拟薄一点,知识点比较简单的书籍,别一上来就整什么红宝石书籍,特地特地厚的,先让本人能对其编程产生趣味,不然刚开始就整厚书籍、难懂的点,可能学上3~5天本人就放弃了,没了当初的趣味。(切记学习须要循序渐进,不可急于求成。) 看官网文档,对于一些编程语言,官方网站都会有系列的入门教程,这个是很重要的,官网出的货色都是知识面很广,而且受众整体比拟广,所以很容易看懂和上手。 不论是看书还是官网教程都要及时的被动敲代码,对于书中的例子或官网教程中的案例,刚开始都须要本人在本地敲一篇,你能够先间接对照着实现,看本人是否胜利运行,之后在缓缓的了解和批改。在你实现的过程中你会发现,这个过程就是一个正反馈的过程。你会领会到当你把一个我的项目,一点一滴的敲进编译器,能胜利运行后果时那种骄傲,满足的情绪(要常常这么做,这一点一滴胜利就是你坚持下去的能源)。 看视频第二阶段能够看一些网上的编程视频,比方B站外面的教程或某些培训班的培训教程(网上能够找到)。目前很多程序员都在B站制作品质一流的编程系列教程,这些教程只有你用心去找,都能找到。 看视频的作用,能够增强你对知识点的了解,看他人是如何制作,解释一个知识点的,是否和你刚开始看书或看官网教程了解的一样。 看视频的过程中,你也须要对照着作者的实现办法本人在本地实现,有时候你会发现看作者实现立马就懂了,可是当你本人在本地实现的时候就会遇到各种各样的问题,兴许你可能破费1终日都无奈解决(哈哈哈,别丢失斗志,这很失常)。 过后我学习C#的时候,看的是黑马程序员的培训教材,有好几个G呢,过后如同是学长在淘宝购买的,咱们就一起看、了解、学习,不懂的中央就一起探讨,剖析。 做我的项目做我的项目是终极目标,只有做我的项目能力将那些零散的知识点汇总起来,造成一条线。做我的项目也能让本人有成就感,看到本人通过几个月一点一滴保持做进去的货色,就特地满足。 在学校的话,能够加入一些较量,比方大学生三创(翻新、创意、守业)较量,和同学一起依照一个ID来构思,实现一个我的项目。 在参加的过程中,你会发现以前学习的货色可能都或多或少有点用途,当你们一起拿着本人做的我的项目来加入较量,西装革履的给各级领导解说,展现的时候你会发现那是如许的骄傲与满足。 还有就是有些我的项目可能挣到外快,比方给学校某些院系做官网、和老师一起做课题钻研等。 写博客写博客,你可能会很纳闷,为什么我会把写博客独自放在这里。 上面的地址和截图是我过后学习C#时在博客园创立的博客,次要写一些知识点和汇总在编程过程中遇到的各种问题。 博客园:https://www.cnblogs.com/netxi... 当初回过头让我去看当初写的货色,感觉好童稚呀,都写的是些什么,如果让我当初从新些,我感觉能写出比那时好几万倍的博客,可是当初是当初,当初是当初。那些货色就在那里,它能证实我的学习过程,它能让我看到本人的以前。 写博客的益处特地多,如果你用心去注意,很多大佬都有写博客的习惯。 写博客它能让你整顿本人的思维,能够把想到的知识点条理化。能够记录重要的知识点,不便回顾。能够帮忙他人,当他人遇到和你一样的问题时,他就能参考你的解决办法。能够帮忙你找工作(简历中能够放本人博客的地址,面试官看到后会对你另眼相看)。取得心理成就,让本人更自信(博客就相当于本人的学习经验,越多本人的信息越足)。上面是我过后大三时候的简历,当初看来技能点还是满满的。 给大学生的寄语在这里,我以还算过来人的身份想给大学生们说说本人的心里话,你们目前真的能够说是比任何时候都有劣势,有工夫,有前景。 确立指标你首先须要找到本人的趣味点所在,目前你有机会和试错的老本去尝试各种各样你感觉本人想干的事件,你能够在不影响学习的状况下,尽可能多的让本人接触到各行各业。确定好本人未来想从事的事件后,提前去理解,筹备。 抓住工夫在大学你会领有大把大把的工夫,你能够打游戏,能够和舍友通宵开黑,能够去各个中央逛。然而你得放弃头脑清醒,你得把工夫也调配在你未来从事的事件上,你得提前去布局,你得让本人去成长。这里援用股神巴菲特说的一句话:"人生就像滚雪球,最重要之事是发现湿雪和长长的山坡。"。 ...

July 12, 2021 · 1 min · jiezi

关于c#:KIT305KIT607

KIT305/KIT607Assignment 2Implementation and Evaluation of a Mobile ApplicationJournal and Mood Tracking ApplicationDue DateThe assignment has three assessable components: The application code (worth 50%; pair-based work), due on Monday 20th May 2019 23:55 (week 12).A report (worth 40%; pair-based work), due on Monday 27th May 2019 23:55 (week 13).A demonstration (worth 10%; pair-based work), due in your scheduled tutorial (week 13).BackgroundIn assignment 1, your task was to design and prototype a native mobile application that allowed a user to create andmodify journal entries and track their mood.Your task for this assignment 2 is to now implement and evaluate a mobile Android or iOS application that providesthe functionality. An updated list of requirements and additional requirements is provided in this document.In the week 7 tutorial and in your own time, you will evaluate your different prototypes from assignment 1, todetermine which ones meet the usability goals discussed in this unit, and which should form the basis of yourassignment 2 code. Note that you are not required to match all of the functionality or visual style from assignment 1,but you should aim for some similarity between your assignment 1 and assignment 2 work. Functionality fromassignment 1 which is not specified in the “Code” section of this document is not required to be complete (forexample, if your assignment 1 featured a login page, you are not expected to make this function, but you areencouraged to include a non-functional version of this in the app if you have time).The goal of this assignment is to assess your ability to implement and evaluate mobile applications, and todemonstrate your understanding of the fundamentals of mobile device programming when applied to a practicalcontext.Group WorkThis is a pair-based assignment. Group members will need to agree on a target mobile OS (Android or iOS), and - aftersome usability think-aloud testing of the available prototypes – agree on the design that is to be implemented in code.You MUST have a partner chosen by your week 7 tutorial. If you have difficulties finding a partner, use thediscussion board on MyLO, and speak to other students looking for partners. You will be assigned to a group in week7.Use the following link to register your group (only one group member needs to do this):https://forms.gle/srcK1HwaHD6...Changes to group members MUST be approved by the Unit Coordinator. Late changes may not be approved.Group members should contribute equally to ALL components of the assignment (report, code, demonstration). Thisassignment will be subject to peer assessment, further details will be provided on MyLO. Code (50%)When you create your application, please use the following bundle identifier:au.edu.utas.username.assignment2(replace username with the username of one of the group members)The Android or iOS application that you are to implement must consist of at least:A way of entering a new journal entry and saving it.o At a minimum, journals should consist of a title, text, and a date of when the journal entry is saved. Extra meta-data such as location or tagged friends is not required to function correctly. Storing an image is considered an additional requirement (see below), not a core requirementfor this assignment.A way of showing a user’s past journal entries, and seeing more information about them.A way of editing and deleting previous journal entries.A way of selecting a current mood (this can be separate to creating journal entries or integrated into creating ajournal entry).A way of seeing how a user’s mood has changed in the past.o As a core requirement, this needs only to list past moods. Displaying a graph is considered anadditional requirement (see below).Data entered by the user should persist between runs of the application. You can use any data persistence methodtaught in this unit to accomplish this (e.g. SQLite, file writing, or SharedPreferences/UserPreferences). You should not“pre-fill” the database with user-entered information (such as existing journal entries), as the application shouldfunction (not crash) when the user has just opened the application for the first time. Remember that any testing datayou enter while developing your application will not be visible to your marker, as they will be installing a freshversion of your application on their emulator.An important feature of your application will be its usability, i.e. learnable, memorable, efficient, failure-resistant,forgiving, and satisfying. For the purpose of this assignment, particular emphasis will be placed on the “efficiency”aspect of usability. This means that if users choose to, they can create a short journal entry quickly, without too manyadditional steps.Aside from checking for functionality, your program will be assessed on its robustness (i.e. does the applicationcrash), usability, and aesthetics. You will not be assessed on your coding style, commenting, or indentation, howevergiven the scale of this application, you are advised to do this to assist in development.Remember to leave enough time to test your application on the School Mac computers. There may be some problemswhen you transfer a project from a personal laptop, so you need to leave enough time to solve these.When transferring an Android Studio project between computers, use the File -> Export to Zip… option to avoid errors.Additional requirementsTo gain higher marks, additional functionality should be added based upon the list below. Use the CRA below towork out how many marks you will get for completing these additional requirements.The user can store an image in their journal by taking a picture using the phone.The user can share a journal entry to another application (such as email, chat program). The shared data,should just be a plain-text version of the journal entry (you do not need to implement user accounts or a server forthis, see the lecture slides for information on sharing).The history of the user’s mood over time is shown using a graph.o You are allowed to use a 3rd-party plugin for drawing a graph for this part of the assignment (as longas you cite the author).If your assignment 1 prototype doesn’t include functionality for these requirements, you can still implement this byadding this to your application.Check the CRA at the end of this document to see the weighting of each component.Report (40%)You will have been reading many articles throughout the semester that report on the design, iterative refinement, andevaluation of new mobile and ubiquitous computing applications. Your readings have also been complemented byarticles on interaction design and discount usability methods. Accompanying the implementation of your applicationwill be a report outlining how you were able to apply the process of usability testing (and specifically think-aloudevaluation) to iteratively improve the design and usability of your application.You must write a report that is up to six (6) pages long (single-spaced, 10pt Times font). This page count includes figuresand tables, but excludes references.Your report should include the following sections:Introduction;Description of Application (including selected screenshots of lo-fi prototype and final application);(Usability) Methodology;Results;Discussion;Conclusions; andReferences.The Methodology section will outline the usability testing that was employed. It will also include details on how thetesting was conducted, including a description of the user participants and the test-tasks that were chosen for thethink-aloud evaluation (with a table showing tasks in rows and requirements in columns; see week 02 lecture). It isexpected that for a HD-level assignment, that you conduct iterative testing across at least three different prototypes.Check the CRA for what is required.The Results section will report the results of the usability testing. You should present a table of results, however onlysimple summary statistics are necessary; you are NOT expected to conduct accurate statistical analysis such as t-Tests,ANOVAs, or correlation). The purpose of this section is to show that you understand the testing process and haveconducted testing, not to get perfect usability scores. You will not be assessed on whether or not your results werepositive or not.The Discussion section will provide a self-assessment critique of performance on all of the above criteria, and willinclude a summary of the strengths and weaknesses of the application. You should refer to your results section toback up your statements with data.The report will also reference the set readings, lecture slides, and other literature and resources as appropriate tojustify decisions and provide background information. Demonstration (10%)In addition, you are required to demonstrate your application during the week 13 tutorial timeslot. Thedemonstrations will be limited to four (4) minutes total. All group members must participate in the demonstrations,and the 4-minute timeslots will be strictly enforced to ensure that all presentations are completed within the tutorialsession. The group demonstrations will need to:State the goals of the work for a broad public;Outline the design and testing that was conducted;Provide a convincing example of how a person would use the prototype (using either the emulator, a series ofscreenshots, or a physical device); andProvide convincing evidence that the application meets its goals.You may choose to create a PowerPoint presentation, but this is not necessary. You choose how to best communicatethe information above.If you choose to use a physical device for your demonstration, you must ensure you have tested your applicationthoroughly on the device prior to the demonstration. There will be no time during the tutorial to deploy to the device,you must do that at well before your allocated time.Assignment SubmissionThe following files must be submitted via MyLO before 23:55 on Monday 20th May (Week 12):One zip file, containing the project files. The zip filename should start with your UTAS account name (eithermembers’ name is fine).o For Android, you should create this ZIP file using the File -> Export to Zip option. Submit the ZIP filewhich is created.o For iOS, you need to find your .xcodeproj file and project folder in Finder, select them both, right-clickand choose “Compress”. Submit the ZIP file which is created.A group assignment coversheet (available from the ICT website):http://www.utas.edu.au/__data...The following files must be submitted via MyLO before 23:55 on Monday 27th May (Week 13):The group report, in PDF format, with a filename that starts with your UTAS account name (either members’name is fine).A group assignment coversheet (available from the ICT website):http://www.utas.edu.au/__data...Only one group member needs to submit these deliverables.Peer assessment submission items are to be announced on MyLO, and will be due in Week 13.Make sure to test your application on the University Mac machines in UC215 before submitting your assignment.Unzip your application to the desktop of a lab machine you haven’t used before. Test that application opens andcompiles in Android Studio/XCode, and runs in the emulator. Android applications will be tested using a Nexus 5Xemulator. iOS applications will be tested on an iPhone X simulator. (If you have errors attempting to run your project,be sure to try Build -> Clean Project, and running again). Plagiarism and Cheating:Practical assignments are used by the Discipline of ICT for students to both reinforce and demonstrate theirunderstanding of material which has been presented in class. They have a role both for assessment and for learning. Itis a requirement that work you hand in for assessment is your own.Working with othersOne effective way to grasp principles and concepts is to discuss the issues with your peers and/or friends. You areencouraged to do this. We also encourage you to discuss aspects of practical assignments with others. However, onceyou have clarified the principles of the problem, you must develop a solution entirely by yourself in your pair. Inother words; you and your partner must develop the application yourselves. You can discuss problems, but not sharesolutions. Assistance with solutions should be provided by staff.Cheating Cheating occurs if you claim work as your own when it is substantially the work of someone else.o This includes the use of third-party code from online resources. Cheating is an offence under the Ordinance of Student Discipline within the University. Furthermore, the ICTprofession has ethical standards in which cheating has no place. Cheating involves two or more parties.o If you allow written work, computer listings, or electronic versions of your code to be viewed,borrowed or copied by another student you are an equal partner in the act of cheating.o You should be careful to ensure that your work is not left in a situation where it may be used/stolenby others.Where there is a reasonable cause to believe that a case of cheating has occurred, this will be brought to the attentionof the unit lecturer. If the lecturer considers that there is evidence of cheating, then no marks will be given to any ofthe students involved and the case will be referred to the Head of Discipline for consideration of further action.Note: You are allowed to use a 3rd-party plugin for drawing a graph for the “mood tracking graph” part of thisassignment, and you may use the built-in SQLite implementation provided in tutorials. You may not use any other3rd-party plugin for any other part of this assignment.KIT305/KIT607 Assignment 2, Semester 1, 2019: Implementation and Evaluation of a Mobile ApplicationCriterion High Distinction (HD) Distinction (DN) Credit (CR) Pass (PP) Fail (NN)Code (50%; ILO2)Students are to produce a journal and mood trackingapplicationFunctionality – Journal List (30%):The application should have a way of showing auser’s past journal entries, and seeing moreinformation about them.The application should have a way of editing anddeleting previous journal entries.A custom layout/view for each entry is used,showing appropriate detail for a summaryscreen.The user can delete entries from the journal.The user can modify entries in the journalwithout needing to delete and re-add the items.The user can see more detail about a journalentry by navigating to a journal page andsensible choices were made for this.The interface for this part is highly intuitive;provides a consistent look and feel and usageacross all screens and is aesthetically pleasing.Application never crashes and has been testedthoroughly to avoid the existence of bugs.The journal can be filtered or searched in someway.A custom layout/view for each entry isused, showing appropriate detail for asummary screen.The user can delete entries from thejournal.The user can see the quantity required foreach item.The user can modify items in the listwithout needing to delete and re-add theitems.The user can see more detail about ajournal entry by navigating to a journalpage and sensible choices were made forthis.The interface for this part is intuitive andaesthetically pleasing.Application never crashes. There are onlyvery minor bugs (if any).A custom layout/view for each entry isused, showing details of each journalentry.The user can delete entries from thejournal.The user can see more detail about ajournal entry by navigating to a journalpage.The interface for this part is somewhatintuitive.There are only some bugs (if any) in theapplication and/or very rarely crashes.The title of each journalentry is listed.The user can deleteentries from the journal.A basic list view isprovided.The user can see moredetail about a journalentry by navigating to ajournal page.There are only somebugs (if any) in theapplication and/or rarelycrashes.The application does notcompile OR crashes onstart-up OR crashesfrequently.The user is unable to viewall journal entries or isunable to delete items.Functionality – Add Entry (15%):The application should have a way of entering anew journal entry and saving it.At a minimum, journals should consist of atitle, text, and a date of when the journal entryis saved.Users can add journal entries with a title, text,date, and sensibly-chosen additional metadata.The interface for this part is intuitive andaesthetically pleasing.Users can add journal entries with a title,text, and a custom date, and additionalmeta-data.The interface for this part is intuitive andaesthetically pleasing.Users can add journal entries with a title,text, and a custom date and time.The interface for this part is somewhatintuitive.There are only a few bugs (if any) in thispart of the app.Users can add journalentries with a title, text,and the current dateand time.There are only a fewbugs (if any) in this partof the app.The application does notcontain functionality to addjournal entries.Crashes prevent the userfrom adding journalentries.Functionality – Mood Tracking (15%):The application should have a way of selecting acurrent mood (this can be separate to creatingjournal entries or integrated into creating a journalentry).The application should have a way of seeing howa user’s mood has changed in the past.Users can enter their mood without having tocreate a journal entry. Users can select acustom mood (if appropriate to design of app).Users are able to see a history of their moods.Sensible choices are made for this display.The interface for this part is intuitive andaesthetically pleasing.Users can enter their mood without havingto create a journal entry.Users are able to see a history of theirmoods.The interface for this part is intuitive.Users can enter their mood without havingto create a journal entry.Users are able to see a history of theirmoods.The interface for this part is somewhatintuitive.There are only a few bugs (if any) in thispart of the app.Users can select amood when creating ajournal entry.There are only a fewbugs (if any) in thisscreen.The application providesno functionality forentering a mood, orcrashes prevent this partof the assignment beingassessed.Functionality – Data Persistence (15%):Data entered by the user should persist betweenruns of the application. You can use any datapersistence method taught in this unit toaccomplish this (e.g. SQLite, file writing, orSharedPreferences/UserPreferences).All data entered by the user persists betweenruns of the application.There are no noticeable bugs with thepersistence.The application functions when there is no datain the database.All data entered by the user persists between runs of the application.There are only some bugs (if any) with the persistence.The application functions when there is no data in the database.Most data entered bythe user persistsbetween runs of theapplication.There are only somebugs (if any) wheresome data does notsave.The applicationfunctions when there isno data in the database.Data does not persistwhen the application isclosed and re-opened. Usability - Efficiency (5%):The application should make it easy for user toquickly create short journal entries.The interface provides well-thought outfunctionality for making creation of journalentries a quick process.Basic functionality for making the creation of journal entries quickly is provided.There are no noticeable bugs with this implementation.Basic functionality formaking the creation ofjournal entries quickly isprovided.There are only somebugs with thisimplementation.The application does nothave any design decisionsthat make creating ajournal entry a quickprocess.Additional Functionality – Camera (10%):The application should allow the user to addimages to their journal entries.The application allows you to choose a photofrom the phone’s image gallery or camera andadd it to a journal entry.The image is displayed on the screen after theuser selected the image and throughout therest of the app.The image is saved to the database (either fileURL or image data is fine).There are no bugs with the camerafunctionality.The application allows you to choose a photo from the phone’s image gallery or cameraand add it to a journal entry.The image is displayed on the screen after the user selected the image and throughoutthe rest of the app.The image is saved to the database (either file URL or image data is fine).The application allowsyou to choose a photofrom the phone’s imagegallery or camera andadd it to a journal entry.The image is displayedon the screen after theuser selected theimage, but the imagedoes not persist onconsecutive runs.The application featuresno camera functionality orthe camera functionalitycrashes the app whentriggered.Additional Functionality – Sharing (5%):The application should allow the user to sharea journal entry to another application on thephone (such as email, chat program).The application allows you to use the OS’ builtinsharing functionality to share a text version ofa journal entry with all details (title, text, date,mood).Bonus (difficult): The user can share the text,AND image attached to the journal entry.The application allows you to use the OS’ built-in sharing functionality to share a textversion of a journal entry with most details.The application allowsyou to use the OS’ builtinsharing functionalityto share the title of thejournal entry.The application featuresno sharing functionality orthe sharing functionalitycrashes the app whentriggered.Additional Functionality – Mood Graph (5%):The application should display a graph toshowing the history of the user’s mood.The application shows a visually pleasing graphwhich uses data from the database (or otherdata persistence method).The graph can be filtered by different timeperiods.There are only a few bugs (if any) with thegraph functionality.The application shows a simple graphwhich uses data from the database (orother data persistence method).The graph can be filtered by different timeperiods.There are only some bugs (if any) with thegraph functionality.The application shows a simple graphwhich uses data from the database (orother data persistence method) but doesn’tchange when the user selects differenttime periods (but options still visually existto select a time period).There are only some bugs (if any) with thegraph functionality.The application shows asimple graph (that is notsimply a static image).The graph uses datafrom the database (orother data persistencemethod).The application does notfeature a graph or thegraph crashes the appwhen displayed or a staticimage is shown for thegraph. Report (40%; ILOs 1,3,4)Student is to create a report up to 6 pages long.Description of Application (25%; ILO3)The report will describe the functionality that hasbeen implemented; including images of the low-fiprototype and final application.All core functionality is explained in a concise,and well-written manner.Screenshots are clear and show the corefunctionality of the app.A reasoned description of how the finalapplication and lo-fi prototype differ isprovided.All core functionality is explained in awell-written manner.Screenshots are clear and show the corefunctionality of the app.A description of how the final applicationand lo-fi prototype differ is provided.All core functionality is explained.Screenshots show the core functionalityof the app.Report contains anoverview of thefunctionality and somescreenshots.Fails to provide adescription section.Methodology (25%; ILO4)The report will outline the usability testing thatwas conducted and the procedure in which itwas conducted.The employed usability testing is welldescribedand well founded; and accompaniedby clear usability test tasks and successrequirements.Choice of methodology is well-justified.At least three prototypes are evaluated overmultiple rounds of testing (i.e. iterative testing isconducted).The employed usability testing is welldescribed;and accompanied by clearusability test tasks and successrequirements.At least three prototypes are evaluated.The employed usability testing is welldescribed. ...

July 11, 2021 · 19 min · jiezi

关于c#:C实践笔记3数据类型之间的转换

前言无论是什么语言在开发的过程中,总会遇到不同类型数据之间的转换。C#也不例外,不过C#曾经帮咱们做好了一些转换的办法。 一.罕用的转换类。Encoding BitConverterConvertMarshal 二.数据转换1.byte[] => string 办法1:string str1 = System.Text.Encoding.Default.GetString(byteArray);办法2:string str2 = BitConverter.ToString(byteArray);转换后数据之间会带"-""31-32-33-34-35-36-37-38-39"办法3:string str3 = Convert.ToBase64String(byteArray); 办法4:string str4 = HttpServerUtility.UrlTokenEncode(byteArray);2.string => byte[] 办法1:byte[] byteArray = System.Text.Encoding.Default.GetBytes(str);办法2:byte[] byteArray = new byte[str.Length];for (int i =0;i<str.Length;i++){ byteArray[i] = Convert.ToByte(str[i]);}办法3;byte[] byteArray = Convert.FromBase64String(str);办法4:byte[] byteArray = HttpServerUtility.UrlTokenDecode(str);

June 30, 2021 · 1 min · jiezi

关于c#:ftp多线程上传下载以及断点续传

上传性能首先退出默认的配置项(这部分有对应的办法进行设置): 异步上传的局部代码 /// <summary> /// 异步上传 (多个文件最好用这个办法) 多线程时设置最大连接数 能够保障按队列先入先进来传输 此时不须要设置线程池中线程数量 /// </summary> /// <param name="fullName"></param> /// <param name="fileName">如果为空 默认取上传文件的名称</param> /// <param name="process"></param> public void AsynUpload(string fullName,string fileName, Func<FtpState, FtpState> process) { ManualResetEvent waitObject; FtpState state = new FtpState(); try { string _port = string.IsNullOrEmpty(port) ? "" : $":{port}"; fileName = string.IsNullOrEmpty(fileName) ? Path.GetFileName(fullName) : fileName; string ftpfullpath = $"ftp://{ipAddr}{_port }//{fileName}"; Uri target = new Uri(ftpfullpath); FtpWebRequest request = (FtpWebRequest)WebRequest.Create(target); request.Method = WebRequestMethods.Ftp.UploadFile; request.Credentials = new NetworkCredential(account, password); //request.KeepAlive = false;//是否保留连贯 设置了这个并不能失效 异步上传 request.UseBinary = true;// ftp默认是传输二进制 request.ServicePoint.ConnectionLimit = maxConnect;//最大连接数 // Store the request in the object that we pass into the // asynchronous operations. state.Request = request; state.FullName = fullName; state.ProcessCall = process; state.Operate = FtpOperate.UpLoad; //文件大小 FileInfo file = new FileInfo(fullName); state.Size = file.Length; // Get the event to wait on. waitObject = state.OperationComplete; // Asynchronously get the stream for the file contents. request.BeginGetRequestStream( new AsyncCallback(EndGetStreamCallback), state ); // Block the current thread until all operations are complete. waitObject.WaitOne(); // The operations either completed or threw an exception. if (state.OperationException != null) { if (UploadFail != null) { UploadFail.Invoke(state, state.OperationException); return; } throw state.OperationException; } else { if (UploadSuccess != null) { UploadSuccess.Invoke(state, state.StatusDescription); return; } } } catch (Exception ex) { if (UploadFail != null) { UploadFail.Invoke(state, ex); return; } } }利用多线程 异步上传: ...

June 26, 2021 · 2 min · jiezi

关于c#:Win32Api-使应用Always-on-top的几种方法

本文介绍几种使利用始终置于顶层的办法。 问题形容个别状况下,想要将利用置于顶层,设置其TopMost属性为true即可。对于多个设置了TopMost属性的利用,后激活的在下面。 但有的利用,比方全局的快捷操作工具条,它须要在所有利用之上,即便是设置了TopMost的利用。 解决思路留神:使某个利用永远不会被其它利用笼罩,这自身是个伪命题。因为如果有两个程序(A和B)这样做,拖动两个窗口使它们重叠,这两个窗口中的一个必须在另一个之上,这在逻辑上是互相矛盾的。 所以应该尽量避免这种状况,如果非要这样做,本文提供如下几种方法实现(不要将两个这样的利用重叠,否则会不停将置顶)。 首先,该应用程序须要设置其TopMost属性为true,这样一般窗口自身就会在它上面。本文次要探讨该窗口如何置于设置了TopMost属性的窗口之上。 计划一:捕捉WM_WINDOWPOSCHANGING音讯咱们晓得,应用Win32的SetWindowPos接口能够扭转窗口的Z Order,能够猜想,当另外一个利用置顶时,咱们的利用会扭转其Z Order,因而,咱们能够尝试捕捉WM_WINDOWPOSCHANGING音讯。 当窗口的大小、地位、Z序扭转时,窗口会接管到WM_WINDOWPOSCHANGING音讯,咱们能够应用WndProc解决窗口音讯。当捕捉到该音讯时,咱们能够尝试将利用再次置顶。要害代码如下,测试可行,但不确定是否有副作用: /// <summary>/// 计划一:捕捉WM_WINDOWPOSCHANGING音讯,若无SWP_NOZORDER标记,则置顶/// </summary>private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled){ switch (msg) { case Win32Api.WM_WINDOWPOSCHANGING: Win32Api.WINDOWPOS wp = (Win32Api.WINDOWPOS)Marshal.PtrToStructure( lParam, typeof(Win32Api.WINDOWPOS)); if ((wp.flags & Win32Api.SWP_NOZORDER) == 0) _ = SetTopMostLater(); // 不应用弃元编译器会收回正告 break; } return IntPtr.Zero;}private async Task SetTopMostLater(){ await Task.Delay(300); var interopHelper = new WindowInteropHelper(this); Win32Api.SetWindowPos(interopHelper.Handle, Win32Api.HWND_TOPMOST, 0, 0, 0, 0, Win32Api.TOPMOST_FLAGS);}计划二:循环置顶这个是比拟容易想到的一个计划,每隔肯定的工夫给利用设置下TopMost,该计划也是可行的: ...

June 25, 2021 · 1 min · jiezi

关于c#:C实践笔记1语言语法的使用

一.using static 1.C#6 using static新语法,能够简化前缀:例: 1 using static System.Console; //1.应用using static 2 3 namespace test 4 { 5 internal class Program 6 { 7 private static void Main(string[] args) 8 { 9 WriteLine("test"); //2.省去写Console.只是语法糖而已。 Console.WriteLine("test");10 }11 }12 }2.只能应用它的静态方法目前我在单例模式来用Instance,省略类名的前缀,这有点相似应用c++的宏定义来应用实例。

June 25, 2021 · 1 min · jiezi

关于c#:AgileConfig轻量级配置中心130发布支持多用户权限控制

AgileConfig 当初是设计给我本人用的一个工具,所以只设置了一道管理员明码,没有用户的概念。然而很多同学在应用过后都提出了须要多用户反对的倡议。整个团队或者整个公司都应用同一个明码来治理十分的不不便。 明天 AgileConfig 1.3.0 版本终于反对了多用户,以及简略的权限治理。用户跟权限的设计,在咱们开发管理系统的时候常常波及,最罕用的就是RBAC基于角色的权限管制。然而基于 AgileConfig 简略的理念,我略微简化了一点权限管制的功能设计,尽量的升高学习老本。 权限设计AgileConfig 的权限设计分为3个固定的角色: 超级管理员 超级管理员具备所有的管制权限,能够随便增加批改删除用户、利用、配置等等任何信息管理员 一般管理员能够新建利用,能够删除批改属于他的利用(利用的管理员属性为以后用户),以及该利用的配置项。管理员能够给任何用户受权所属利用配置项的管理权限。管理员能够增加批改删除角色为操作员的用户。操作员 操作员对利用没有任何管制权限,只能编辑或者公布下线通过管理员受权的利用的配置项。用户治理1.3.0 版本新增了多用户反对,那么用户治理是必须的性能。应用管理员级别的用户登录零碎后,点击“用户”=>“增加”按钮弹出用户新增界面。增加“用户名”、“明码”、团队等根本信息后,抉择用户的角色。点击“确定”新建用户。提醒胜利后就能够应用该用户登录零碎了。 利用受权1.3.0 版本反对对用户进行简略的受权治理。管理员在新建/编辑利用的时候能够保护一个管理员角色的用户。该账号对该利用具备齐全的管制权限。如果想要其它用户来编辑配置项,能够在受权界面进行受权。点击“受权”按钮弹出受权界面。权限分为两局部: 配置修改权:配置项的改删查权限配置高低线权:配置项的上线,下线权限。降级须要更新的数据库构造因为1.3退出了多用户的反对,新增了几张表跟字段,导致1.2降级1.3后程序运行报错的问题,须要手工调整表构造。 以下以mysql为例: agc_app表新增字段 app_admin varchar(36)新建agc_user表 CREATE TABLE `agc_user` ( `id` varchar(36) NOT NULL, `user_name` varchar(50) DEFAULT NULL, `password` varchar(50) DEFAULT NULL, `salt` varchar(36) DEFAULT NULL, `team` varchar(50) DEFAULT NULL, `create_time` datetime(3) NOT NULL, `update_time` datetime(3) DEFAULT NULL, `status` enum('Normal','Deleted') NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;新建agc_user_app_auth表 CREATE TABLE `agc_user_app_auth` ( `id` varchar(36) NOT NULL, `app_id` varchar(36) DEFAULT NULL, `user_id` varchar(36) DEFAULT NULL, `permission` varchar(50) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;新建agc_user_role表CREATE TABLE `agc_user_role` ( `id` varchar(36) NOT NULL, `user_id` varchar(50) DEFAULT NULL, `role` enum('SuperAdmin','Admin','NormalUser') NOT NULL, `create_time` datetime(3) NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;新建实现表跟字段后从新运行程序,会提醒重置超级管理员明码,之后就能够失常应用了。 ...

June 18, 2021 · 1 min · jiezi

关于c#:CSC-503SENG-474-2

Due on: Friday, JUNE 25th at 23:59 PSTWhere: Brightspace (https://bright.uvic.ca/d2l/ho...Instructions: >? You must complete this assignment entirely on your own. In other words, you should come upwith the solution yourself, write the code yourself, conduct the experiments yourself, analyze theresults yourself, and finally, write it all solely by yourself. The university policies on academicdishonesty (a.k.a. cheating) will be taken very seriously.? This does not mean that you need to go to a cave and self-isolate while preparing the assignment.You are allowed to have high-level discussions with your classmates about the course material.You are also more than welcome to use Piazza or come to office hours and ask questions. If indoubt, ask!— we are here to help.? If you are still stuck, you can use books and published online material (i.e., material that has afixed URL). However, you must explicitly credit all sources. You are also not allowedto copy-paste online materials. Woe to you if we catch you copy-pasting the uncreditedsources!– Why “if stuck”? Assignments are designed to develop your practical ML skills and makeyou strong. If you do the assignments well, the project will feel like a piece of cake. So,give your best. But, on the other hand, do not waste a whole week on a single question:if you are stuck on a question for a few days, ask (us) for help!? If you cannot make it until the deadline, you can use a maximum of two grace days perassignment. They are not free, though: each grace day comes with the 25% mark penalty(so submitting on Monday evening would reduce your score by 25%; submitting on Tuesdaywould further reduce it by 50%). No other accommodations will be provided unless explicitlyapproved by the instructor at least 7 days before the deadline.? These assignments are supposed to be really hard! Start early! You will need at leasttwo weeks to complete them!– If you do not feel challenged enough, please let me know, and I’ll think of something.? Remember: you will need to gather at least one-third of all points during the assign-ments to pass the course. If you don’t, you will get an F!? Make sure to follow the technical requirements outlined below. TAs have the full power to take50% off your grade if you disregard some of them.? Be sure that your answers are clear and easy for TAs to understand. They can penalize you ifyour solutions lack clarity or are convoluted (in a non-algebraic way), even if they are nominallycorrect.? We will try to grade your assignments within seven (7) days of the initial submission deadline.1? If you think there is a problem with your grade, you have one week to raise concerns after thegrades go public. Grading TAs will be holding office hours during those seven days to addressany such problems. After that, your grade is set in stone.Technical matters:? You must type up your analysis and solutions electronically and submit them as a self-containingJupyter notebook. Jupyter notebooks can contain code, its output, and images. They can alsobe used to type math and proofs in LATEX mode.– You must use LATEX mode to type formulas. Typing a?2=sqrt(3)+b1 is a pretty goodway to lose 50% of your grade for no good reason.? Each problem should be submitted as a separate file.? Each file should be named SurnameInitial N.ipynb, where N is two digit-padded problemnumber. Correct: SmithJ 05.ipynb. Incorrect: JohnSmith V12345 Problem 1.ipynb,prob1.pdf etc.? Zip all ipynb files and submit them as assignment1.zip to the Brightspace. Do not submitRAR, TAR, 7zip, SHAR and whatnot; just use good ol’ ZIP. Do not include other files.? The first cell of each Jupyter notebook must start with your name and V number. See theattached notebook for the details.? Your notebook should be organized sequentially according to the problem statement. Usesections (with the appropriate numbers and labels) within the notebook. Figures and relevantcode should be placed in the proper location in the document.? Notebook code must be runnable! Ideally, all answers will be the output of a code cell.? You must use Python 3 to complete the assignments. Feel free to use NumPy and pandas asyou find it fit. Use SciPy, scikit-learn, and other non-standard libraries only when explicitlyallowed to do so.? Your first executable cell should set the random seed to 1337 to ensure the reproducibility ofyour results. For Numpy/SciPy and pandas, use numpy.random.seed(1337); otherwise, userandom.seed(1337).? Document your code! Use either Markdown cells or Python comments to let us know what youhave done!? Finally, be concise! We do not appreciate long essays that amount to basically nothing.This assignment consists of 4 problems. Some are intended only for graduate students (thosetaking CSC 503), and are labelled as such. Some contain bonus sections: you can use bonus pointsto improve your overall homework score. Bonus points cannot be transferred to other assignments orthe final project. Any graduate-level problem counts as a bonus problem for undergraduate students.Some problems are purposefully open-ended. Whatever you think the correct answer is, makesure to support it with code and data.2Problem 1. The American Handwriting [40 points]The U.S. National Institute of Standards and Technology collected digital images of the digits writtenby high school students and the U.S. Census Bureau employees over the years. These images serveas the basis of the extremely popular MNIST dataset that is commonly used to benchmark machinelearning classifiers.Wouldn’t it be a good idea to play with that dataset? To do so, install Keras and load the MNISTdataset as follows:from keras.datasets import mnist(train_X, train_y), (test_X, test_y) = mnist.load_data()Now, let’s see how we can use neural networks to classify these images. ...

June 18, 2021 · 9 min · jiezi

关于c#:C中委托和事件的区别

C#中委托和事件的区别大抵来说,委托是一个类,该类外部保护着一个字段,指向一个办法。事件能够被看作一个委托类型的变量,通过事件注册、勾销多个委托或办法。本篇别离通过委托和事件执行多个办法,从中领会两者的区别。 □ 通过委托执行办法 class Program{ static void Main(string[] args) { Example example = new Example(); example.Go(); Console.ReadKey(); }}public class Example{ public delegate void DoSth(string str); internal void Go() { //申明一个委托变量,并把已知办法作为其构造函数的参数 DoSth d = new DoSth(Print); string str = "Hello,World"; //通过委托的静态方法Invoke触发委托 d.Invoke(str); } void Print(string str) { Console.WriteLine(str); }}以上, ○ 在CLR运行时,委托DoSth实际上就一个类,该类有一个参数类型为办法的构造函数,并且提供了一个Invoke实例办法,用来触发委托的执行。○ 委托DoSth定义了办法的参数和返回类型○ 通过委托DoSth的构造函数,能够把合乎定义的办法赋值给委托○ 调用委托的实例办法Invoke执行了办法 但,实际上让委托执行办法还有另外一种形式,那就是:委托变量(参数列表) public class Example{ public delegate void DoSth(object sender, EventArgs e); internal void Go() { //申明一个委托变量,并把已知办法作为其构造函数的参数 DoSth d = new DoSth(Print); object sender = 10; EventArgs e = new EventArgs(); d(sender, e); } void Print(object sender, EventArgs e) { Console.WriteLine(sender); }}以上, ...

June 12, 2021 · 2 min · jiezi

关于c#:C-学习笔记-6委托

委托是c#最重要的个性之一,c#前面所有的个性根本都是建设在委托的根底之上。1.c#的委托是什么c# 中的委托能够了解为函数的一个包装,C#中的函数已参数的形式进行传递,这绝对与C++中的函数指针。 委托的定义和办法的定义相似,在定义后面加上delegate关键字。举例: class Program { delegate void RunCmd(); // 申明委托类型 static RunCmd runcmd1; // 申明委托对象变量 static RunCmd runcmd2; // 申明委托对象变量 static RunCmd runcmd3; // 申明委托对象变量 public static void RunCmdExecute() { Console.Write("execute"); } public void RunCmdPause() { Console.Write("Puase"); } static void Main(string[] args) { runcmd1 = new RunCmd(RunCmdExecute);//创立委托对象,静态方法 //runcmd1 = RunCmdExecute; // 快捷语法集体不倡议应用 runcmd1 = new RunCmd(new Program().RunCmdPause);//创立委托对象,实例办法 //runcmd1 += new Program().RunCmdPause; // 快捷语法 runcmd1(); // 留神只会输入最初一个“pause” // 组合委托 runcmd1 = RunCmdExecute; runcmd2 = new Program().RunCmdPause; runcmd3 = runcmd1 + runcmd2; runcmd3(); // 输入 “executePuase” Console.Read(); } }委托的调用除了像办法(函数一样)还有一种是应用委托的Invoke办法。举例:runcmd1.Invoke(); //invoke翻译为征引(某人、某实践、实例等作为反对);留神调用委托不能为空,否则会引发异样。 ...

June 11, 2021 · 1 min · jiezi

关于c#:设计模式抽象工厂

设计模式之形象工厂上一篇咱们学习了简略工厂,晓得简略工厂是创立不同类的中央,那么这些工厂是如何创立得呢?随着咱们业务逻辑的减少,可能须要好多这种简略工厂,咱们不可能每一个都去被动创立,尽管说这样也能够实现,然而却不优雅而且前期维护者分不清批改重点,导致牵一发而动全身。 接下来学习如何创立通过一种形式去创立简略工厂,那么即便须要很多工厂,也能够通过这种形式去创立,缩小代码的耦合,使其内聚性更高。 形象工厂与工厂办法都为了解决接口抉择问题,然而实现上,形象工厂是一个核心工厂,用于创立其它工厂的模式。 不同的实现服务(类/Server)在局部办法上是不同的,因而须要做一个接口适配,这个适配类就相当于工厂中的工厂,用于创立把不同的服务形象为对立的接口做雷同的业务。 Demo业务: 假设当初目前有两个物流公司A,B,他们都有发货,取货的业务,同时公司A,B都能够自主的去进行各自不同品种的发货和取货,也就是说能够自定义。如果这有这两个公司那么很简略,咱们能够应用简略工厂,新创建两个工厂就能够解决,然而如果是10个或者50个公司,那么咱们创立工厂就有点不适合,这个时候就得应用形象工厂。 形象工厂定义的形象工厂都是抽象类,定义了发货,取货的形象办法,返回的也是抽象类。 /// <summary> /// 形象工厂 /// </summary> public abstract class AbstractFactory { /// <summary> /// 发货 /// </summary> /// <returns></returns> public abstract ASendGood SendGood(); /// <summary> /// 收货 /// </summary> /// <returns></returns> public abstract AGetGood GetGood(); } /// <summary> /// 取货 抽象类 /// </summary> public abstract class AGetGood { public abstract void GetGood(); } /// <summary> /// 发货 抽象类 /// </summary> public abstract class ASendGood { public abstract void SendGood(); } /// <summary> /// 公司A形象工厂 /// </summary> public class CompanyAAbstractFactory : AbstractFactory { public override AGetGood GetGood() { return new CompanyAGetGood(); } public override ASendGood SendGood() { return new CompanyASendGood(); } } /// <summary> /// 公司B的形象工厂 /// </summary> public class CompanyBAbstractFactory : AbstractFactory { public override AGetGood GetGood() { return new CompanyBGetGood(); } public override ASendGood SendGood() { return new CompanyBSendGood(); } } public class CompanyAGetGood : AGetGood { public override void GetGood() { Console.WriteLine("公司A 取货"); } } public class CompanyASendGood : ASendGood { public override void SendGood() { Console.WriteLine("公司A 发货"); } } class CompanyBGetGood : AGetGood { public override void GetGood() { Console.WriteLine("公司B 取货"); } } class CompanyBSendGood : ASendGood { public override void SendGood() { Console.WriteLine("公司B 发货"); } } 定义完形象工厂及各自的抽象类,接下来就是调用了。 ...

June 6, 2021 · 2 min · jiezi

关于c#:设计模式简单工厂

工厂模式工厂模式:顾名思义就是使得这个类的作用和工厂一样,生产产品,在这里应用,咱们就是生产类。工厂模式就是生产类,创立类的模式。 其在父类中提供一个创建对象的办法,容许子类决定实例化对象的类型。 代码绑定着具体类会导致代码更软弱,更不足弹性,不易扩大,批改艰难。 针对接口编程,能够隔离掉当前零碎可能产生的一大堆扭转,易于扩大。 用于解决扭转,并帮忙咱们“找出会变动的方面,把它们从不变的局部分离出来” Demo比方当初有一个物流公司,之前业务很繁多,只做陆上物流,随着工夫的推移,市场的变动,也有了海上物流,那么如何设计出一种实现形式来应答这种在业务逻辑上的不确定性,如果前面在减少一种地面物流,那么将如何设计呢。 如何只有路上物流和海上物流,咱们能够只在独自的类中各自申明下,前面通过if/eles形式来判断是那个物流,从而去实现它即可。这样做没有问题,能够解决业务下面所面临的问题,然而确不是软件开发中最好的实现形式,如果你通过if/eles来实现,那么它们的耦合度太高,前期如果陆上物流产生批改,会导致批改的中央过多,且不易于扩大。 简略实现逻辑 /// <summary> /// 海上物流 /// </summary> public class AtSeaLogistics { /// <summary> /// 海上发货 /// </summary> public void SendSeaGoods(string goodName) { Console.WriteLine("海上 Send:"+goodName); } } /// <summary> /// 海洋物流 /// </summary> public class LandLogistics { /// <summary> /// 海洋发货 /// </summary> public void SendLandGoods(string goodName) { Console.WriteLine("海洋 Send:"+goodName); } } static void Main(string[] args) { int logisticsType = 0; //默认为海洋运输 Console.WriteLine("开始发货"); if (logisticsType==0) { LandLogistics land = new LandLogistics(); land.SendLandGoods("Iphone 13"); } else { AtSeaLogistics atSea = new AtSeaLogistics(); atSea.SendSeaGoods("海鱼"); } Console.WriteLine("发货实现"); Console.ReadKey(); }运行后,因为是默认海洋发货,则调用海洋发货模块,进行发货。这其实是一种很简略,也是咱们目前写简略逻辑最最罕用的形式,实现性能没有问题,可是这种实现形式存在很大的隐患和不可扩大,如果前期在须要增加一种运输形式,可能得须要在Main()办法中批改才行,运输形式和物流的耦合性过高,且不易扩大。 ...

June 6, 2021 · 2 min · jiezi

关于c#:设计模式总览

看到掘金的30天发文连更挑战,想试试本人到底能够间断保持几天,奖品不奖品的不重要,重在参加吗?接下来的30天里,我将率领大家一起学习设计模式,以前总感觉设计模式很简单,在个别的惯例编程中很少应用到,仔细阅读后发现,之前的想法是如许无知。如果一个编程人员想晋升本人,想让本人更加值钱,那么代码标准,设计模式这些术层面的知识点也是须要理解和把握的。 其实在日常的开发中,咱们或多或少都会应用到设计模式,只是大家不太分明而已。比方咱们常常应用到的单例模式,工厂模式等。 楼主次要从事C#开发,程序中举例的代码应用C#。设计模式总览(形象、封装、继承、多态)是面向对象(OO)的基本概念,OO准则时咱们的指标,设计模式是咱们的做法。设计模式总共有23种,从大的构造上进行划分,可分为3大类,顺次是创立型模式、结构型模式、行为模式。 创立型模式这类模式是创建对象的机制,能够晋升已有代码的灵活性和可服用性。 工厂办法形象工厂生成器原型单例 结构型模式介绍如何将对象和类组装成较大的构造,并同时放弃构造的灵便和高效。 适配器桥接组合装璜外观享元代理 行为模式这类模式负责对象间的高效沟通和职责委派。 责任链命令迭代器中介者备忘录观察者状态策略模版办法访问者 如果你只有一把铁锤,那么任何货色看上去都像钉子。那么咱们要致力让本人手里领有多个铁锤。最根底的,底层的模式通常被称为习用技巧,这类模式个别只能在一种编程语言中应用。 最通用的,高层的模式是架构模式,咱们能够在任何编程语言中应用这类模式,与其余模式不同,它们可用于整个应用程序的架构设计。 小寄语一个人的奋斗,像怀孕一样,日子久了,总会被看进去的。 人生短暂,我不想去谋求本人看不见的,我只想抓住我能看的见的。 我是哉说,感谢您的浏览,如果对你有帮忙,麻烦点赞,转发 谢谢。

June 5, 2021 · 1 min · jiezi

关于c#:ASPNET-Core-MVC-入门到精通-3-使用MediatR

ASP.NET Core MVC 入门到精通 - 3. 应用MediatR 环境: .NET 5ASP.NET Core MVC (project)1. MediatRMediatR .NET中的简略中介者模式实现,一种过程内消息传递机制(无其余内部依赖)。反对以同步或异步的模式进行申请/响应,命令,查问,告诉和事件的消息传递,并通过C#泛型反对音讯的智能调度。 Simple mediator implementation in .NETIn-process messaging with no dependencies.Supports request/response, commands, queries, notifications and events, synchronous and async with intelligent dispatching via C# generic variance. 另:中介者模式 - 定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合涣散,且能够独立地扭转它们之间的交互。中介者模式又叫调解模式,它是迪米特法令的典型利用。 2. 装置 & 配置对于.NET5 (.net core), 应用nuget 装置MediatR.Extensions.Microsoft.DependencyInjection. 配置: public void ConfigureServices(IServiceCollection services){ services.AddControllersWithViews(); services.AddMediatR(typeof(Startup));}3. MediatR音讯类型3.1. Notifications 告诉模式Notifications 告诉模式用于生产者发送告诉,消费者(能够多个)接管到告诉后,进行后续解决。例:一个APS.NET 页面,拜访时,发送Notifications告诉;消费者简略记录收到告诉的工夫。 3.1.1. 定义基于INotification的告诉类public class Ping : INotification { }3.1.2. 定义消费者(关注告诉的解决办法)public class Pong1 : INotificationHandler<Ping>{ public Task Handle(Ping notification, CancellationToken cancellationToken) { Debug.WriteLine($"Pong1, {DateTime.Now}"); return Task.CompletedTask; }}public class Pong2 : INotificationHandler<Ping>{ public Task Handle(Ping notification, CancellationToken cancellationToken) { Debug.WriteLine($"Pong2, {DateTime.Now}"); return Task.CompletedTask; }}3.1.3. 发送音讯告诉// 基于dotnet core的依赖注入,注入IMediator对象private readonly IMediator _mediator;public HomeController(ILogger<HomeController> logger, IMediator mediator){ _logger = logger; _mediator = mediator;}public async Task<IActionResult> IndexAsync(){ // e.g. 拜访首页时,发送告诉 await _mediator.Publish(new Ping()); return View();}3.1.4. 输入Pong1, 5/27/2021 4:37:18 PMPong2, 5/27/2021 4:37:18 PM3.2. Request/Response 申请响应模式request/response用于命令和查问的场景。 ...

May 28, 2021 · 2 min · jiezi

关于c#:Winform窗体圆角以及描边完美解决方案

圆角我的项目中须要把窗体的四角改为圆角,winform窗体的圆角不是很好设置或者说绘制。在网上查找了很多计划,最终找到了一种完满解决方案。 在网上材料中罕用的是都是重绘窗体四角。然而采纳的形式不一样最初的成果也不一样同时代码量带来的体力劳动也是不一样的。 第一种计划:重写OnPaint或者再窗体的Paint事件中实现重绘。 这种计划有一个显著的毛病是软件运行时会引起窗体的闪动,这种计划绘制的圆角有肯定的纹刺,圆角不润滑。 第二种计划:采纳Win32 API重绘 这种计划是比拟完满的计划,没有计划一中的毛病。代码如下。 public partial class FrmLogin : Form, ILoginView { private ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); public FrmLogin() { InitializeComponent(); Load += FrmLogin_Load; SetFormRoundRectRgn(this, 5); //设置圆角 } private void FrmLogin_Load(object sender, EventArgs e) { this.BackColor = ColorTranslator.FromHtml("#FF5DB3AB"); //171, 179, 93 BackgroundImage = ImageHelper.GetImage("Login\\login_bg.png"); }}/// <summary> /// 设置窗体的圆角矩形 /// </summary> /// <param name="form">须要设置的窗体</param> /// <param name="rgnRadius">圆角矩形的半径</param> public static void SetFormRoundRectRgn(Form form, int rgnRadius) { int hRgn = 0; hRgn = Win32.CreateRoundRectRgn(0, 0, form.Width + 1, form.Height + 1, rgnRadius, rgnRadius); Win32.SetWindowRgn(form.Handle, hRgn, true); Win32.DeleteObject(hRgn); }using System;using System.Collections.Generic;using System.Linq;using System.Runtime.InteropServices;using System.Text; namespace UClass.View.Login{ public class Win32 { #region Window Const public const int WM_ERASEBKGND = 0x0014; public const int WM_LBUTTONDOWN = 0x0201; public const int WM_LBUTTONUP = 0x0202; public const int WM_LBUTTONDBLCLK = 0x0203; public const int WM_WINDOWPOSCHANGING = 0x46; public const int WM_PAINT = 0xF; public const int WM_CREATE = 0x0001; public const int WM_ACTIVATE = 0x0006; public const int WM_NCCREATE = 0x0081; public const int WM_NCCALCSIZE = 0x0083; public const int WM_NCPAINT = 0x0085; public const int WM_NCACTIVATE = 0x0086; public const int WM_NCLBUTTONDOWN = 0x00A1; public const int WM_NCLBUTTONUP = 0x00A2; public const int WM_NCLBUTTONDBLCLK = 0x00A3; public const int WM_NCMOUSEMOVE = 0x00A0; public const int WM_NCHITTEST = 0x0084; public const int HTLEFT = 10; public const int HTRIGHT = 11; public const int HTTOP = 12; public const int HTTOPLEFT = 13; public const int HTTOPRIGHT = 14; public const int HTBOTTOM = 15; public const int HTBOTTOMLEFT = 0x10; public const int HTBOTTOMRIGHT = 17; public const int HTCAPTION = 2; public const int HTCLIENT = 1; public const int WM_FALSE = 0; public const int WM_TRUE = 1; #endregion #region Public extern methods [DllImport("gdi32.dll")] public static extern int CreateRoundRectRgn(int x1, int y1, int x2, int y2, int x3, int y3); [DllImport("user32.dll")] public static extern int SetWindowRgn(IntPtr hwnd, int hRgn, Boolean bRedraw); [DllImport("gdi32.dll", EntryPoint = "DeleteObject", CharSet = CharSet.Ansi)] public static extern int DeleteObject(int hObject); [DllImport("user32.dll")] public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam); [DllImport("user32.dll")] public static extern bool ReleaseCapture(); #endregion }}窗体和控件描边实现思路:在现有的窗体和控件的根底之上画一个比原来窗体和控件范畴大1的矩形,描边的宽度和色彩能够通过pen设置。具体代码如下 ...

May 25, 2021 · 2 min · jiezi

关于c#:Mybatis配置数据库连接

首先resources下的mybatis-config.xml<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"><!--外围配置文件--><configuration> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/ssms?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <mapper resource="cn/zmxy/dao/UsersMapper.xml"/> </mappers></configuration>pojo实现类层的Java类(对应数据库表),比方Users表public class Users { private int id; private String name; private String pwd; public Users(){}}dao层的映射xml和Interface接口UsersMapper.xml<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace 命名空间 保定一个对应的dao/mapper接口--><mapper namespace="cn.zmxy.dao.UsersMapper"> <select id="getUserList" resultType="cn.zmxy.pojo.Users"> SELECT * FROM ssms.users </select> <select id="getUserById" resultType="cn.zmxy.pojo.Users" parameterType="int"> SELECT * FROM ssms.users WHERE id = #{id} </select> <insert id="addUser" parameterType="cn.zmxy.pojo.Users"> INSERT INTO ssms.users (id, name, pwd) VALUES (#{id}, #{name}, #{pwd}) </insert> <update id="updateUser" parameterType="cn.zmxy.pojo.Users"> UPDATE ssms.users SET name = #{name}, pwd = #{pwd} WHERE id = #{id} </update> <delete id="deleteUser" parameterType="int"> DELETE FROM ssms.users WHERE id = #{id} </delete></mapper>UsersMapper.javapackage cn.zmxy.dao;import cn.zmxy.pojo.Users;import java.util.List;public interface UsersMapper { // 查问全副用户 public List<Users> getUserList(); // 依据ID查问用户 public Users getUserById(int id); // 增加用户 public int addUser(Users user); // 批改用户 public int updateUser(Users user); // 删除用户 public int deleteUser(int id);}写一个utils类,获取SqlSessionMyBatisUtils.javapackage cn.zmxy.utils;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import java.io.IOException;import java.io.InputStream;public class MyBatisUtils { private static SqlSessionFactory sqlSessionFactory; static { try { String resource = "mybatis-config.xml"; InputStream is = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); } catch (IOException e) { e.printStackTrace(); } } public static SqlSession getSqlSession() { return sqlSessionFactory.openSession(); }}最初就能够调用了,写一个test类UserMapperTest.javapackage cn.zmxy.dao;import cn.zmxy.pojo.Users;import cn.zmxy.utils.MyBatisUtils;import org.apache.ibatis.session.SqlSession;import org.junit.Test;import java.util.List;public class UserDaoTest { @Test public void test() { // 第一步,获取SqlSession对象 SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 第二步,执行SQL UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class); List<Users> userList = usersMapper.getUserList(); // 打印users for (Users users : userList) { System.out.println(users); } // 敞开SqlSession sqlSession.close(); } @Test public void getUserById() { // 第一步,获取SqlSession对象 SqlSession sqlSession = MyBatisUtils.getSqlSession(); UsersMapper mapper = sqlSession.getMapper(UsersMapper.class); Users user = mapper.getUserById(1); System.out.println(user); // 敞开SqlSession sqlSession.close(); } @Test public void addUser() { // 第一步,获取SqlSession对象 SqlSession sqlSession = MyBatisUtils.getSqlSession(); UsersMapper mapper = sqlSession.getMapper(UsersMapper.class); int num = mapper.addUser(new Users(0, "露露", "1234")); System.out.println("受影响行数:" + num); sqlSession.commit(); // 敞开SqlSession sqlSession.close(); } @Test public void updateUser() { // 第一步,获取SqlSession对象 SqlSession sqlSession = MyBatisUtils.getSqlSession(); UsersMapper mapper = sqlSession.getMapper(UsersMapper.class); int num = mapper.updateUser(new Users(3, "露露", "1234")); System.out.println("受影响行数:" + num); sqlSession.commit(); // 敞开SqlSession sqlSession.close(); } @Test public void deleteUser() { // 第一步,获取SqlSession对象 SqlSession sqlSession = MyBatisUtils.getSqlSession(); UsersMapper mapper = sqlSession.getMapper(UsersMapper.class); int num = mapper.deleteUser(11); System.out.println("受影响行数:" + num); sqlSession.commit(); // 敞开SqlSession sqlSession.close(); }}

May 13, 2021 · 2 min · jiezi

关于c#:C-解决httplistener-querystring-中文乱码返回json中文格式乱码

解决httplistener querystring 中文乱码计划:在申请达到时候,获取Request.Url,返回get申请参数 键值对 public class RequestHelper { public static Dictionary<string, string> EncodeQueryString(Uri uri) { var ret = new Dictionary<string, string>(); var q = uri.Query; if (q.Length > 0) { foreach (var p in q.Substring(1).Split('&')) { var s = p.Split(new char[] { '=' }, 2); ret.Add(HttpUtility.UrlDecode(s[0]), HttpUtility.UrlDecode(s[1])); } } return ret; } }解决返回json中文格局乱码:对中午json字符串进行编码 HttpUtility.UrlDecode(“中文”); public class ResponseHelper { public static void Respose(HttpListenerResponse response, string jsonStr = "") { byte[] buffer = Encoding.UTF8.GetBytes(jsonStr); response.ContentLength64 = buffer.Length; response.ContentType = "application/json"; response.ContentEncoding = Encoding.UTF8; response.StatusCode = 200; Stream output = response.OutputStream; output.Write(buffer, 0, buffer.Length); //敞开输入流,开释相应资源 output.Close(); response.Close(); } }转载于:链接 ...

May 13, 2021 · 1 min · jiezi

关于c#:cmysql数据库备份还原

1:援用dllMySql.Data.dll, MySqlbackup.dll 2:建一个数据连贯动态类public static class mysql{public static string constr = "database=test;Password=明码;user ID=root;server=ip地址";public static MySqlConnection conn = new MySqlConnection(constr);}3:建winform窗体备份代码 DialogResult result = MessageBox.Show("备份门路默认在以后程序下", "提醒", MessageBoxButtons.YesNo, MessageBoxIcon.Question);if (result == DialogResult.Yes){string time1 = System.DateTime.Now.ToString("d").Replace("/", "-");string file = ".//mysql/" + time1 + "_test.sql";using (MySqlCommand cmd = new MySqlCommand()){using (MySqlBackup mb = new MySqlBackup(cmd)){cmd.Connection = mysql.conn;mysql.conn.Open();mb.ExportToFile(file);mysql.conn.Close();MessageBox.Show("已备份");}}}else{return;}还原代码 string file = textBox1.Text;if (file == ""){MessageBox.Show("不能为空");return;}DialogResult result = MessageBox.Show("确定还原吗?", "还原", MessageBoxButtons.YesNo, MessageBoxIcon.Question);if (result == DialogResult.Yes){try{using (MySqlCommand cmd = new MySqlCommand()){using (MySqlBackup mb = new MySqlBackup(cmd)){cmd.Connection = mysql.conn;mysql. conn.Open();mb.ImportFromFile(file);mysql. conn.Close();MessageBox.Show("已还原");}}}catch (Exception ex){MessageBox.Show(ex.Message);}}else{return;}

May 7, 2021 · 1 min · jiezi

关于c#:原创基于NET的轻量级高性能-ORM-RizXFramework

前言接上一篇《【原创】打造基于Dapper的数据拜访层》,Dapper在应酬多表自在关联、分组查问、匿名查问等利用场景时未免显得吃力,常常要手写SQL语句(或者用工具生成SQL配置文件)。试想一下,我的项目中整个DAL层都塞满了SQL语句,对于前期保护来说无异于天下大乱,这个坑谁踩谁晓得。本框架在API设计上最大水平地借鉴 EntityFramework 的写法,洁净的实体,丝滑的增删改查,持重的导航属性,另外还反对链式查问(点标记)、查问表达式、聚合查问等等。在实体映射转换层面,应用 Emit 来动静构建绑定指令,性能最大限度地靠近原生程度。 XFramework 亮点原生.NET语法,零学习老本反对LINQ查问、拉姆达表达式反对批量增删改查和多表关联更新反对 SqlServer、MySql、Postgre、Oracle,.NET Core最大亮点,真正反对一对一、一对多导航属性。这一点置信现有开源的ORM没几个敢说它反对的实体字段类型不用与数据库的类型统一反对长期表、表变量操作提供原生ADO操作其它更多亮点,用了你就会晓得性能看看与EntityFramework的性能比照,机器配置不同跑进去的后果可能也不一样,仅供参考。须要特地阐明的是EntityFramework是用了AsNoTracking的,不然有缓存的话就没有比拟的意义了 性能阐明1. 实体定义如果类有 TableAttribute,则用 TableAttribute 指定的名称做为表名,否则用类名称做为表名实体的字段能够指定 ColumnAttribute 个性来阐明实体字段与表字段的对应关系,删除/更新时如果传递的参数是一个实体,必须应用 [Column(IsKey = true)] 指定实体的主键ForeignKeyAttribute 指定外键,一对多外键时类型必须是 IList 或者 ListColumnAttribute.DataType 用来指定表字段类型。以SQLSERVER为例,System.String 默认对应 nvarchar 类型。若是varchar类型,须要指定[Column(DbType= DbType.AnsiString)]`[Table(Name = "Bas_Client")]``public partial class Client``{` `/// <summary>` `/// 初始化 <see cref="Client"/> 类的新实例` `/// </summary>` `public Client()` `{` `this.CloudServerId = 0;` `this.Qty = 0;` `this.HookConstructor();` `}` `/// <summary>` `/// 初始化 <see cref="Client"/> 类的新实例` `/// </summary>` `public Client(Client model)` `{` `this.CloudServerId = 0;` `this.Qty = 0;` `this.HookConstructor();` `}` `/// <summary>` `/// clientid` `/// </summary>` `[Column(IsKey = true)]` `public virtual int ClientId { get; set; }` `/// <summary>` `/// activedate` `/// </summary>` `public virtual Nullable<DateTime> ActiveDate { get; set; }` `/// remark` `/// </summary>` `[Column(Default = "'默认值'")]` `public virtual string Remark { get; set; }` `[ForeignKey("CloudServerId")]` `public virtual CloudServer CloudServer { get; set; }` `[ForeignKey("ClientId")]` `public virtual List<ClientAccount> Accounts { get; set; }` `/// <summary>` `/// 构造函数勾子` `/// </summary>` `partial void HookConstructor();``}`2. 上下文定义`1 SQLSERVER:var context = new SqlDbContext(connString);``2 MySQL:var context = new MySqlDbContext(connString);``3 Postgre:var context = new NpgDbContext(connString);``4 Oracle:var context = new OracleDbContext(connString);`3. 匿名类型`//// 匿名类``var guid = Guid.NewGuid();``var dynamicQuery =` `from a in context.GetTable<TDemo>()` `where a.DemoId <= 10` `select new` `{` `DemoId = 12,` `DemoCode = a.DemoCode,` `DemoEnum = Model.State.Complete,// 枚举类型反对` `};``var result = dynamicQuery.ToList();``// 点标记``dynamicQuery = context` `.GetTable<TDemo>()` `.Where(a => a.DemoId <= 10)` `.Select(a => new` `{` `DemoId = 12,` `DemoCode = a.DemoCode,` `DemoEnum = Model.State.Complete,// 枚举类型反对` `});``result0 = dynamicQuery.ToList();`4. 所有字段`// Date,DateTime,DateTime2 反对``var query =` `from a in context.GetTable<TDemo>()` `where a.DemoId <= 10 && a.DemoDate > sDate && a.DemoDateTime >= sDate && a.DemoDateTime2 > sDate` `select a;``var result1 = query.ToList();``// 点标记``query = context` `.GetTable<TDemo>()` `.Where(a => a.DemoId <= 10 && a.DemoDate > sDate && a.DemoDateTime >= sDate && a.DemoDateTime2 > sDate);``result1 = query.ToList();`5. 指定字段`// 指定字段``query = from a in context.GetTable<TDemo>()` `where a.DemoId <= 10` `select new TDemo` `{` `DemoId = (int)a.DemoId,` `DemoCode = (a.DemoCode ?? "N001")` `};``result1 = query.ToList();``// 点标记``query = context` `.GetTable<TDemo>()` `.Where(a => a.DemoCode != a.DemoId.ToString() && a.DemoName != a.DemoId.ToString() && a.DemoChar == 'A' && a.DemoNChar == 'B')` `.Select(a => new TDemo` `{` `DemoId = a.DemoId,` `DemoCode = a.DemoName == "张三" ? "李四" : "王五",` `});``result1 = query.ToList();`6.构造函数用过 EntityFramework 的同学都晓得,如果要通过构造函数的形式查问指定字段,除非老老实实从新定义一个新的实体,否则一个 “The entity or complex type cannot be constructed in a LINQ to Entities query“ 的异样马上给甩你脸上。XFramework 框架的这个用法,就是为了让你远离这会呼吸的痛!~ ...

April 25, 2021 · 12 min · jiezi

关于docker:Ubuntu系统Docker环境安装远程服务开启以及Portainer访问

以下内容有可能须要迷信上网能力做到。 开始我这里应用的环境是阿里云ecs,零碎是Ubuntu 20.04 64位 docker 装置如果零碎是第一次装置docker,简略来说只须要执行两条命令 1.sudo apt-get update2.sudo apt-get install docker-ce docker-ce-cli containerd.io装置教程地址docker 官网文档 在装置实现之后输出docker info 查看docker信息 在 Windows10 零碎中,能够下载 Docker Desktop on Windows官网地址 留神,在装置docker之前,须要先装置并开启WSL(Windows中的Linux子系统)官网地址 Portainer 装置Portainer 是一款开源容器管理工具官网文档官网地址 1.docker volume create portainer_data2.docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce装置实现后能够在浏览器输出http://localhost:9000 来拜访。在第一次进入时须要设定明码。 能够通过增加 Endpoints 来治理近程的 Docker 容器 点击菜单中的 Endpoints,抉择 Environment type 中的 Docker ,轻易输出一个当前你能认出来的 Name ,而后填入 Endpoint URL ,这个 URL 就是你要治理的近程服务器的地址或者域名。失常状况下,如果你的服务器没有开启 TLS 认证的话,就能够点击 Add endpoint 按钮了。 ...

April 24, 2021 · 2 min · jiezi

关于.net:2021-Top-100-CNET-Interview-Questions-And-Answers

https://jackniu81.github.io/2021/04/22/2021-Top-100-C-NET-Interview-Questions-And-Answers/1. What is the difference between “dispose” and “finalize” variables in C#?Dispose - This method uses interface – “IDisposable” interface and it will free up both managed and unmanaged codes like – database connection, files etc.Finalize - This method is called internally unlike Dispose method which is called explicitly. It is called by garbage collector and can’t be called from the code.2. What does “Jagged Arrays” mean?Answer: Jagged arrays refer to the array that has an element of type array. The dimensions and the sizes of the elements are different. An array of arrays is the other name of the jagged array. ...

April 22, 2021 · 29 min · jiezi

关于c#:C-计算字符串-SHA1

private string SHA1(string str){ byte[] strRes = Encoding.Default.GetBytes(str); HashAlgorithm iSha = new SHA1CryptoServiceProvider(); strRes = iSha.ComputeHash(strRes); StringBuilder enText = new StringBuilder(); foreach (byte iByte in strRes) { enText.AppendFormat("{0:x2}", iByte); } return enText.ToString();}

April 18, 2021 · 1 min · jiezi

关于c#:C-Stream-保存为文件

首先把 Stream 读到 byte 数组中,而后再用 BinaryWriter 写入到二进制文件: using System.IO;// streamFile 是 Stream 类型byte[] bytes = new byte[streamFile.Length];streamFile.Read(bytes, 0, bytes.Length);streamFile.Seek(0, SeekOrigin.Begin);FileStream fs = new FileStream("D:/a.jpg", FileMode.Create);BinaryWriter bw = new BinaryWriter(fs);bw.Write(bytes);bw.Close();fs.Close();

April 18, 2021 · 1 min · jiezi

关于c#:C-字符串转换为指定编码集的-base64-字符串

using System;using System.Text;string EncodeBase64(string code_type, string code){ string encode = ""; byte[] bytes = Encoding.GetEncoding(code_type).GetBytes(code); try { encode = Convert.ToBase64String(bytes); } catch { encode = code; } return encode;}EncodeBase64("utf-8", "abc123");

April 18, 2021 · 1 min · jiezi

关于c#:WinForm-DataGridView-控件中复选框的用法

System.Windows.Forms.DataGridView 是 .NET 窗体中提供的数据列表容器控件,就像是 MSSQL 中查问进去的行列,除了展现数据外还提供了编辑的性能。单元格内甚至可能退出特有的控件元素,如文本框,复选框,甚至是图片等,此文介绍了对于其中的复选框。 能够在窗体设计器中为 DataGridView 增加一个 ColumnType 值为 DataGridViewCheckBoxColumn 的列,这就是复选框列,复选框的 TrueValue 与 FalseValue 属性别离指选中与不选中状态的值,这两个值用于在前面判断选中状态。留神复选框与表格容器都不能为只读,否则鼠标点不动复选框。 判断表格中某一行是否被复选框选中,只需判断复选框的值,拿到其所在行号就可能晓得,代码如: for (int i = 0; i < dataGridView1.Rows.Count; i++){ if ((bool)dataGridView1.Rows[i].Cells[0].EditedFormattedValue == true) { Console.WriteLine(i + " selected"); }}代码中假如有个名为 dataGridView1 的表格,假如复选框是第一列,也就是每一行的第一个单元格,连贯起来就是遍历每一行的第一个单元格的值。 相干环境: .NET Framework 4.5

April 18, 2021 · 1 min · jiezi

关于c#:C-Dictionary-类型排序

在 C#.NET 中 System.Collections.Generic.Dictionary<TKey, TValue> 示意键和值的汇合,这个类型蕴含 OrderBy 办法用于排序,参数跟一个 lamda 表达式: // 这里假如 datas 为 Dictionary<string, string> 类型datas.OrderBy(x => x.Key).ToDictionary(x => x.Key, y => y.Value);// OrderByDescending 办法用于倒序应用时留神 ToDictionary 办法进行了一次类型转换;键类型如果是 string,那么将会依照字母程序进行排列,就像英文字典一样。 相干环境:.NET Framework 4.0

April 18, 2021 · 1 min · jiezi

关于c#:C-获取-WebBrowser-的内容源码

System.Windows.Forms.WebBrowser 是 WinForm 框架中提供的一个简略的 Web 浏览器组件,浏览器内核就是零碎自带的 IE 内核,版本依赖于 IE 的版本。假如有一个 Name 属性值为 webBrowser1 的 WebBrowser 控件,获取 Web 内容源码的办法如下: using System;using System.IO;using System.Windows.Forms;using System.Text;StreamReader getReader = new StreamReader(webBrowser1.DocumentStream, Encoding.GetEncoding(webBrowser1.Document.Encoding));string gethtml = getReader.ReadToEnd();getReader.Close();

April 18, 2021 · 1 min · jiezi

关于c#:C-获取某目录下的所有文件

using System;using System.Collections.Generic;using System.IO;private List<string> finded_files = new List<string>();private void RecursiveGetFiles(string parent_path){ string[] files = Directory.GetFiles(parent_path); foreach (string file in files) { // 这里能够进行文件的过滤,比方筛选指定的后缀 finded_files.Add(file); } string[] paths = Directory.GetDirectories(parent_path); foreach (string path in paths) { RecursiveGetFiles(path); }}

April 17, 2021 · 1 min · jiezi

关于c#:C-获取随机字符串

代码如下: using System;string GetRandomString(int length){ string result = ""; for (int i = 0; i < length; i++) { char c = (char)new Random(Guid.NewGuid().GetHashCode()).Next(97, 123); result += c; } return result;}length 参数就是指的字符串的长度;默认是返回随机小写英文字母,因为原理是根据的 ASCII 码表,所以只需稍加批改就能获取大写字母或者是数字。

April 17, 2021 · 1 min · jiezi

关于asp.net:ASPNET-应用程序缓存

ASP.NET 应用程序缓存的钻研;首先新建一个 Web 窗体,默认状况下就可能间接应用 Cache 对象来进行缓存的治理,但十分奇怪的是在 Visual Studio 中,当鼠标放到这个 Cache 上时会呈现来自 System.Web.Caching.Cache 的提醒,但实际上你不能间接应用这个命名空间加上类型来治理缓存,否则会呈现谬误;当本人键入这个命名空间加上 Cache 时只会呈现两个名字带 Expiration 的成员。来自两个不同命名空间的 Cache 对象治理缓存实际上成果是一样的,它们可能都间接作用于以后 Web 应用程序的缓存,如下代码: System.Web.HttpRuntime.Cache.Insert("cache_test", "System.Web.HttpRuntime.Cache success.<br/>", null, DateTime.Now.AddSeconds(5), System.Web.Caching.Cache.NoSlidingExpiration);System.Web.Caching.Cache cache = new System.Web.Caching.Cache();Response.Write(System.Web.HttpRuntime.Cache.Get("cache_test").ToString());Response.Write(Page.Cache.Get("cache_test").ToString());Response.Write(this.Cache.Get("cache_test").ToString());Response.Write(cache.Get("cache_test").ToString());cache.Insert("cache_test", "System.Web.Caching.Cache success.<br/>", null, DateTime.Now.AddSeconds(5), System.Web.Caching.Cache.NoSlidingExpiration);Response.Write(System.Web.HttpRuntime.Cache.Get("cache_test").ToString());Response.Write(Page.Cache.Get("cache_test").ToString());Response.Write(this.Cache.Get("cache_test").ToString());Response.Write(cache.Get("cache_test").ToString());//对象援用对于非动态的字段、办法或属性“Cache.Insert(...)”是必须的//System.Web.Caching.Cache.Insert("cache_test", "System.Web.Caching.Cache success.", null, DateTime.Now.AddSeconds(5), System.Web.Caching.Cache.NoSlidingExpiration);//对象援用对于非动态的、办法或属性“Cache.Get(...)”是必须的//Response.Write(System.Web.Caching.Cache.Get("cache_test").ToString());因为创立的 Web 窗领会默认继承自 System.Web.UI.Page,所以可能间接应用 Page 类提供的公开成员 Cache;System.Web.HttpRuntime.Cache 是动态类,也可能间接应用;就只有 System.Web.Caching.Cache 须要实例化后应用。 最终的输入后果如下: System.Web.HttpRuntime.Cache success.System.Web.HttpRuntime.Cache success.System.Web.HttpRuntime.Cache success.System.Web.HttpRuntime.Cache success.System.Web.Caching.Cache success.System.Web.Caching.Cache success.System.Web.Caching.Cache success.System.Web.Caching.Cache success. 相干环境:.NET Framework 4.0

April 17, 2021 · 1 min · jiezi

关于c#:CNET-PPT-导出为图片

在应用 Microsoft Office 组件之前我有理解过许多不须要依赖的形式,比方 Spire.Presentation,Aspose 这些组件,Spire.Presentation 应用起来很便捷,然而免费版有图片张数限度,Aspose 如同没有单纯的 PPT 解决,应该是把 PPT 先转为 PDF,再从 PDF 进行输入的。但毕竟是商业我的项目,免费问题是防止不了的,对于这些组件的开发商并不算大厂,所以什么破解、盗版的形式我都会间接回绝(集体认为应该尊重劳动成果),对于本人从底层解析 PPT 的难度过大,因为波及到解释类语言,即便费良久功夫解析进去也要思考平台兼容性,所以最终我还是抉择了 Microsoft Office。应用 Office 套件的毛病实际上也非常明显,像是体积太宏大,原本只须要这么一个小点的性能却要装置几个 GB 的多余部件,部署环境从此须要依赖 Windows + Office。不过倒是相比拟其它商业我的项目,Microsoft Office 能够不用激活就可能应用可编程的组件(过期后可能会存在一点小问题),这的确是一个比拟具备说服力的理由。性能的实现从代码上来看并不多: using Microsoft.Office.Core;using Microsoft.Office.Interop.PowerPoint;Application app = new Application();Presentation ppt = app.Presentations.Open(fileName, MsoTriState.msoTrue, MsoTriState.msoTrue, MsoTriState.msoFalse);int slideCounts = ppt.Slides.Count + 1;for (int i = 1; i < slideCounts; i++){ string picSavePath = "D:/filename_" + i + ".jpg"; ppt.Slides[i].Export(picSavePath, ".jpg");}ppt.Close();app.Quit();代码到这里实际上就曾经完了,增加的援用是 COM 程序集里的 Microsoft PowerPoint 15.0 Object Library 与 Microsoft Office 15.0 Object Library,具体的版本号视状况而定。尽管代码没有什么问题,或者本地调试也没有什么问题,然而部署到大多数的生产环境中多半是不能执行的,因为 COM 程序集的调用须要肯定的权限,如果某些中央的配置不当就可能会遇到各种各样的谬误,而且大多数的异样音讯可能也很难看出问题所在。我是把程序作为 ASP.NET 网站给部署到 IIS 上的,比方上面就是我遇到的各种异样: ...

April 17, 2021 · 1 min · jiezi

关于c#:C-发送邮件

这里以 QQ 邮箱的 SMTP 服务为例,写代码之前须要先进入 QQ 邮箱进行配置,开启 SMTP 服务,而后查看受权,拿到受权码,记录下 SMTP 服务器地址和端口,配置实现后才是写代码。.NET Framework 曾经对发送邮件相干的性能进行了整合,因而调用起来并不算麻烦: MailAddress sender = new MailAddress("发件人邮箱");MailAddress to = new MailAddress("收件人邮箱");// 邮件服务设置SmtpClient smtpClient = new SmtpClient();// SSL 和鉴权的配置是依据 QQ 邮箱配置的,不同 SMTP 服务器所要求的可能会不一样smtpClient.EnableSsl = true;smtpClient.UseDefaultCredentials = false;// 鉴权的格局是 QQ 邮箱规定的smtpClient.Credentials = new NetworkCredential("发件人邮箱", "受权码");smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;smtpClient.Host = smtpServer;smtpClient.Timeout = 5000;// 端口是 QQ 邮箱规定的,能够到 QQ 邮箱帮忙核心查找smtpClient.Port = 587;MailMessage mailMessage = new MailMessage(sender, to);mailMessage.Subject = "邮件题目";mailMessage.Body = "邮件内容";mailMessage.BodyEncoding = Encoding.UTF8;mailMessage.IsBodyHtml = true;// 最初发送smtpClient.Send(mailMessage);不同 SMTP 服务器所要求的参数可能会不一样,所以肯定要先看官网提供的文档,但基本上发邮件的代码都大同小异了。 ...

April 17, 2021 · 1 min · jiezi

关于c#:C-通过反射的方式调用方法

using System;using System.Reflection;using System.IO;// 读取 .dll 文件byte[] fileData = File.ReadAllBytes("D:\\file.dll");Assembly assembly1 = Assembly.Load(fileData);// 获取 TypeType type1 = assembly1.GetType("namespace.type");// 获取办法MethodInfo method = type1.GetMethod("method");// 创立一个实例object activator = Activator.CreateInstance(type1);// 执行办法并获取返回后果object result = method.Invoke(activator, null);载入程序集是通过读取为字节数组的形式,这样能够防止 Assembly.LoadFile 办法造成的 .dll 文件被占用问题,这里须要应用绝对路径;获取 Type 时须要在后面加上命名空间,获取办法只需提供办法名称即可;对于静态方法的调用能够不用应用 Activator 类创立实例,所以 Invoke 办法的第一个参数能够为 null,Invoke 办法的第二个参数是 object[] 类型,示意传递给该办法的参数汇合,办法被调用后返回的后果是以 object 类型保留的,在理论状况下当然还须要一个转换操作。

April 17, 2021 · 1 min · jiezi

关于windows:C-编写-Windows-服务应用程序

在 .NET Framework 平台中编写 Windows 服务 算是一件比拟容易的事件。首先关上 Visual Studio 创立一个名为 Windows 服务 的我的项目,创立后看到的是一个 .cs 文件的设计界面,用鼠标右键单击能够看到几个菜单,点击增加安装程序后又会转到另一个 .cs 文件的设计界面,这个界面上默认有两个组件,一个叫 serviceProcessInstaller1,另一个叫 serviceInstaller1,其中 serviceInstaller1 组件的属性窗口如下: Description 属性和 DisplayName 属性别离指服务的形容和名字,ServiceName 属性指服务的过程名字,StartType 属性指服务的启动类型,这里抉择 Automatic 的意思为主动启动;这里还会把 serviceProcessInstaller1 组件的 Account 属性批改为 LocalSystem,要不然等到装置服务的时候可能会呈现要求输出用户名和明码的对话框。 服务装置组件的配置曾经完了,当初转到服务的代码地位,还是在方才那个右键菜单地位,点击“查看代码”就能够看到服务要执行的代码,我编写如下代码: using System;using System.ServiceProcess;namespace WindowsService1{ public partial class Service1 : ServiceBase { public Service1() { InitializeComponent(); } System.Timers.Timer timer = new System.Timers.Timer(); protected override void OnStart(string[] args) { timer.Interval = 1000; timer.AutoReset = true; timer.Enabled = true; timer.Start(); timer.Elapsed += new System.Timers.ElapsedEventHandler(timertick); } private void timertick(object source, System.Timers.ElapsedEventArgs e) { System.IO.FileStream fs = new System.IO.FileStream("D:\\log.txt", System.IO.FileMode.Append); System.IO.StreamWriter sw = new System.IO.StreamWriter(fs); sw.WriteLine(DateTime.Now.ToString()); sw.Close(); fs.Close(); } protected override void OnStop() { } }}OnStart 办法中的代码会在服务启动时执行一次,所以这里我用了一个定时器有限执行;OnStop 办法中的代码会在服务进行时执行。服务程序编译后仍然会是 .exe 文件,只不过不可能间接运行,这里须要应用 .NET Framework 提供的程序来装置咱们编写的服务,装置服务的命令如下: ...

April 17, 2021 · 1 min · jiezi

关于c#:C-中-DateTime-的加减

在 .NET Framework 4.0 中,DateTime 类型与 DateTime 类型之间 不能进行加运算,然而能够进行减运算。两者相减后的后果可用 TimeSpan 类型存储,TimeSpan 类中具备间接获取减运算后果的成员,代码如下: using System;TimeSpan ts = Convert.ToDateTime("2019-11-15 14:00:00") - Convert.ToDateTime("2019-11-14 14:00:00");double days = ts.TotalDays;//天double hours = ts.TotalHours;//时double minutes = ts.TotalMinutes;//分须要留神的是值能够为正数。

April 17, 2021 · 1 min · jiezi

关于c#:C-for-与-foreach-循环的性能测试

测试的办法是用这两种循环形式遍历已知的汇合数据,应用的计时器是 Stopwatch 类,最初会在两个相应的文本框中输入工夫耗费,先间接贴出后果画面: 测试各执行了十次,其中右边的文本框是 for 语句的后果,左边的是 foreach 语句的后果,能够看出 foreach 语句在这个程序当中效率更高,上面是测试的局部代码: using System;using System.Diagnostics;using System.Collections.Generic;using System.Windows.Forms;private List<int> datas = new List<int>(100000000);for (int i = 0; i < 100000000; i++){ datas.Add(i);}// forprivate void normalFor(){ Stopwatch watch = new Stopwatch(); watch.Start(); int result = 0; for (int i = 0; i < datas.Count; i++) { result += datas[i]; } watch.Stop(); textBox1.Text += watch.ElapsedMilliseconds.ToString() + "ms\r\n";}// foreachprivate void forEach(){ Stopwatch watch = new Stopwatch(); watch.Start(); int result = 0; foreach (int i in datas) { result += i; } watch.Stop(); textBox2.Text += watch.ElapsedMilliseconds.ToString() + "ms\r\n";}这个程序中拿了较为极其的数据来作测试,最终也只是达到了不到 200 ms 的差距,实际上在应用环境中两者之间的性能差异基本上能够忽略不计,还是就思考开发者的应用习惯和上下文环境来进行抉择。 ...

April 16, 2021 · 1 min · jiezi

关于c#:C-对象与-JSON-字符串的相互转换

程序应用 .NET Framework 提供的 JavaScriptSerializer 类进行序列化和反序列化操作,须要援用 .NET Framework 中的 System.Web.Extensions 程序集。对于间接进行 DataTable 类型对象的转换会呈现 “序列化类型为“System.Reflection.RuntimeModule”的对象时检测到循环援用” 这一异样,所以程序中对 DataTable 类型的转换作了独自解决,当然只是从 DataTable 转换为 JSON 时作了解决,如果将 JSON 字符串转换为 DataTable 仍然会失败,我想通常状况下的前后端交互只须要用到 DataTable 到 JSON 的转换就差不多了吧,上面是实现: using System;using System.Web.Script.Serialization;using System.Data;using System.Collections.Generic;// 对象转换为 JSON 字符串string ObjectToJSON(object _obj){ try { JavaScriptSerializer serializer = new JavaScriptSerializer(); if (_obj is DataTable) { DataTable dt = (DataTable)_obj; List<Dictionary<string, object>> rows = new List<Dictionary<string, object>>(); Dictionary<string, object> row; foreach (DataRow dr in dt.Rows) { row = new Dictionary<string, object>(); foreach (DataColumn dc in dt.Columns) { row.Add(dc.ColumnName, dr[dc]); } rows.Add(row); } return serializer.Serialize(rows); } return serializer.Serialize(_obj); } catch { return "{}"; }}// JSON 字符串转换为相应类型的对象T JSONToObject<T>(string _json){ try { JavaScriptSerializer serializer = new JavaScriptSerializer(); return serializer.Deserialize<T>(_json); } catch { return default(T); }}相干环境:.NET Framework 4.0 ...

April 16, 2021 · 1 min · jiezi

关于c#:C-图片转换为-base64-字符串

程序的根本转换方法是应用 .NET Framework 提供的 base64 转换器,其中用到了 ImageFormatGuidToString 办法,这个办法是为了确保图像保留到内存流的时候用的是失常的图像格式。如果是应用 Image 类创立的新图像,那么它的 RawFormat 参数值并不是惯例的格局,这个时候如果应用这种图像格式保留到内存流中会导致失败,具体的异样音讯大略是 “值不能为 null。参数名:encoder”,所以这个中央在图像保留到内存流之前首先查看了现有图像的格局。转换后的 base64 字符串是没有标识头的,要在 HTML 标签中显示须要本人加上头部,如 “data:image/png;base64,...”: using System;using System.Drawing;using System.Drawing.Imaging;using System.IO;// Image 对象转换为 base64 字符串string ImageToBase64(Image _image){ MemoryStream ms = new MemoryStream(); try { if (ImageFormatGuidToString(_image.RawFormat) == null) { _image.Save(ms, ImageFormat.Png); } else { _image.Save(ms, _image.RawFormat); } byte[] arr = new byte[ms.Length]; ms.Position = 0; ms.Read(arr, 0, (int)ms.Length); return Convert.ToBase64String(arr); } catch { return null; } finally { ms.Close(); }}// base64 字符串转换为 Image 对象Image Base64ToImage(string _base64){ byte[] arr = Convert.FromBase64String(_base64); MemoryStream ms = new MemoryStream(arr); Bitmap bmp = new Bitmap(ms); try { Image result = new Bitmap(bmp.Width, bmp.Height); Graphics g = Graphics.FromImage(result); g.DrawImage(bmp, 0, 0); g.Dispose(); return result; } catch { return null; } finally { bmp.Dispose(); ms.Close(); }}// 用于查看图像格式string ImageFormatGuidToString(ImageFormat _format){ if (_format.Guid == ImageFormat.Bmp.Guid) { return "bmp"; } else if (_format.Guid == ImageFormat.Gif.Guid) { return "gif"; } else if (_format.Guid == ImageFormat.Jpeg.Guid) { return "jpg"; } else if (_format.Guid == ImageFormat.Png.Guid) { return "png"; } else if (_format.Guid == ImageFormat.Icon.Guid) { return "ico"; } else if (_format.Guid == ImageFormat.Emf.Guid) { return "emf"; } else if (_format.Guid == ImageFormat.Exif.Guid) { return "exif"; } else if (_format.Guid == ImageFormat.Tiff.Guid) { return "tiff"; } else if (_format.Guid == ImageFormat.Wmf.Guid) { return "wmf"; } else { return null; }}相干环境:.NET Framework 4.0 ...

April 16, 2021 · 1 min · jiezi

关于c#:C-执行基本的-Web-POST-请求

这个办法用的是浏览器最传统的表单提交形式 application/x-www-form-urlencoded,这个办法可用到两种组合数据的办法,一是间接传递数据到 data 对象,二是组合键/值对类型的数据到 parameters 对象,办法内会优先选择 data 对象所带的参数,如果想要以键/值对的形式传递,将 data 对象的值填为空字符串即可,这两个二选一;获取返回值的办法中退出了异样解决,这使得即便在遇到申请服务器产生服务器谬误(如 404 等 HTTP 状态)时也可失常取得返回的异样信息,应用时须要留神超时值与字符编码集: using System;using System.Net;using System.Text;using System.IO;using System.Collections.Generic;public string HttpPost(string url, string data = "", IDictionary<string, string> parameters = null, int timeout = 5000, CookieCollection cookies = null){ HttpWebRequest request = null; request = WebRequest.Create(url) as HttpWebRequest; request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; request.Timeout = timeout; if (cookies != null) { request.CookieContainer = new CookieContainer(); request.CookieContainer.Add(cookies); } if (!string.IsNullOrWhiteSpace(data)) { byte[] databytes = Encoding.UTF8.GetBytes(data); using (Stream stream = request.GetRequestStream()) { stream.Write(databytes, 0, databytes.Length); } } else if (parameters != null && parameters.Count != 0) { StringBuilder buffer = new StringBuilder(); int i = 0; foreach (string key in parameters.Keys) { if (i > 0) { buffer.AppendFormat("&{0}={1}", key, parameters[key]); } else { buffer.AppendFormat("{0}={1}", key, parameters[key]); i++; } } byte[] kvdata = Encoding.UTF8.GetBytes(buffer.ToString()); using (Stream stream = request.GetRequestStream()) { stream.Write(kvdata, 0, kvdata.Length); } } try { using (Stream stream = request.GetResponse().GetResponseStream()) { using (StreamReader reader = new StreamReader(stream, Encoding.UTF8)) { return reader.ReadToEnd(); } } } catch (WebException ex) { using (Stream stream = ex.Response.GetResponseStream()) { using (StreamReader reader = new StreamReader(stream, Encoding.UTF8)) { return reader.ReadToEnd(); } } }}相干环境:.NET Framework 4.0 ...

April 16, 2021 · 1 min · jiezi

关于c#:C-执行-Web-GET-请求

这里留神超时值不要设置得太小,不然会引发 System.Net.WebException 异样,值以毫秒为单位,个别设置为 5000 以上: using System;using System.Net;using System.IO;using System.Text;string GetHttpResponse(string url, int timeout){ HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Method = "GET"; request.Timeout = timeout; HttpWebResponse response = (HttpWebResponse)request.GetResponse(); Stream responseStream = response.GetResponseStream(); StreamReader streamReader = new StreamReader(responseStream, Encoding.UTF8); string resString = streamReader.ReadToEnd(); streamReader.Close(); responseStream.Close(); return resString;}相干环境:.NET Framework 4.0

April 16, 2021 · 1 min · jiezi

关于c#:比尔盖茨都不知道的cwinfrom的陷阱坑

1.datagridview外面的坑:1.1、界面UI图 如图,标段和分包名称都是个下拉框,原本我写的办法是初始化加载数据只查问了标段,通过点击表白这个单元格的事件触发了查问分包名称,从而造成分包的下拉框,但这样的弊病就是经常报这个(分包名称字段)dataGridViewColum的数据报错,出错就是绑定数据异样,这个并不是数据格式的问题。这让人很苦恼。这个相似的代码在这里能找到:https://juejin.cn/post/687517... ,如果您有幸看到这篇文章,肯定不要被原文蒙蔽啊。 1.2 办法改良 这里的查问我就是一开始加载时,把所有信息全副查问进去,这样一一对应关系也有了,也不至于一开始加载联动关系对应不上。 这不是是点击标会联动分包名称的下拉,也不必多说了。 2.label文字换行的坑: 2.1 原本这个需要是我想做个文章列表页,用label用习惯了,一开始如图区域的控件 我用的是label,而后文字不换行被遮蔽了,百度了一下,好多反复文章都是说怎么调属性的诸如此类,如图: 反正最终款式很丑,无论如何,行的文字对不齐。 前面应用的是RichText这个控件,暗藏横向滚动条和背景,这样就行了。就如同html的p标签款式个别,我这么平平淡淡的说,也只是跟大家讲 思维很重要,不要陷入思维误区,有些货色的应用不是你想想的那样,应该多多尝试,还有就是想吐槽一下,为什么百度能搜出这么多不靠谱的文章,反复不说 还排名这门靠前。 本文来源于:程序员ken,专属平台有csdn、思否(SegmentFault)、 简书、 开源中国(oschina)、掘金,转载请注明出处。

April 4, 2021 · 1 min · jiezi

关于linq:在C中编写LINQ查询

本文介绍能够用于在 C# 中编写 LINQ 查问的三种办法: 应用查问语法。应用办法语法。联合应用查问语法和办法语法。上面的示例演示应用后面列出的每种办法的一些简略 LINQ 查问。 备注这些查问对简略的内存中汇合进行操作;然而,根本语法等同于在 LINQ to Entities 和 LINQ to XML 中应用的语法。示例 - 查问语法编写大多数查问的举荐形式是应用查问语法创立查问表达式 。上面的示例演示三个查问表达式。第一个查问表达式演示如何通过利用蕴含 where 子句的条件来筛选或限度后果。它返回源序列中值大于 7 或小于 3 的所有元素。第二个表达式演示如何对返回的后果进行排序。第三个表达式演示如何依据某个键对后果进行分组。此查问基于单词的第一个字母返回两个组。 // Query #1.List<int> numbers = new List<int>() { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };// The query variable can also be implicitly typed by using varIEnumerable<int> filteringQuery = from num in numbers where num < 3 || num > 7 select num;// Query #2.IEnumerable<int> orderingQuery = from num in numbers where num < 3 || num > 7 orderby num ascending select num;// Query #3.string[] groupingQuery = { "carrots", "cabbage", "broccoli", "beans", "barley" };IEnumerable<IGrouping<char, string>> queryFoodGroups = from item in groupingQuery group item by item[0];留神,查问类型为 IEnumerable。能够应用 var 编写所有这些查问,如上面的示例所示: ...

March 31, 2021 · 2 min · jiezi

关于c#:C-笔记

C# 类型零碎

March 29, 2021 · 1 min · jiezi

关于c#:C队列Queue介绍和用法详细指南

队列用于示意对象的先进先出(FIFO)汇合。当你须要我的项目的先进先出拜访时应用。这是非通用类型的汇合, 在System.Collections命名空间。依据程序的须要, 它用于创立一直增长的动静汇合。在队列中, 你能够存储雷同类型和不同类型的元素。通常, 当你以与存储在汇合中雷同的形式拜访该信息时, 队列是有用的, 它是存储数据的长期存储。 下图阐明了Queue类的层次结构: 重要事项: Queue类实现了IEnumerable, ICollection和可克隆接口。当你在列表中增加我的项目时, 该我的项目称为入队.当你删除我的项目时, 该我的项目称为出队.队列承受null作为援用类型的有效值。将元素增加到队列后, 将通过重新分配外部数组来依据须要主动减少容量。在队列中, 容许你存储反复的元素。队列的容量是队列能够包容的元素数。如何创立队列?队列类有四个构造函数用于创立队列的办法如下: Queue():此构造函数用于创立Queue类的实例, 该实例为空并具备默认的初始容量, 并应用默认的增长因子。Queue(ICollection):此构造函数用于创立Queue类的实例, 该实例蕴含从指定汇合中复制的元素, 具备与复制的元素数量雷同的初始容量, 并应用默认的增长因子。Queue(Int32):此构造函数用于创立Queue类的实例, 该实例为空并具备指定的初始容量, 并应用默认的增长因子。Queue(Int32, Single):此构造函数用于创立Queue类的实例, 该实例为空并具备指定的初始容量, 并应用指定的增长因子。让咱们看看如何应用Queue()构造函数创立一个队列: 第1步:包含零碎汇合借助using关键字在程序中命名空间。 语法如下: using System.Collections;第2步:应用Queue类创立一个队列, 如下所示: Queue queue_name = new Queue();第3步:如果要在队列中增加元素, 请应用入队在队列中增加元素的办法。如下例所示。 例子: // C# program to illustrate queueusing System;using System.Collections; public class GFG { static public void Main() { // Create a queue // Using Queue class Queue my_queue = new Queue(); // Adding elements in Queue // Using Enqueue() method my_queue.Enqueue( "GFG" ); my_queue.Enqueue(1); my_queue.Enqueue(100); my_queue.Enqueue( null ); my_queue.Enqueue(2.4); my_queue.Enqueue( "Geeks123" ); // Accessing the elements // of my_queue Queue // Using foreach loop foreach ( var ele in my_queue) { Console.WriteLine(ele); } }}输入如下: ...

March 28, 2021 · 3 min · jiezi

关于c#:分支语句C如何使用Switch语句用法示例

在C#中, Switch语句是多路分支语句。它提供了一种无效的形式, 能够依据表达式的值将执行转移到代码的不同局部。开关表达式是整数类型, 例如int, char, byte或short, 或者是枚举类型, 或者是字符串类型。查看表达式的不同状况, 而后执行一次匹配。 语法如下: switch (expression) {case value1: // statement sequence break;case value2: // statement sequence break;...case valueN: // statement sequence break;default: // default statement sequence}switch执行流程图: 要记住的要点: 在C#中, 不容许反复的大小写值。开关中变量的数据类型和案例的值必须是同一类型。案例的值必须是常量或文字。不容许应用变量。break in switch语句用于终止以后序列。默认语句是可选的, 它能够在switch语句中的任何地位应用。不容许应用多个默认语句。例子: // C# program to illustrate// switch case statementusing System; public class GFG { // Main Method public static void Main(String[] args) { int nitem = 5; switch (nitem) { case 1: Console.WriteLine( "case 1" ); break ; case 5: Console.WriteLine( "case 5" ); break ; case 9: Console.WriteLine( "case 9" ); break ; default : Console.WriteLine( "No match found" ); break ; } }}输入如下: ...

March 28, 2021 · 3 min · jiezi

关于c#:快速了解C-80中可空引用类型Nullable-reference-type语言特性

Visual C# 8.0中引入了可空援用类型(Nullable reference type),通过编译器提供的弱小性能,帮忙开发人员尽可能地躲避由空援用带来的代码问题。这里我大抵介绍一下可空援用类型的根本内容。刚开始接触这个语言个性的时候,可能会不太容易了解。援用类型原本不就是能够为空(null)的么,为啥还要特地地引入“可空援用类型”的概念呢?其实这是从编译器的角度要求开发人员在编程的时候就思考某个变量是否有可能为空,从而尽可能地缩小由空援用所带来的代码谬误。假如有如下类: class Student{ public Student(string name, DateTime dayOfBirth) => (Name, DayOfBirth) = (name, dayOfBirth); public string Name { get; set; } public DateTime DayOfBirth { get; set; } public string Notes { get; set; }}此类定义了一个“学生”实体的根本信息,为了简化起见,这里只列出了须要探讨的几个属性: Name:学生姓名DayOfBirth:学生生日Notes:对学生信息的一些备注假如咱们有两个操作:在所有学生中,找出所有具备备注信息的学生,以及对所有学生按姓名排序,在C#中很容易应用Linq来实现: var studentsHasNotes = students.Where(s => s.Notes.Length > 0);以及: var orderedStudents = students.OrderBy(s => s.Name);到目前为止没啥问题,程序可能失常运行。然而认真进行代码审查不难发现,在获取所有具备备注信息的学生的代码中(也就是下面第一段代码中),有可能呈现空援用的异样,因为对于一个“学生”实体来说,它的Notes属性是有可能为null的。当初咱们关上“可空援用类型”这一语言个性,打开方式次要有两种:能够在我的项目级别,编辑csproj我的项目文件进行设置,也能够通过#nullable预编译指令来实现: 编辑csproj我的项目文件,退出<Nullable>enable</Nullable>即可: 通过#nullable预编译指令来实现,只须要在代码中须要的中央退出#nullable指令即可: 启用“可空援用类型”这一语言个性之后你会发现,在下面的Student类的构造函数处呈现了一个正告,提醒在构造函数执行实现时,不可为空的“Notes”属性须要有一个不为空的值,倡议将其设置为可空的string类型。为什么编译器仅提醒Notes有可能为空,而不是Name属性呢?因为构造函数中曾经为Name赋值了,因而,对于任何一个Student的对象,Name不可能为空,而Notes则不然。 Name不可能为空?它不是string类型么?万一在代码中它为空了怎么办?别急,编译器是不会容许呈现这种状况的: 在此,咱们将Notes属性设置为string类型,于是你会发现,位于构造函数上的正告信息曾经没有了,因为咱们容许Student对象能够没有Notes数据,但在“找出所有具备备注信息的学生”这一操作时,又会呈现正告,提醒说Notes有可能为空: 于是,你会发现,在启用了可空援用类型的语言个性后,咱们就须要认真考查Student类型中的每一个援用类型的属性,看它在理论利用中是否有可能为空,如果可能为空,则用可空援用类型来定义属性,之后编译器就会帮忙你来剖析哪些地方有可能存在空援用。 在下面的“找出所有具备备注信息的学生”例子中,如果你感觉Notes必定不会为空,那么也能够应用“!”操作符来笼罩编译器的正告信息,比方: 当初风行的.NET开源框架基本上都曾经反对了可空援用类型了,而且如果你是一名开源框架的开发人员,也强烈建议在你的框架中启用这一语言个性来尽可能地防止空援用问题。比方,如果你在代码中启用了可空援用类型个性,那么当你从Newtonsoft.Json的JsonConverter类继承时,你会发现,你必须应用可空援用类型的函数重载: ...

March 24, 2021 · 1 min · jiezi

关于c#:技术分享PPT整理二C常用类型与数据结构

这篇博客起源于我对Dictionary、List、ArrayList这几个类区别的好奇,过后在革新公司的旧零碎,发现很多中央应用了ArrayList,但咱们平时用的多是泛型汇合List<T>,革新的时候要全副替换成泛型汇合,本来我对于这几个汇合类就有些疑难,所以略微做了些功课。 装箱与拆箱在开始剖析汇合类之前先简略说下装箱拆箱的概念,在理论的开发中,兴许咱们很少提到这个概念,但它实际上遍布咱们的开发过程,并且对性能有很大的影响,首先来理解一下什么是装箱和拆箱: 装箱和拆箱是值类型和援用类型之间互相转换是要执行的操作。装箱在值类型向援用类型转换时产生拆箱在援用类型向值类型转换时产生int i = 123;object o = (object)i; // 将int转object,产生装箱int j = (int)o; // 从object转回原来的类型,解除装箱通过下面的阐明和例子能够看到,这是一个很简略的概念,实际上就是在咱们进行类型转换时产生的一种状况,但如果咱们再深刻一些能够从数据结构的角度来更清晰地解释这个问题,先看上面两个例子: 值类型int i = 123;object o = i; // 装箱会把i的值拷贝到oi = 456; // 扭转i的值// i的变动不会影响到o的值Console.WriteLine("{0},{1}", i,o); 原始值类型和装箱的对象应用不同的内存地位,因而可能存储不同的值。 援用类型public class ValueClass{ public int value = 123; public void Test() { ValueClass b = new ValueClass(); ValueClass a = b; b.value = 456; Console.WriteLine("{0},{1}", a.value, b.value); }} 两个变量指向同一块内存数据,当一个变量对内存区数据扭转之后,另一个变量指向的数据当然也会扭转。 简略地说,值类型的赋值相当于间接将物品交给另一个人,而援用类型的赋值相当于将一个寄存了物品的地址复制给另一个人,每当有人来找的时候,再依据地址去找到物品,地址没有产生扭转的状况下,将外面的物品替换,那么前面所有顺着线索找过去的人拿到的都是被替换的物品。如果以数据结构的常识来看,援用类型和值类型就是别离寄存在堆和栈外面的数据。 堆与栈咱们把内存分为堆空间和栈空间: 线程堆栈:简称栈Stack,栈空间比拟小,然而读取速度快托管堆:简称堆Heap,堆空间比拟大,然而读取速度慢栈存储的是根本值类型,堆存储的是new进去的对象。援用类型在栈中存储一个援用,其理论的存储地位位于托管堆。 值类型:在C#中,继承自System.ValueType的类型被称为值类型,次要有以下几种:bool、byte、char、decimal、double、enum、float、Int、long、sbyte、short、struct、uint、ulong、ushort 援用类型:以下是援用类型,继承自System.Object:class、interface、delegate、object、string 装箱(Boxing)咱们再回头看方才例子的装箱操作,能够用很清晰的图片来表白: int i = 123;object o = (object)i; ...

March 22, 2021 · 2 min · jiezi

关于qt5:项目实战QtC轨道交通行业高性能高流畅度模拟火车移动图像控件

若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/114866533长期继续带来更多我的项目与技术分享,征询请加QQ:21497936、微信:yangsir198808 红瘦子(红模拟)的博文大全:开发技术汇合(蕴含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬联合等等)继续更新中…(点击传送门) 开发专栏:商业我的项目实战 需要 高清线阵相机扫描火车并主动切割单节车厢实现图像合成。通过视频图像处理组件晦涩模仿火车行驶整个过程的视频图像: 1.模仿火车通过时的滚动图像,图像次要以两侧和顶部图像的预览为主; 2.模仿的图像数据可反对手动调节速度变量使火车滚动速度变动; 3.模仿的图像反对倒退滚动,并在点击暂定后图像可通过鼠标拖拽能实现后退或后退成果。 4.反对上部、中部、下部图片独自增加等(间接设置图片列表) 5.反对上部、中部、下部一次性增加一列操作(每次增加) 6.反对清空已增加图片清空操作 7.反对模仿挪动速度的设置、获取、减速、加速、速度反向等操作 8.反对模仿火车播放器操作:播放、暂停、复原、进行等操作 9.反对左部区域百分比回调,区域宽度可设置百分比,回调优先级:底部 > 左部 > 右部 10.已高度性能显示优化,逻辑优化,较Qt+GPU更加晦涩播放(轨道交通行业内相干技术人员技术支持), 技术要求 1.视频图像播放晦涩、无卡顿、无丢帧景象。 2.视频图像播放速度调节适度安稳无丢帧卡顿。 3.视频图像导入图片数量横向不低于100张,导入过程无卡顿。 4.视频图像窗口缩放(小窗口、全屏切换)不影响图像播放晦涩度、无卡顿、丢帧。 Demo: Qt (录屏只有30fps,截取为gif后显示卡顿,可下载打包的四个版本进行终端测试). 下载体验地址 CSDN(粉丝免积分下载):https://download.csdn.net/download/qq21497936/15837003 QQ群:1047134658(点击“文件”搜寻“train”,群内与博文同步更新) Demo C ; C#接口源代码 若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/114866533

March 16, 2021 · 1 min · jiezi

关于.net:进击吧Blazor系列入门教程-第一章-7图表

《进击吧!Blazor!》是自己与张善友老师单干的Blazor零根底入门教程视频,此教程能让一个从未接触过Blazor的程序员把握开发Blazor利用的能力。视频地址:https://space.bilibili.com/48...Blazor WebAssembly 是单页利用 (SPA) 框架,用于应用 .NET 生成交互式客户端 Web 利用,采纳 C# 代替 JavaScript 来编写前端代码 本系列文章因篇幅无限,省略了局部代码,残缺示例代码:https://github.com/TimChen44/...作者:陈超超Ant Design Blazor 我的项目贡献者,领有十多年从业教训,长期基于.Net技术栈进行架构与开发产品的工作,现就职于正泰团体。邮箱:timchen@live.com欢送各位读者有任何问题分割我,咱们共同进步。图表的作用我就不扯了,想要让零碎高大上就少不了它,作为一个加分项,咱们天然也要给咱们ToDo援用来一波。 Chart控件抉择目前还没有比拟优良的Blazor原生Chart控件,这也是咱们未来须要晋升Blazor生态的重要工作之一。 然而无需悲观,Blazor反对C#调用JS,反之亦可,所以社区中有不少通过此技术对现有JS版本的Chart控件二次分装的Blazor组件可用。 这里我就举荐自己封装G2Plot后的Blazor组件ant-design-charts-blazor。 文档地址:https://ant-design-blazor.git...源码地址:https://github.com/ant-design...技术实现形式介绍:https://zhuanlan.zhihu.com/p/...https://www.bilibili.com/vide... 革新ToDo援用组件通过命令或可视化界面为ToDo.Client增加AntDesign.Charts组件$ dotnet add package AntDesign.Charts 在 wwwroot/index.html(WebAssembly) 或 Pages/_Host.razor(Server) 中引入动态文件:<script src="https://unpkg.com/@antv/g2plot@latest/dist/g2plot.js"></script><script src="_content/AntDesign.Charts/ant-design-charts-blazor.js"></script>在 _Imports.razor 中退出命名空间@using AntDesign.Charts将Charts命名空间退出全局援用,领有应用时省略残缺命名门路的益处,然而请留神当Chart中的组件与其余组件重名时,不管Chart组件还是其余组件都须要补上残缺命名门路,思考到Chart应用的页面并不多,所以自己的习惯不会将他退出 _Imports.razor中。统计页咱们用柱状图做一个每日代办事项数量统计图 ChartAmountDto.cs在ToDo.Shared我的项目中创立用于显示数据的实体。 public class ChartAmountDto{ public string Day { get; set; } public string Type { get; set; } public int Value { get; set; }}Day字段存储日期文本。Type存储重要度信息,蕴含“一般”,“重要”两个值,图表中也是用这个进行分组显示。Value存储具体的数值。 ChartController.cs在ToDo.Server我的项目新建ChartController控制器,用于提供图表所需的数据。 [ApiController][Route("api/[controller]/[action]")]public class ChartController{ TodoContext Context; public ChartController(TodoContext context) { Context = context; } //每日待办数量 public List<ChartAmountDto> GetAmountDto() { return Context.Task.GroupBy(x => new { x.PlanTime, x.IsImportant }).Select(x => new ChartAmountDto() { Day = x.Key.PlanTime.ToString("yy-MM-dd"), Type = x.Key.IsImportant ? "一般" : "重要", Value = x.Count(), }).ToList(); }}通过对打算日期和重要度进行分组,而后对分组后果进行计数,接口返回的局部数据结构如下 ...

March 14, 2021 · 2 min · jiezi

关于c#:C-学习笔记二-C-的基础语法

C# 是由 C 语言和 C++ 演变而来,属于 C 语言系,并兼容了 许多 Java 的个性,C/C++,Java 程序员能够很容易了解 C# 的内容。 标识符和关键字标识符是程序员一块内存起的一个名字(这块内存能够是一个变量,一个类或一个办法)。在 C# 中,标识符必须是一个残缺的词汇(即标识符中不能蕴含空格),由 Unicode 字符组成( C 语言只能蕴含英文字母,数字和下划线),并且以字母或下划线结尾。 关键字对于编译器而言有着非凡的含意,它通常用于指定编译器的零碎行为。关键字都被保留,这意味着你不能在标识符中应用它们。 不过,有的人天生就喜爱打破常规,他就要用关键字作为标识符,能够,微软也为这类人提供了办法,那就是在关键字前加上一个 @ 。这样他就能够被用作标识符了,比方: int @int = 0;这样你就定义了一个名字叫做 int 的 int 类型(整型)的变量。 须要留神的是,加了 @ 的标识符和未加 @ 的标识符含意完全相同。字面值,标点符号和运算符字面值是嵌入到程序中的原始的数值。 标点符号帮忙划分程序的构造。 操作符转换以及连贯所有的表达式。 正文C# 反对单行和多行正文。别离用符号 // 和 /**/ 示意,这一点与 C 语言齐全一样。

March 10, 2021 · 1 min · jiezi

关于c#:理解ASPNET-Core-中的WebSocket

在本文中,咱们将具体介绍RFC 6455 WebSocket标准,并配置一个通用的.NET 5应用程序通过WebSocket连贯与SignalR通信。 咱们将深刻底层的概念,以了解底层产生了什么。 对于WebSocket 引入WebSocket是为了实现客户端和服务器之间的双向通信。HTTP 1.0的一个痛点是每次向服务器发送申请时创立和敞开连贯。然而,在HTTP 1.1中,通过应用放弃连贯机制引入了长久连贯(RFC 2616)。这样,连贯能够被多个申请重用——这将缩小提早,因为服务器晓得客户端,它们不须要在每个申请的握手过程中启动。 WebSocket建设在HTTP 1.1标准之上,因为它容许长久连贯。因而,当你第一次创立WebSocket连贯时,它实质上是一个HTTP 1.1申请(稍后具体介绍)。这使得客户端和服务器之间可能进行实时通信。简略地说,下图形容了在发动(握手)、数据传输和敞开WS连贯期间产生的事件。咱们将在前面更深刻地钻研这些概念。 协定中蕴含了两局部:握手和数据传输。 握手 让咱们先从握手开始。 简略地说,WebSocket连贯基于单个端口上的HTTP(和作为传输的TCP)。上面是这些步骤的总结。 服务器必须监听传入的TCP套接字连贯。这能够是你调配的任何端口—通常是80或443。客户端通过一个HTTP GET申请发动开始握手(否则服务器将不晓得与谁对话)——这是“WebSockets”中的“Web”局部。在消息报头中,客户端将申请服务器将连贯降级到WebSocket。服务器发送一个握手响应,通知客户端它将把协定从HTTP更改为WebSocket。客户端和服务器单方协商连贯细节。任何一方都能够退出。上面是一个典型的关上(客户端)握手申请的样子。 GET /ws-endpoint HTTP/1.1Host: example.com:80Upgrade: websocketConnection: UpgradeSec-WebSocket-Key: L4kHN+1Bx7zKbxsDbqgzHw==Sec-WebSocket-Version: 13留神客户端是如何在申请中发送Connection: Upgrade和Upgrade: websocket报头的。 并且,服务器握手响应。 HTTP/1.1 101 Switching ProtocolsUpgrade: websocketConnection: UpgradeSec-WebSocket-Accept: CTPN8jCb3BUjBjBtdjwSQCytuBo=数据传输 咱们须要了解的下一个要害概念是数据传输。任何一方都能够在任何给定的工夫发送音讯——因为它是一个全双工通信协议。 音讯由一个或多个帧组成。帧的类型能够是文本(UTF-8)、二进制和管制帧(例如0x8 (Close)、0x9 (Ping)和0xA (Pong))。 装置 让咱们付诸行动,看看它是如何工作的。 首先创立一个 ASP.NET 5 WebAPI 我的项目。 dotnet new webapi -n WebSocketsTutorialdotnet new slndotnet sln add WebSocketsTutorial当初增加SignalR到我的项目中。 dotnet add WebSocketsTutorial/ package Microsoft.AspNet.SignalR示例代码 咱们首先将WebSockets中间件增加到咱们的WebAPI应用程序中。关上Startup.cs,向Configure办法增加上面的代码。 在本教程中,我喜爱放弃简略。因而,我不打算探讨SignalR。它将齐全基于WebSocket通信。你也能够用原始的WebSockets实现同样的性能,如果你想让事件变得更简略,你不须要应用SignalR。 app.UseWebSockets(); 接下来,咱们将删除默认的WeatherForecastController,并增加一个名为WebSocketsController的新控制器。留神,咱们将只是应用一个控制器action,而不是拦挡申请管道。 这个控制器的残缺代码如下所示。 ...

March 4, 2021 · 2 min · jiezi

关于c#:手把手教你爬取优酷电影信息2

上一章节中咱们实现了对优酷单页面的爬取,简略进行回顾一下,应用HtmlAgilityPack库,对爬虫的爬取一共分为三步 爬虫步骤 加载页面解析数据保留数据继第一篇文档后的爬虫进阶,本文章次要是对上一篇的进阶。实现的性能次要为:1、爬取电影类别列表2、循环每个类别的电影信息,对每个类别的信息分页爬取3、爬取的数据保留到数据库中 一、爬取电影类别列表 应用Chrome浏览器,F12,找到以后地位,失去以后地位的Xpath。咱们须要的数据是电影的类别编码和电影类别名称。 规定剖析:XPATH门路为 "//*[@id='filterPanel']/div/ul/li/a")类别编码为A标签Href门路的内容,咱们对其进行截取类别名称为A标签InnerTest,咱们对其进行截取 代码示例 //加载web内容 private static readonly string _url = "http://list.youku.com/category/video/c_0.html"; /// <summary> /// 失去所有的类别 /// </summary> public static List<VideoType> GetVideoTypes() { //加载web内容 var web = new HtmlWeb(); var doc = web.Load(_url); //内容解析-取得所有的类别 var allTypes = doc.DocumentNode.SelectNodes("//*[@id='filterPanel']/div/ul/li/a").ToList(); //类别列表中去掉【全副】这个选项 var typeResults = allTypes.Where((u, i) => { return i > 0; }).ToList(); var reList = new List<VideoType>(); foreach (var node in typeResults) { var href = node.Attributes["href"].Value; reList.Add(new VideoType { Code = href.Substring(href.LastIndexOf("/") + 1, href.LastIndexOf(".") - href.LastIndexOf("/") - 1), Name = node.InnerText }); } return reList; }二、爬取每个类别的总分页数code 为电影类别编码页面规定 $"http://list.youku.com/category/show/{code}.html"依据页面规定进行爬取: ...

February 26, 2021 · 2 min · jiezi

关于c#:如何将IHttpHandler和IHttpModule迁移到ASPNET-Core中间件

ASP.NET Core是一个跨平台、开源的框架,用于在Windows、Mac和Linux操作系统(OS)上开发web应用程序。你能够应用以下任何IDE开发ASP.NET Core 应用程序: Visual StudioVisual Studio for MacVisual Studio Code在这篇博文中,咱们将学习如何如何将asp.net IHttpHandler和IHttpModule迁徙到ASP.NET Core中间件并提供代码示例。 让咱们开始吧! ASP.NET IHttpHandler 在ASP.NET应用程序中,HTTP处理程序是一个过程,它在对向web服务器的每个响应上执行。咱们能够创立本人的自定义HTTP处理程序。 上面是将所有.aspx页重定向到一个新页的代码。 public class RedirectionHandler : IHttpHandler{ public bool IsReusable { get { return false; } } public void ProcessRequest(HttpContext context) { var response = context.Response; response.Write("<p>Process files with .aspx extension</p>"); // Any redirection logic can be written here. }}web.config中增加如下代码: <add name="RedirectionHandler" verb="*" path="*.aspx" type="MyWebApplication.RedirectionHandler" resourceType="Unspecified"/>ASP.NET IHTTPModule IHttpModule还将在应用程序的每个申请的HTTP处理程序执行之前和之后。它们帮忙咱们验证传入和传出的申请并批改它们。 上面是用于依据用户的IP地址限度用户的IHttpModule代码。 public class IPRestrictionModule : IHttpModule{ public void Init(HttpApplication context) { context.BeginRequest += (source, arguments) => { var application = (HttpApplication)source; var beginContext = application.Context; beginContext.Response.Write("<p>Restrict Users based on IP</p>"); // Code logic comes here. }; context.EndRequest += (source, arguments) => { var application = (HttpApplication)source; var endContext = application.Context; endContext.Response.Write("<p>Request ended.</p>"); }; }}web.config中增加如下代码: ...

February 26, 2021 · 2 min · jiezi

关于c#:手把手教你爬取优酷电影信息-1

爬虫的制作次要分为三个方面1、加载网页构造2、解析网页构造,转变为合乎需要的数据实体3、保留数据实体(数据库,文本等) 在理论的编码过程中,找到了一个好的类库“HtmlAgilityPack”。介绍:官网:http://html-agility-pack.net/...Html Agility Pack源码中的类大略有28个左右,其实不算一个很简单的类库,但它的性能确不弱,为解析DOM曾经提供了足够弱小的性能反对,能够跟jQuery操作DOM媲美) 应用阐明:Html Agility Pack(XPath 定位),在理论应用过程中,发现有局部内容如果通过Css进行定位会比XPath更加不便,所以通过查找找到了另外一个CSS的解析了类库 ScrapySharp(Css 定位) 整顿:Nuget包须要援用的库1、Html Agility Pack(XPath 定位)2、ScrapySharp(Css 定位) 代码下载地址: https://github.com/happlyfox/FoxCrawler第一点——加载网页构造Html Agility Pack封装了加载内容的办法,使doc.Load(arguments),具备多种重载形式,以下列举官网的三个实例 /// <summary> /// 加载网页构造 /// </summary> private static void LoadDocment() { // 从文件中加载 var docFile = new HtmlDocument(); docFile.Load("file path"); // 从字符串中加载 var docHtml = new HtmlDocument(); docHtml.LoadHtml("html"); // 从网站中加载 var url = "http://html-agility-pack.net/"; var web = new HtmlWeb(); var docWeb = web.Load(url); }第二点——解析网页构造,转变为合乎需要的数据实体 /// <summary> /// 解析网页构造 /// </summary> private static YouKu ParsingWebStructure() { /*选用优酷片库列表 地址:http://list.youku.com/category/show/c_96_s_1_d_1_p_{index}.html */ //首先加载web内容 var url = "http://list.youku.com/category/show/c_96_s_1_d_1_p_1.html"; var web = new HtmlWeb(); var doc = web.Load(url); //输入WebHtml内容 //Console.WriteLine(doc.DocumentNode.InnerHtml); /* HtmlAgilityPack 解析形式官网提供的有俩种示例*/ //1、 With XPath var value = doc.DocumentNode.SelectSingleNode("//*[@id='total_videonum']").Attributes["id"].Value; var resultCount = doc.DocumentNode.SelectSingleNode("//*[@id='total_videonum']").InnerText; Console.WriteLine($"id='{value}' 筛选后果:{resultCount}个"); // 2、With LINQ var linqNodes = doc.DocumentNode.SelectSingleNode("//*[@id='filterPanel']/div[2]/ul").Descendants("li").ToList(); Console.WriteLine("电影产地:"); List<string> videoCountry = new List<string>(); foreach (var node in linqNodes) { videoCountry.Add(node.InnerText); Console.Write($"{node.InnerText} \t"); } //3、应用ScrapySharp进行Css定位 var cssNodes = doc.DocumentNode.CssSelect("#filterPanel > div > label"); Console.WriteLine(); List<string> videoType = new List<string>(); foreach (var node in cssNodes) { videoType.Add(node.InnerText); Console.Write($"{node.InnerText} \t"); } //结构实体 YouKu model = new YouKu() { id = value, videoNum = int.Parse(resultCount), videoCountry = videoCountry, videoType = videoType }; return model; }public class YouKu{ public string id { get; set; } public int videoNum { get; set; } public List<string> videoCountry { get; set; } public List<string> videoType { get; set; }}第三点——保留数据实体,转变为合乎需要的数据实体 /// <summary> /// 保留数据实体 /// </summary> private static void SavaData() { var model = ParsingWebStructure(); var path = "youku.txt"; if (!File.Exists(path)) { File.Create(path); } File.WriteAllText(path, getJsonByObject(model)); } private static string getJsonByObject(Object obj) { //实例化DataContractJsonSerializer对象,须要待序列化的对象类型 DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType()); //实例化一个内存流,用于寄存序列化后的数据 MemoryStream stream = new MemoryStream(); //应用WriteObject序列化对象 serializer.WriteObject(stream, obj); //写入内存流中 byte[] dataBytes = new byte[stream.Length]; stream.Position = 0; stream.Read(dataBytes, 0, (int)stream.Length); //通过UTF8格局转换为字符串 return Encoding.UTF8.GetString(dataBytes); }四 Main static void Main(string[] args) { ///爬虫的制作次要分为三个方面 ///1、加载网页构造 ///2、解析网页构造,转变为合乎需要的数据实体 ///3、保留数据实体(数据库,文本等) /* * 在理论的编码过程中,找到了一个好的类库“HtmlAgilityPack”。 * 介绍: * 官网:http://html-agility-pack.net/?z=codeplex * Html Agility Pack源码中的类大略有28个左右,其实不算一个很简单的类库,但它的性能确不弱,为解析DOM曾经提供了足够弱小的性能反对,能够跟jQuery操作DOM媲美) * 应用阐明: * Html Agility Pack(XPath 定位),在理论应用过程中,发现有局部内容如果通过Css进行定位会比XPath更加不便,所以通过查找找到了另外一个CSS的解析了类库 ScrapySharp(Css 定位) * 整顿: * Nuget包须要援用的库 * 1、Html Agility Pack(XPath 定位) * 2、ScrapySharp(Css 定位) */ //第一点——加载网页构造,Html Agility Pack封装了加载内容的办法,应用doc.Load(arguments),具备多种重载形式,以下列举官网的三个实例 //LoadDocment(); //第二点——解析网页构造,转变为合乎需要的数据实体 //ParsingWebStructure(); //第三点——保留数据实体,转变为合乎需要的数据实体 SavaData(); Console.Read(); }

February 26, 2021 · 2 min · jiezi

关于c#:进击吧Blazor第一章-5组件开发

《进击吧!Blazor!》是自己与张善友老师单干的Blazor零根底入门系列视频,此系列能让一个从未接触过Blazor的程序员把握开发Blazor利用的能力。视频地址:https://space.bilibili.com/48...本系列文章是基于《进击吧!Blazor!》直播内容编写,降级.Net5,改良问题,解说更全面。因为篇幅无限,文章中省略了局部代码,残缺示例代码:https://github.com/TimChen44/...作者:陈超超Ant Design Blazor 我的项目贡献者,领有十多年从业教训,长期基于.Net技术栈进行架构与开发产品的工作,现就职于正泰团体。邮箱:timchen@live.com欢送各位读者有任何问题分割我,咱们共同进步。 这次分享我么要聊聊Blazor的精华,也是我集体认为Blazor框架体系中最优良的个性——组件。 组件组件(Component)是对数据和办法的简略封装。简直所有UI相干的框架都有组件(控件)的概念。 晚期的Delphi组件叫做VCL(Visual Component Library),它采纳本身嵌套的形式组合成所需的用户界面,并提供属性,办法,事件与组件内部进行交互,本身有着独立的生命周期,在必要的时候进行销毁。 之后.Net的WinForms和WPF组件绝对于Delphi尽管设计实现上齐全不同,然而对组件的定义和用处上简直统一。 当初Web前端框架Angular中也采纳了组件的概念,整体理念仍旧类似。 有些框架依据是否可见将组件分为,组件(Component)不可见,控件(Control)可见,比方Delphi,WinForms纵观这些框架的组件设计,能够提炼出组件蕴含以下个性。Blazor利用也是应用组件构建的。组件是自蕴含的用户界面 (UI) 块,例如页、对话框或窗体。 组件蕴含插入数据或响应 UI 事件所需的 HTML 标记和解决逻辑。 组件非常灵活且轻量。 可在我的项目之间嵌套、重复使用和共享。 1.参数(属性)提供组件内部向组件外部传递数据的形式。 在Blazor中咱们称组件的属性(Property)叫参数(Parameter),参数自身就是一个属性,然而为了让Blazor框架能辨别两者,所以咱们在属性上减少 [Parameter]个性来申明属性为组件的参数。 [Parameter]public string Text { get; set; }组件参数组件参数能够接管来在razor页面中给与的值,反对简略类型,也能够反对简单类型。 <!--组件代码--><h1>Blazor is @Text!</h1>@code { [Parameter] public string Text { get; set; }}<!--组件应用--><Component Title="Superior">上例就是将Superior通过参数传入组件,组件中就会输入Blazor is Superior! 路由参数组件能够接管来自 @page 指令所提供的路由模板的路由参数。 路由器应用路由参数来填充相应的组件参数。参数类型受限于路由规定,只反对几个根本类型。 <!--页面代码-->@page "/RouteParameter/{text}"<h1>Blazor is @Text!</h1>@code { [Parameter] public string Text { get; set; }}当应用/RouteParameter/Superior地址进行路由时,跳转到上例中的页面,并且页面输入Blazor is Superior! 级联参数在某些状况下,应用组件参数将数据从先人组件流向子代组件不太不便,尤其是在有多个组件层时。 级联值和参数提供了一种不便的办法,使先人组件为其所有子代组件提供值,从而解决了此问题。 先人组件中应用CascadingValue设定须要向下传递的级联值,子代组件中应用 [CascadingParameter] 个性来申明级联参数用于接管级联值。 ...

February 25, 2021 · 5 min · jiezi

关于c#:线程安全Ⅱ

混合模式因为用户模式和内核模式各有优劣,为了利用两者各自的有点,因而能够同时应用两种模式来进行结构,在没有线程竞争的时候能够具备用户模式的性能劣势,而在多个线程同时竞争一个结构的时候又能提供不产生自旋的长处,使应用程序的性能失去晋升。 示例代码class HybridLock : IDisposable{ private int m_Waiters = 0; private AutoResetEvent m_WaiterLock = new AutoResetEvent(false); public void Enter() { //线程想要取得锁 if (Interlocked.Increment(ref this.m_Waiters) == 1) return; //锁能够应用直,接返回 //另一个线程正在期待,阻塞该线程 this.m_WaiterLock.WaitOne(); //产生较大的性能影响 //WaitOne返回后,这个线程便领有了锁 } public void Leave() { //这个线程筹备开释锁 if (Interlocked.Decrement(ref this.m_Waiters) == 0) return; //没有其它线程阻塞,间接返回 //有其它线程正在阻塞,唤醒其中一个 this.m_WaiterLock.Set(); //产生较大的性能影响 } public void Dispose() { this.m_WaiterLock.Dispose(); }}剖析代码HybridLock对象的Enter办法调用了Interlocked.Increment,让m_Waiters字段递增1,这个线程发现没有线程领有这个锁,因而该线程取得锁并间接返回(取得锁的速度十分快)。如果另一个线程染指并调用Enter,此时m_Waiters字段再次递增值为2,发现锁被另一个线程领有,所以这个线程会调用AutoResetEvent对象的WaitOne来阻塞自身(这里因为是内核模式所以会产生性能影响),避免自旋。 再看看Leave办法,一个线程调用Leave时,会调用Interlocked.Decrement使m_Waiters字段递加1,如果m_Waiters字段是0,阐明没有其它线程在Enter的调用中产生阻塞,这时线程能够间接返回。然而如果线程发现m_Waiters字段的值递加后不为0,阐明存在线程竞争,至多有一个线程在内核中阻塞,这个线程必须只能唤醒一个阻塞的线程,通过调用AutoResetEvent对象的Set办法实现, 自旋、线程所有权和递归因为转换成内核代码会造成性能损失,而线程占有一个锁的工夫通常比拟短,所以能够先让线程处于用户模式且自旋一段时间,若还未取得锁的权限便可让它转为内核模式,如果线程在期待期间锁变得可用便可防止转为内核模式了。 示例代码(提供自旋、线程所有权和递归反对)class HybridLock : IDisposable{ //用户模式 private int m_Waiters = 0; //内核模式 private AutoResetEvent m_WaiterLock = new AutoResetEvent(false); //管制自旋 private int m_SpinCount = 1000; //用有锁的线程 private int m_OwningThreadId = 0; //领有次数 private int m_Recursion = 0; public void Enter() { //如果线程曾经领有,递增递归次数并返回 var threadId = Thread.CurrentThread.ManagedThreadId; if(this.m_OwningThreadId == threadId) { this.m_Recursion++; return; } //尝试获取 var spinWait = new SpinWait(); for (int i = 0; i < this.m_SpinCount; i++) { //如果锁能够应用了 if (Interlocked.CompareExchange(ref this.m_Waiters, 1, 0) == 0) goto GotLock; //给其它线程运行的机会,心愿锁会被开释 spinWait.SpinOnce(); } //自旋完结,依然没有取得锁则再试一次 if(Interlocked.Increment(ref this.m_Waiters) > 1) { //有其它线程被阻塞,这个线程也必须阻塞 this.m_WaiterLock.WaitOne(); //性能损失 //期待该线程用有锁醒来 } GotLock: //一个线程用有锁时,记录ID并指出线程领有锁一次 this.m_OwningThreadId = threadId; this.m_Recursion = 1; } public void Leave() { //如果线程不必有锁,bug var threadId = Thread.CurrentThread.ManagedThreadId; if (threadId != this.m_OwningThreadId) throw new SynchronizationLockException("线程未领有锁!"); //递加递归计数,如果线程依然用有锁,间接返回 if (--this.m_Recursion > 0) return; //当初没有线程领有锁 this.m_OwningThreadId = 0; //若没有其它线程被阻塞间接返回 if (Interlocked.Decrement(ref this.m_Waiters) == 0) return; //唤醒一个被阻塞的线程 this.m_WaiterLock.Set(); //性能损失 } public void Dispose() { this.m_WaiterLock.Dispose(); }}Monitor类这个类提供了一个互斥锁,这个锁反对自旋、线程所有权和递归,是线程同步罕用的类。 ...

February 25, 2021 · 2 min · jiezi

关于c#:RabbitMQ-简介

概述RabbitMQ 是基于 AMQP 实现的一个开源音讯组件,次要用于在分布式系统中存储转发音讯,由因高性能、高可用以及高扩大而出名的 Erlang 语言写成。 特点高牢靠:RabbitMQ 提供了多种多样的个性让你在可靠性和性能之间做出衡量,包含长久化、发送应答、公布确认以及高可用性。 高可用队列:反对跨机器集群,反对队列平安镜像备份,音讯的生产者与消费者不管哪一方呈现问题,均不会影响音讯的失常收回与接管。 灵便的路由:所有的音讯都会通过路由器转发到各个音讯队列中,RabbitMQ 内建了几个罕用的路由器,并且能够通过路由器的组合以及自定义路由器插件来实现简单的路由性能。 工作原理音讯从发送端到接收端的流转过程即 RabbitMQ 的音讯工作机制,请见下图: 根本用法共有 6 种根本用法:单对单、单对多、公布订阅模式、按路由规定发送接管、主题、RPC(即近程存储调用)。咱们将介绍单对单、单对多和主题的用法。 1、单对单:单发送、单接管 2、单对多:一个发送端,多个接收端,如分布式的工作派发 3、主题:Exchange Type 为 topic,发送音讯时须要指定交换机及 Routing Key,消费者的音讯队列绑定到该交换机并匹配到 Routing Key 实现音讯的订阅,订阅后则可接管音讯。只有消费者将队列绑定到该交换机且指定的 Routing Key 合乎匹配规定,能力收到音讯。 其中 Routing Key 能够设置成通配符,如:或 #(示意匹配 Routing Key 中的某个单词,# 示意任意的 Routing Key 的音讯都能被收到)。如果 Routing Key 由多个单词组成,则单词之间用. 来分隔。 命名标准: 交换机名的命名倡议:Ex{AppID}.{自定义 ExchangeName},队列名的命名倡议:MQ{AppID}.{自定义 QueueName} 。 好用的轮子其中EasyNetQ是.NET上RabbitMQ的当先客户端API,在NuGet.org上有超过400万次下载。这是一个凋谢源代码我的项目。 EasyNetQ是为了提供一个尽可能简洁的实用与RabbitMQ的.NET类库。为了实现这些指标,EasyNetQ提供一种自认为你会在.NET下应用RabbitMQ的视图。为了放弃应用灵活性,简略起见,EasyNetQ强制应用了一些简略的约定。包含如下: 音讯用 .NET 类型示意音讯通过.NET类型路由开源地址更多功能见: https://github.com/EasyNetQ/E...

February 24, 2021 · 1 min · jiezi

关于c#:应用界面开发小技巧-如何在覆盖表单上显示自定义按钮

点击获取工具>> 留神:GitHub上提供了残缺的示例我的项目,网址为:https://github.com/DevExpress-Examples/how-to-display-a-custom-button-on-an-overlay-form 概述Overlay Form是一个半透明的启动屏幕,他在后盾线程中运行并笼罩控件或表单来避免对其进行拜访,Overlay Form仅蕴含一个期待指示器。 本示例演示如何显示: 期待指示器下方的百分比标签;一个自定义按钮,该按钮终止已解决的工作并敞开Overlay Form。 本示例使您能够更改标签文本、按钮字形以及单击按钮时执行的操作。 实现细节您能够按以下形式自定义Overlay Form图形: 从OverlayWindowPainterBase类继承它;重写Draw办法;将创立的对象作为参数传递给SplashScreenManager.ShowOverlayForm办法。本示例应用OverlayImagePainter和OverlayTextPainter对象(OverlayWindowPainterBase后辈),它们实现了图像和文本的绘制逻辑,并且您能够应用它们的属性来自定义图像和文本。 OverlayImagePainter对象在Overlay Form的顶部核心绘制一个自定义图像,并解决该图像上的单击。 您能够指定以下属性: Image - 失常状态下的图像;HoverImage - 处于悬停状态的图片;ClickAction - 单击图像时执行的操作。OverlayTextPainter对象在期待指示器下方绘制一个自定义标签,您能够指定以下属性: Text - 标签文本;Font - 文本字体(默认应用Tahoma,18);Color - 文本色彩(默认为彩色)。OverlayWindowCompositePainter对象在OverlayImagePainter和OverlayTextPainter对象中组成绘图逻辑,该复合绘制器作为参数传递给SplashScreenManager.ShowOverlayForm办法。 显示Overlay Form时执行的操作是应用.Net Framework类库(工作并行库(TPL))中可用的可勾销工作来实现的。 自定义按钮和标签地位按钮图像显示在Overlay Form的顶部地方,标签显示在期待指示器下方,您能够重写以下办法来指定其地位: OverlayTextPainter.CalcTextBounds — 返回一个矩形,该矩形指定标签的地位;OverlayImagePainter.CalcImageBounds — 返回一个矩形,它指定按钮的地位。每次须要从新绘制叠加表单时(例如,当用户调整重叠控件的大小时),都会调用这些办法,drawArgs办法参数蕴含绘制笼罩图所需的信息。本示例应用以下属性: Bounds — 获取Overlay Form边界;ImageBounds — 获取期待指示器的范畴;上面的代码段显示了如何更新以后示例来在自定义地位显示按钮和标签。 C# `using DevExpress.Utils.Extensions;using DevExpress.XtraSplashScreen; class OverlayImagePainterEx : OverlayImagePainter {public OverlayImagePainterEx(Image image, Image hoverImage = null, Action clickAction = null) : base(image, hoverImage, clickAction) { }protected override Rectangle CalcImageBounds(OverlayLayeredWindowObjectInfoArgs drawArgs) {int indent = 10;return Image.Size.AlignWith(drawArgs.Bounds).WithY(indent).WithX(drawArgs.Bounds.Width - Image.Height - indent);}} ...

February 23, 2021 · 2 min · jiezi

关于c#:在NET中使用Apache-Kafka一

已经在你的应用程序中应用过异步解决吗?在解决不须要立刻执行的工作时,异步代码仿佛是不可避免的。Apache Kafka是最罕用和最强壮的开源事件流平台之一。许多公司和开发者利用它的弱小性能来创立高性能的异步操作,用于微服务的数据集成,以及用于应用程序衰弱指标的监控工具。这篇文章解释了在.NET应用程序中应用Kafka的细节,还展现了如何在Windows操作系统上装置及应用。 它是如何工作的 当今世界,数据正在以指数模式增长。为了包容一直增长的数据,Kafka这样的工具应运而生,提供了强壮而令人印象粗浅的架构。 然而Kafka是如何在幕后工作的呢? Kafka在生产者和消费者之间替换信息。生产者和消费者是这一线性过程的两个次要角色。 Kafka也能够在一个或多个服务器的集群中工作。这些服务器被称为Kafka代理,通过代理你能够受害于多种个性,例如数据复制、容错和高可用。 这些代理由另一个叫做Zookeeper的工具治理。总之,它是一种旨在放弃分布式系统中同步和组织配置数据的服务。 Kafka Topics Kafka只是一个代理,所有的行为都产生在这。生产者向世界发送音讯,而消费者读取特定的数据块。如何辨别数据的一个特定局部与其余局部?消费者如何晓得要应用哪些数据?要了解这一点,你须要一个新的内容:topic。 Kafka topics是传递音讯的载体。由生产者产生的Kafka记录被组织并存储到topic中。 假如你正在解决一个用于记录动物目录的API我的项目。你要确保公司中的每个人都可能拜访每一个新注册的动物。所以你选了Kafka。 在零碎中注册的每一个新动物都将通过Kafka进行播送。topic的名称是tree_catalog。 在这种状况下,topic像堆栈一样工作。它将信息保留在达到时的雷同地位,并保证数据不会失落。 达到的每个数据记录被存储在一个slot中,并用一个称为offset的惟一地位号注册。 例如,当一个消费者生产了存储在offset是0的音讯时,它提交音讯,申明一切正常,而后挪动到下一个offset,依此类推。这个过程通常是线性的。然而,因为许多消费者能够同时将记录“插入”到同一个topic中,所以确定哪些数据地位曾经被占用的责任留给了消费者。这意味着消费者能够决定应用音讯的程序,甚至决定是否从头开始从新开始解决(offset为0)。 分区 分布式系统的一个要害个性是数据复制。它容许一个更平安的体系结构,数据能够被复制到其余中央,以防不好的事件产生。Kafka通过分区解决复制。Kafka topics被配置为扩散在几个分区(可配置的)。每个分区通过惟一的offset保留数据记录。 为了实现冗余,Kafka在分区(一个或多个)创立正本,并在集群中流传数据。 这个过程遵循leader-follower模型,其中一个leader正本总是解决给定分区的申请,而follower复制该分区。每次制作人将音讯推送到某个主题时,它都会间接传递给该主题的领导者。 生产组 在Kafka中,生产来自topic的音讯最合适的形式是通过生产组。 顾名思义,这些组由一个或多个消费者组成,目标是获取来自特定主题的所有音讯。 为此,组必须始终具备惟一的id(由属性group.id设置)。无论何时消费者想要退出那个组,它都将通过组id来实现。 每次你增加或删除一个组的消费者,Kafka会从新均衡它们之间的负载,这样就不会过载。 设置 当初,你曾经理解了Kafka的通用工作原理,是时候开始环境设置了。为了简化,这个例子将应用Docker来保留Kafka和Zookeeper映像,而不是将它们装置到你的机器上。这样能够节俭一些空间和复杂性。 对于Windows用户,Docker提供了一种装置和治理Docker容器的简略形式:Docker桌面。进入它的下载页面并下载安装程序。运行它,并在不更改默认设置选项的状况下持续到最初。确保在此过程实现后重新启动计算机。重启后,Docker可能会要求你装置其余依赖项,所以请确保承受每一个依赖项。在Docker上装置一个无效的Kafka本地环境最快的门路之一是通过Docker Compose。通过这种形式,能够通过一个YAML文件建设应用程序服务,并疾速地让它们运行。 创立一个名为docker-compose的新文件,并将以下的内容保留到其中: version: '2'services:  zookeeper:    image: wurstmeister/zookeeper    ports:      - "2181:2181"  kafka:    image: wurstmeister/kafka    ports:      - "9092:9092"    environment:      KAFKA_ADVERTISED_HOST_NAME: 127.0.0.1      KAFKA_CREATE_TOPICS: "simpletalk_topic:1:1"      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181    volumes:      - /var/run/docker.sock:/var/run/docker.sock留神,代码从Docker Hub的wurstmeister帐户中导入了两个服务镜像(kafka和zookeeper)。这是在Docker上应用Kafka最稳固的镜像之一。端口也应用它们的推荐值进行设置,因而请留神不要更改它们。 其中最重要的设置之一属于KAFKA_CREATE_TOPICS。在这里,你必须定义要创立的topic名称。还有其余办法能够创立主题,当前你将看到。 通过命令行导航到docker-compose.yml所在的文件夹。而后执行如下命令启动镜像: docker-compose up这段代码将加载所有依赖项并启动镜像。在此过程中,可能会看到大量的日志。 如果没有谬误日志显示,阐明启动胜利。 为了查看Docker镜像是否启动,在另一个cmd窗口中运行以下命令: docker ps显示如下: 亲自动手 你的Kafka环境曾经能够应用了。下一步是在Visual Studio中进行我的项目创立。进入我的项目创立窗口。搜寻ASP.NET Core Web Application模板,单击Next。 解决方案新建一个名称消费者我的项目和生产者我的项目将在同一个解决方案中共存。 下一个窗口抉择API模板。勾销勾选“配置为HTTPS”选项。 创立我的项目后,右键单击解决方案,抉择增加新我的项目,而后,抉择ASP.NET Core Web Application我的项目类型。 持续并像后面一样抉择API模板。 当初,在ST-Kafka-NET解决方案中有两个我的项目。 NuGet包 ...

February 22, 2021 · 2 min · jiezi

关于c#:Net-NLog日志框架配置与使用

NLog是实用于各种.NET平台(包含.NET规范)的灵便,收费的日志记录平台,NLog可将日志写入多个指标,比方Database、File、Console、Mail。上面介绍下NLog的根本应用办法。 应用步骤增加援用装置NLog Nuget package:Install-Package NLog.Config; 增加配置文件在我的项目中增加一个配置文件(也能够间接将NLog的配置我的项目放入*.exe.config中),重命名为NLog.config;更改如下两项属性内容: 复制到输入目录 - 如果较新则复制生成操作 - 内容增加配置内容,上面展现的是GitHub上的示例配置:<?xml version="1.0" encoding="utf-8" ?><nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <!-- 配置输入指标 --> <targets> <!-- 输入到文件 --> <target name="logfile" xsi:type="File" fileName="file.txt" /> <!-- 输入到控制台 --> <target name="logconsole" xsi:type="Console" /> </targets> <!-- 定义输入规定,可配置多个 --> <rules> <logger name="*" minlevel="Info" writeTo="logconsole" /> <logger name="*" minlevel="Debug" writeTo="logfile" /> </rules></nlog>创立Logger类,获取NLog.Logger实例:public class Log{ // ... private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();}配置示例如下配置为自己罕用配置,可参考该配置及GitHub领导文档自定义配置: 留神:首次应用NLog时,可先将throwExceptions置为true,这样如果配置有问题没有胜利打印日志,VS会抛出异样,不便定位起因。调试好后,再将该项置为false。 另外:示例中fileName(日志文件全门路名称)是通过后盾代码配置的,这样能够动静设置日志的输入地位。 // NLog.config<?xml version="1.0" encoding="utf-8" ?><nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" throwExceptions="false" autoReload="true" async="true" encoding="UTF-8"> <targets> <target name="logconsole" xsi:type="Console" layout="${date:format=HH\:mm\:ss} | ${level:padding=-5} | ${message}"/> <target name="logfile" xsi:type="File" createDirs="true" keepFileOpen="true" fileName="${gdc:logDirectory:whenEmpty=${baseDir}}/logs/${shortdate}/Whiteboard.log" archiveFileName="${gdc:logDirectory:whenEmpty=${baseDir}/logs/${shortdate}}/Whiteboard_{##}.log" archiveAboveSize="102400" archiveNumbering="Sequence" maxArchiveDays="30" layout="${longdate} | ${level:uppercase=false:padding=-5} | ${message} ${onexception:${exception:format=tostring} ${newline} ${stacktrace} ${newline}"/> </targets> <rules> <logger name="*" minlevel="Debug" writeTo="logconsole"/> <logger name="*" minlevel="Debug" writeTo="logfile" /> </rules></nlog>// Log.cs 设置日志文件输入地位string logDir = Path.Combine(Environment.GetFolderPath( Environment.SpecialFolder.LocalApplicationData), Process.GetCurrentProcess().ProcessName);NLog.GlobalDiagnosticsContext.Set("logDirectory", logDir);

February 22, 2021 · 1 min · jiezi

关于c#:线程安全

线程平安多个线程试图同时拜访同一个数据时,数据不会受到毁坏 线程同步结构结构模式别离有用户模式和内核模式两种,其中用户模式结构应用了非凡的CPU指令协调线程(协调是在硬件中产生的事件),所以其结构速度要显著快于内核模式结构,同时用户模式中阻塞的线程池线程永远不会被认为阻塞,所以线程池不会创立新线程替换阻塞线程。在用户模式中运行的线程可能被零碎抢占,但线程会以最快的速度再次调度,所以想要获取某一资源又临时无奈获得时,线程会用户模式中始终运行,这并不是一个良好的景象。而内核模式的结构是由Windows操作系统本身提供的,要求在应用程序的线程中调用在操作系统内核中实现的函数,将线程从用户模式切换为内核模式会造成微小的性能损失。然而也有一个长处:一个线程应用内核模式结构获取一个由其它线程正在拜访的资源时,Windows会阻塞线程,使之不再节约CPU工夫,等到资源可用时会复原线程,容许它拜访资源。 用户模式结构易失结构:在蕴含一个简略数据类型的变量上执行原子性的读或写操作互锁结构:在蕴含一个简略数据类型的变量上执行原子性的读和写操作原子性指事务的不可分割性,意味着一个变量的值的读取都是一次性的,如以下代码 class SomeType{ public static int x;}SomeType.x = 0x01234567;变量x会一次性从0x00000000变成0x01234567,另一个线程不可能看到一个处于两头值的状态,如0x01234000,这便是原子性。 易失结构编写好的代码须要被编译器编译成IL代码,再通过JIT编译器转换老本地CPU指令能力被计算机执行。而在这些转换过程中,编译器、JIT编译器、CPU自身可能都会对原先编写好的代码进行优化。如上面这段代码通过编译后将会隐没 private static void SomeMethod(){ //常量表达式在编译时计算为0 int value = 100 - (50 * 2); //value为0循环永不执行 for (int i = 0; i < value; i++) { //永远执行不到,不须要编译循环中的代码 Console.WriteLine(i); }}上述代码中,编译器发现value为0,循环永远不会执行,没有必要编译循环中的代码,因而这个办法编译后会被优化掉。如果有一个办法中调用了SomeMethod办法,在对这个办法进行JIT编译的时候,JIT编译器会尝试内联SomeMethod办法的代码,因为没有代码,所以JIT编译器会删除调用SomeMethod办法的代码。 编译器、JIT编译器和CPU对代码进行优化的时候,从单线程的角度看,代码会做咱们心愿它做的事件,而从多线程来看,代码的用意不肯定会失去保留,以下的代码进行了演示: class SomeType{ private int m_Flag = 0; private int m_Value = 0; public void Thread1() { this.m_Value = 10; this.m_Flag = 1; } public void Thread2() { //可能会输入0,与预期不统一 if(this.m_Flag == 1) Console.WriteLine("value = {0}", this.m_Value); }}static void Main(){ ThreadPool.QueueUserWorkItem((o) => { someType.Thread1(); }); ThreadPool.QueueUserWorkItem((o) => { someType.Thread2(); });}上述代码的问题在于假设Thread1办法中的代码依照程序执行,编译Thread2办法中的代码时,编译器必须生成代码将m_Flag和m_Value 从RAM读入CPU寄存器。RAM可能先传递m_Value的值(此时为0),而后Thread1可能执行,将Thread1改为10,m_Flag改为1。然而Thread2的CPU寄存器没有看到m_Value的值曾经被另一个线程批改为10,呈现输入后果为0的状况。除此之外Thread1办法中的两行代码在CUP/编译器在解释代码时可能会呈现反转,毕竟这样做也不会扭转代码的用意,同样可能呈现在Thread2中m_Value输入0的状况。 ...

February 20, 2021 · 3 min · jiezi

关于c#:聊聊ASPNET-Core中的配置

作为软件开发人员,咱们当然喜爱一些可配置选项,尤其是当它容许咱们扭转应用程序的行为而无需批改或编译咱们的应用程序时。无论你是应用新的还是旧的.NET时,可能心愿利用json文件的配置。在这篇文章中,咱们将探讨读取配置所需的必要步骤以及应用这些值。 .NET的配置历史 对于那些ASP.NET老兵,你可能还记得wen.config。尽管它没有齐全被摈弃,但它在ASP.NET Core中扮演着不那么重要的角色。web.config是一个基于XML的文件,用于配置IIS的主机环境。在这个文件中,咱们能够搁置应用程序设置、加载额定的web模块、注册处理程序等等。 另一个限度是web.config更改后将迫使应用程序重新启动。更改能够很简略,如增加新的应用程序设置,也能够很简单,如向申请管道增加新模块。ASP.NET应用程序必须从新加载,以确保逻辑一致性。开发人员能够将所有设置通过ConfigurationManager拜访。坦率地说,随着工夫的推移,开发人员将重新启动看作是一种性能,而不是一种阻碍,应用它来重置陷入故障状态的应用程序。 当初的ASP.NET Core配置 ASP.NET Core看到了围绕配置产生次要问题,并试图通过以下三方面为开发人员改良: 除了XML之外,还反对其余模式的配置格局。用依赖注入(DI)的敌对办法替换ConfigurationManager。配置热更改,能够立刻在拜访的代码中产生。这些变动反映了更先进的设置,并且对本地云的web应用程序更敌对。应用程序配置能够来自多个地位,可扩展性使开发人员更容易防止自定义解决方案。 随着.NET采纳async/await和异步编程,应用单例可能会导致死锁和性能开销。使DI反对配置后,给开发人员提供了更多的形式来应用设置依赖项,并将这些数据与任何源解耦。它还能够在不拜访ConfigurationManager或web.config的状况下测试配置设置。 冷启动是所有用户的敌人,它会发明令人丧气的体验。无需重新启动就能够进行更改的能力确保了更好的运行时体验。 看看具体代码 目前,咱们曾经探讨了配置的历史和以后状态,然而让咱们跳到理论应用环节。 第一步是创立一个从配置提供程序读取设置的数据类。ASP.NET Core提供了多个开箱即用的性能,但最罕用的是JSON配置提供程序。该类须要蕴含与JSON局部雷同的构造。 public class HelloWorldOptions{ public string Text { get; set; }}下一部分是讲述ASP.NET Core如何绑定HelloWorldOptions类。咱们能够应用BindConfiguration办法做到这一点。 public void ConfigureServices(IServiceCollection services){ services.AddOptions<HelloWorldOptions>() .BindConfiguration("HelloWorld");}字符串HelloWorld示意appsettings.json文件中的局部。 { "HelloWorld" : { "Text": "Hello, Khalid!" }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*"}很好,当初咱们筹备好应用咱们的配置信息了。接下来就有点让人困惑了。咱们有三个接口可供选择: IOptions<T>IOptionsSnapshot<T>IOptionsMonitor<T>每个接口都包装了咱们的配置数据,并为咱们提供了稍微不同的生命周期。 IOptions< T>被注册为一个单例,因而所有的值都被检索一次并存储在ASP.NET Core应用程序的内存。在应用程序启动后,这种办法无奈读取任何更新的配置。注册为单例意味着ASP.NET能够将接口注入到任何依赖项中,而不用放心捕捉它或导致内存透露问题。这个版本很可能是大多数人会应用的。 IOptionsSnapshot< T>具备作用域生存期。ASP.NET Core将对每个HTTP申请从新查看一次。 缓存每个申请的实例,直到用户收到响应。这个办法对于那些心愿动静更改配置但依然须要通过以后管道进行刷新的申请的人十分有用。这个版本有助于应用切换配置,而无需从新加载应用程序。 最初,IOptionsMonitor< T>与IOptionsSnapshot<T>很类似,却是单例生命周期。IOptionsMonitor办法对于应该立刻解决的要害数据更改十分有用。长期存在的后盾服务可能心愿应用IOptionsMonitor持续接管配置更改,但不须要领取低廉的对象创立老本。 既然咱们晓得了每个接口的长处,咱们就能够应用咱们的配置了。在启动时找到的Configure办法中,让咱们增加一个新的GET终结点。 public void Configure(IApplicationBuilder app, IWebHostEnvironment env){ if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapGet("/", async context => { var options = context .RequestServices .GetRequiredService<IOptionsSnapshot<HelloWorldOptions>>() .Value; await context.Response.WriteAsync(options.Text); }); });}留神,在咱们的代码中,咱们应用的是IOptionsSnapshot。通过实例将容许咱们更新配置,而不须要重新启动咱们的应用程序。启动应用程序时,咱们应该看到配置值。更改配置将更改申请的后果。 ...

February 20, 2021 · 1 min · jiezi

关于c#:WPF界面应用开发技巧绑定到条件格式规则的集合

点击获取工具>>DevExpress WPF 领有120+个控件和库,将帮忙您交付满足甚至超出企业需要的高性能业务应用程序。通过DevExpress WPF能创立有着弱小互动性能的XAML根底应用程序,这些应用程序专一于当代客户的需要和构建将来新一代反对触摸的解决方案。 应用模型视图ViewModel(MVVM)架构模型设计WPF应用程序时,可能须要在模型或视图模型中形容条件格局设置规定。 网格能够绑定到蕴含条件格式化规定的对象汇合,这些条件在Model或ViewModel中进行了形容,从而最大限度地缩小了“暗藏代码”的需要。 View模型实现本文中应用的示例蕴含一个视图模型代码,其中包含以下类。 Order - 蕴含订单信息(例如数量,折扣等)的数据对象。ViewModel - 订单视图模型,_ViewModel_公开Orders属性(在网格内显示的订单列表)和Rules属性(格局规定列表)。OrderData - 提供要在网格控件中显示的订单信息。FormattingRule - 形容条件格局设置规定,此类提供的属性与所有类型的条件格局设置规定通用的设置绝对应。FormattingType - 枚举利用格局的可能类型。C# `using System.Collections.Generic;using System.Windows;using System.Windows.Controls; namespace GridDemo {// ... public class ViewModel {public ViewModel() {Orders = GetOrders();Rules = GetFormattingRules();} private static List<FormattingRule> GetFormattingRules() {var rules = new List<FormattingRule>();rules.Add(new FormattingRule() {Expression = "([UnitPrice] [Quantity] (1 - [Discount]) - [Freight]) < 0",ApplyToRow = true,Type = FormattingType.Background});rules.Add(new FormattingRule() {FieldName = "Discount",Expression = "[Discount] > 0",ApplyToRow = false,Type = FormattingType.Font});rules.Add(new FormattingRule() {FieldName = "Discount",Expression = "[Discount] > 0",Type = FormattingType.Icon});return rules;} ...

February 19, 2021 · 2 min · jiezi

关于c#:如何在ASPNET-Core中编写高效的控制器

通过遵循最佳实际,能够编写更好的控制器。所谓的“瘦”控制器(指代码更少、职责更少的控制器)更容易浏览和保护。而且,一旦你的控制器很瘦,可能就不须要对它们进行太多测试了。相同,你能够专一于测试业务逻辑和数据拜访代码。瘦控制器的另一个长处是,它更容易保护控制器的多个版本。 这篇文章探讨了使控制器变胖的坏习惯,而后摸索了使控制器变瘦和易于治理的办法。我列出编写控制器的最佳实际可能并不全面,但我曾经探讨了最重要的一些,并在适当的状况下提供了相干的源代码。在接下来的几节中,咱们将钻研什么是胖控制器,为什么它是一种代码坏滋味,瘦控制器是什么,为什么它是无益的,以及如何使控制器瘦、简略、可测试和可治理。 从控制器中删除数据拜访代码在编写控制器时,你应该保持繁多责任准则,这意味着控制器应该有“一个责任”或“有且只有一个起因能够更改”。换句话说,你心愿将更改控制器代码的起因减至起码。上面的代码显示了具备数据拜访逻辑的典型控制器。 在.NET生态系统中应用特定的技术堆栈会产生一些困惑,因为有很多抉择,比方应该应用哪种类型的运行时?在这篇文章中,咱们将试图把这些要点都说分明。 public class AuthorController : Controller{    private AuthorContext dataContext = new AuthorContext();    public ActionResult Index(int authorId)    {        var authors = dataContext.Authors            .OrderByDescending(x=>x.JoiningDate)            .Where(x=>x.AuthorId == authorId)            .ToList();        return View(authors);    }}在action外部应用数据上下文实例读取数据,违反了繁多职责准则,并使你的控制器充斥着不应该呈现在那里的代码。在本例中,咱们应用一个DataContext(假如咱们应用Entity Framework Core)来连贯、解决数据库中的数据。 今天如果你决定更改数据拜访技术(为了更好的性能或其余起因),你也必须更改你的控制器。例如,如果我想应用Dapper连贯到底层数据库该怎么办?更好的办法是应用repository类来封装数据拜访逻辑(只管我不太喜爱repository模式)。让咱们用以下代码更新AuthorController。 public class AuthorController : Controller{    private AuthorRepository authorRepository = new AuthorRepository();    public ActionResult Index(int authorId)    {        var authors = authorRepository.GetAuthor(authorId);        return View(authors);    }}控制器当初看起来更瘦了。那么这是编写这个控制器的最佳办法吗?不是。如果你的控制器正在拜访数据拜访组件,那么它将做太多的事件,因而违反了繁多职责准则。控制器不应该有间接拜访数据拜访组件的数据拜访逻辑或代码。上面是AuthorController类的改良版本。 public class AuthorController : Controller{    private AuthorService authorService = new AuthorService();    public ActionResult Index(int authorId)    {        var authors = authorService.GetAuthor(authorId);        return View(authors);    }}AuthorService类利用AuthorRepository类执行CRUD操作。 ...

February 19, 2021 · 1 min · jiezi

关于c#:C如何持续地监视外部信号

我是做PLC开发的,次要是操纵硬件。举个例子来说,X轴马达往前走,遇到传感器SB1,就停下来。这个SB1就必须处于继续的监控状态,程序不能以周期的形式去读这个SB1的状态,否则,在上一个读取SB1的行为完结,下一个读取SB1的行为还没有到来的时候,SB1被触发了,而程序却不晓得,则X轴马达就会冲过去,造成机器损坏。 PLC自身能继续地监控传感器,不须要额定编程,用户只有把SB1与X轴马达关联起来即可;SB1被触发了,X轴马达就会停机。 而C#上位机其实是监控PLC里的某个位的,比方M100.0。M100.0与SB1关联起来。SB1从1变成0,M100.0也会从1变成0;反之,SB1从0变成1,M100.0也会从0变成1。 因而,C#只有监督PLC里的M100.0即可,这种监督是继续的,只有M100.0一有变动,C#就能晓得,并且做出响应。 请问,这种继续的监督怎么做? Ps: 想过用While(true),感觉不大好[url]https://www.douban.com/doulis...[/url][url]https://m.douban.com/doulist/...[/url][url]https://book.douban.com/douli...[/url][url]https://movie.douban.com/doul...[/url][url]https://www.douban.com/doulis...[/url][url]https://m.douban.com/doulist/...[/url][url]https://book.douban.com/douli...[/url][url]https://movie.douban.com/doul...[/url][url]https://www.douban.com/doulis...[/url][url]https://m.douban.com/doulist/...[/url][url]https://book.douban.com/douli...[/url][url]https://movie.douban.com/doul...[/url][url]https://www.douban.com/doulis...[/url][url]https://m.douban.com/doulist/...[/url][url]https://book.douban.com/douli...[/url][url]https://movie.douban.com/doul...[/url][url]https://www.douban.com/doulis...[/url][url]https://m.douban.com/doulist/...[/url][url]https://book.douban.com/douli...[/url][url]https://movie.douban.com/doul...[/url][url]https://www.douban.com/doulis...[/url][url]https://m.douban.com/doulist/...[/url][url]https://book.douban.com/douli...[/url][url]https://movie.douban.com/doul...[/url][url]https://www.douban.com/doulis...[/url][url]https://m.douban.com/doulist/...[/url][url]https://book.douban.com/douli...[/url][url]https://movie.douban.com/doul...[/url][url]https://www.douban.com/doulis...[/url][url]https://m.douban.com/doulist/...[/url]

February 18, 2021 · 1 min · jiezi

关于c#:如何在ASPNET-Core-中使用IHttpClientFactory

利用IHttpClientFactory能够无缝创立HttpClient实例,防止手动治理它们的生命周期。 当应用ASP.Net Core开发应用程序时,可能常常须要通过HttpClient调用WebAPI的办法以查看终结点是否失常工作。要实现这一点,通常须要实例化HttpClient并应用该实例来调用你的办法。然而间接应用HttpClient也有一些毛病,次要与手动治理实例的生命周期无关。 你能够应用IHttpClientFactory创立HttpClient来防止这些问题。IHttpClientFactory是在.Net Core 2.1引入的,它提供了一个命名,配置和创立HttpClient实例的外围性能,并能主动治理实例的池化和生命周期。 上面咱们通过代码进一步探讨HttpClient和IHttpClientFactory,以及所设计的概念。要应用提供的代码,你须要装置Visual Studio 2019。 在Visual Studio 2019中创立一个ASP.NET Core MVC我的项目   假如你的零碎中装置了Visual Studio 2019,请依照上面列出来的步骤创立一个新的ASP.NET Core我的项目。 启动Visual Studio IDE。点击“创立新我的项目”。在“创立新我的项目”窗口中,从模板列表中抉择ASP.NET Core Web应用程序。单击Next。在“配置新我的项目”窗口中,指定新我的项目的名称和地位。能够抉择“将解决方案和我的项目放在同一个目录中”复选框。点击Create。在“创立一个新的ASP.NET Core Web应用程序“窗口中,抉择。NET Core作为运行时,而后抉择asp.net Core作为运行时。NET Core 3.1(或更高版本)。抉择“Web Application (Model-View-Controller)”作为我的项目模板来创立一个新的ASP.NET Core MVC应用程序。确保复选框“启用Docker反对”和“配置HTTPS”没有选中,因为咱们不会在这里应用这些个性。确保身份验证设置为“无身份验证”,因为咱们也不会应用身份验证。单击Create。依照这些步骤将创立一个新的ASP.NET Core MVC应用程序。在新我的项目中,创立一个新的API Controller,并应用默认名称保留它,即ValuesController。咱们将在接下来的局部中应用这个我的项目。 挑战HttpClient只管HttpClient没有间接实现IDisposable接口,但它扩大了System.Net.Http。HttpMessageInvoker,这个类实现了IDisposable。然而,当应用HttpClient实例时,你不应该手动操作开释它们。只管能够在HttpClient实例上调用Dispose办法,但不举荐这样做。 应该怎么做呢?一种抉择是使HttpClient动态化,或者将HttpClient的非动态实例包装在自定义类中,并使其成为单例类。然而更好的代替办法是应用IHttpClientFactory来生成HttpClient的实例,而后应用该实例来调用操作方法。 IHttpClientFactory 和HttpClientFactoryIHttpClientFactory是一个由DefaultHttpClientFactory类实现的接口,这是一个工厂模式。DefaultHttpClientFactory实现了IHttpClientFactory和IHttpMessageHandlerFactory接口。IHttpClientFactory提供了ASP.NET Core对创立、缓存和解决HttpClient实例提供了杰出的内置反对。 请留神,HttpClientFactory只是一个帮忙类,用于创立应用提供的处理程序配置的HttpClient实例。这个类有以下办法: Create(DelegatingHandler[])Create(HttpMessageHandler,DelegatingHandler[])CreatePipeline(HttpMessageHandler,IEnumerable<DelegatingHandler>)重载的HttpClientFactory类的Create办法看起来像这样: public static HttpClient Create(params DelegatingHandler[] handlers){ return Create(new HttpClientHandler(), handlers);}public static HttpClient Create(HttpMessageHandler innerHandler, params DelegatingHandler[] handlers){ HttpMessageHandler pipeline = CreatePipeline(innerHandler, handlers); return new HttpClient(pipeline);}引入HttpClientFactory和IHttpClientFactory是为了更好地治理HttpMessageHandler实例的生命周期。 为什么应用IHttpClientFactory?当你开释HttpClient实例时,连贯将放弃关上状态长达4分钟。此外,能够在任何工夫点关上socket的数量是有限度的——不能同时关上太多socket。因而,当应用太多HttpClient实例时,可能会耗尽socket。 这就是IHttpClientFactory的意义所在。你能够通过利用IHttpClientFactory来创立用于调用HTTP API办法的HttpClient实例,以防止HttpClient所面临的问题。在ASP.NET Core中实现IHttpClientFactory的次要指标是为了确保应用工厂模式创立HttpClient实例的同时防止socket耗尽。 ...

February 18, 2021 · 2 min · jiezi

关于c#:Qt开发Activex笔记三C调用Qt开发的Activex控件

若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/113789727 长期继续带来更多我的项目与技术分享,征询请加QQ:21497936、微信:yangsir198808 红瘦子(红模拟)的博文大全:开发技术汇合(蕴含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬联合等等)继续更新中…(点击传送门) Qt开发专栏:开发技术上一篇:《Qt开发Activex笔记(二):Qt调用Qt开发的Activex控件》下一篇:敬请期待... 前言 开发Activex控件,以供其余应用程序调用,本篇章解说C#调用Activex控件,不限于Qt开发的Activex控件。 Wpf要调用Activex控件,必要先用C#对Activex控件进行包装,而后提供给Wpf调用。 Demo C#调用Activex办法步骤一:注册activex控件 运行之前先要注册,应用Qt下自带的idc注册一下。 idc -regserver activeHelloWorldDemo.dll 步骤二:确认activeQt控件的clsid 查看一下,关上注册表并搜寻一下,确认clsid,如下图: "2F12BFB8-137D-4DC2-9A93-634EFE5A6DFC"步骤三:创立c#我的项目,引入com的dll 将注册的dll引入到我的项目中,如下图: 步骤四:代码中应用控件 步骤五:编写代码private void button1_Click(object sender, EventArgs e){ activeHelloWorldDemoLib.activeHelloWorldDemo dlg = new activeHelloWorldDemoLib.activeHelloWorldDemo(); dlg.show();} 源码using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;namespace trainSimulationDemo{ public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { } private void button1_Click(object sender, EventArgs e) { activeHelloWorldDemoLib.activeHelloWorldDemo dlg = new activeHelloWorldDemoLib.activeHelloWorldDemo(); dlg.show(); } }} ...

February 17, 2021 · 1 min · jiezi

关于c#:C高级篇初识LINQ

前言揭示:为了可能将知识点学得更加透彻、记得更加牢固 我会通过教学解说的形式把常识写下来 因为在过程中会让人从学生变成老师 这个过程会开掘出新的常识和观点 是一个自我思维切换而达成的常识深度开掘和晋升的过程 如果能帮忙到大家那就最好 如果有讲错的中央还请多多指教!我只是一只菜鸡 感激了解! 1、初识LINQ置信大家多多少少都在网上或者书里看到过LINQ这玩意,那它到底是个什么玩意呢?明天就和大家一起来学习下LINQ LINQ是集成到C#和VB .NET这些语言中用于提供查问数据能力的一个新特色 在关系型数据库中,数据被组织放入规范性很好的表中,并且通过简略而又弱小的语言SQL来进行拜访,然而程序中却与数据库相同,保留在类对象或构造中的数据差别很大,因而没有通用的查问语句来从数据结构中获取数据,自C#3.0引入LINQ后,咱们便有了查问对象数据的能力 就是说LINQ是C#提供给了咱们开发者一个疾速查问数据的能力 LINQ-----------让语言更柔美,让查问更便捷,让代码更杰出。 2、简略的LINQ案例先来一个示例,让大伙看看LINQ的魅力所在 要应用LINQ的话就要援用它所在的命名空间 using System.Linq; using System;using System.Collections.Generic;using System.Linq;namespace ConsoleApp1{ class GameText { public int gameID; //游戏ID public string gameName; //游戏名称 public string gameIntduced; //游戏介绍 public int gameSize; //游戏大小 } class Program { static List<GameText> game = new List<GameText>() { new GameText(){gameID = 1,gameName = "东凑西凑",gameIntduced = "这是一个2D实习面试我的项目",gameSize = 1}, new GameText(){gameID = 2,gameName = "同桌的你",gameIntduced = "这是一个青春校园题材的游戏",gameSize = 5}, }; static void Main(string[] args) { var res = from m in game where m.gameID > 1 select m.gameName; foreach (var item in res) { Console.WriteLine(item); } } }}次要看这个中央 ...

February 10, 2021 · 4 min · jiezi

关于c#:Win32Api-关闭当前应用

本文介绍Windows零碎下应用Win32API获取以后利用并敞开的办法。 思路应用EnumWindows接口枚举以后窗口;过滤掉不可用、暗藏、最小化的窗口;过滤掉子窗口;通过题目、类名过滤掉零碎窗口;应用PostMessage发送敞开窗口信息。具体实现// 过滤掉零碎的一些窗口private static string[] filterTitles = new string[1] { "program manager"};private static string[] filterClasses = new string[5] { "shell_traywnd", "workerw", "button", "progman", "windows.ui.core.corewindow"};private void CloseCurrentApp(){ CallBack sort = new CallBack(EnumCallback); EnumWindows(sort, 0); return;}private bool EnumCallback(IntPtr hwnd, int lParam){ string title = GetWindowText(hwnd); StringBuilder className = new StringBuilder(256); int nRet = GetClassName(hwnd, className, className.Capacity); if (nRet == 0) className.Append(""); if (!IsWindowVisible(hwnd)) return true; if (!IsWindowEnabled(hwnd)) return true; if (IsIconic(hwnd)) return true; // 过滤掉子窗口 IntPtr parent = GetParent(hwnd); string parentTitle = GetWindowText(parent); if (parent != IntPtr.Zero) { if (IsWindowVisible(parent) && IsWindowEnabled(parent)) return true; } IntPtr owner = GetWindow(hwnd, GW_OWNER); if (owner != IntPtr.Zero) { if (IsWindowVisible(owner) && IsWindowEnabled(owner)) return true; } if (!filterTitles.Contains(title.ToLower()) && !filterClasses.Contains(className.ToString().ToLower())) { PostMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0); Console.WriteLine("敞开窗口(句柄:{0}, 题目:{1})!", hwnd, title); #region 获取窗口信息 int processID = -1; long threadID = -1; processID = GetWindowThreadProcessId(hwnd, out threadID); bool isiconic = IsIconic(hwnd); uint gwlStyle = (uint)GetWindowLong(hwnd, GWL_STYLE); IntPtr hProcess = OpenProcess(ProcessAccessFlags.QueryInformation, false, processID); string fullPath = ""; if (hProcess != IntPtr.Zero) { int capacity = 1024; StringBuilder processName = new StringBuilder(capacity); QueryFullProcessImageName(hProcess, 0, processName, ref capacity); fullPath = processName.ToString(0, capacity); CloseHandle(hProcess); } Console.WriteLine("-------------------窗口info:---------------"); Console.WriteLine("====题目:{0} 句柄:{1}====", title, hwnd); Console.WriteLine("====父窗口题目:{0} 父窗口句柄:{1}====", parentTitle, parent); Console.WriteLine("====过程ID:{0} 类名:{1}====", processID, className.ToString()); Console.WriteLine("====过程名:{0}====", fullPath); Console.WriteLine("====isiconic:{0} 款式:{1}====", isiconic, gwlStyle); WINDOWPLACEMENT placement = new WINDOWPLACEMENT(); placement.length = System.Runtime.InteropServices.Marshal.SizeOf(placement); GetWindowPlacement(hwnd, ref placement); Console.WriteLine("====placement:{0}====", placement.showCmd); EnumPropsDelegate prop = new EnumPropsDelegate(EnumPropsProc); EnumProps(hwnd, prop); #endregion 获取窗口信息 return false; } return true;}private bool EnumPropsProc(IntPtr hwnd, IntPtr lpszString, IntPtr hData){ string propName = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(lpszString); Console.WriteLine("====属性:{0} 数据:{1}====", propName, hData); return true;}#region Win32Apipublic const int GWL_STYLE = (-16);public const int GWL_EXSTYLE = (-20);public const int GW_OWNER = 4;public const int WS_EX_TOOLWINDOW = 0x00000080;public const int WM_SYSCOMMAND = 0x0112;public const int WM_CLOSE = 0x10;public const int SC_CLOSE = 0xF060;public delegate bool CallBack(IntPtr hwnd, int lparam);public delegate bool EnumPropsDelegate(IntPtr hwnd, IntPtr lpszString, IntPtr hData);[DllImport("user32.dll")]public static extern int EnumWindows(CallBack x, int y);[DllImport("user32.dll", CharSet = CharSet.Auto)]internal static extern int GetWindowText(IntPtr hWnd, System.Text.StringBuilder lpString, int nMaxCount);[DllImport("user32.dll", CharSet = CharSet.Auto)]public static extern int GetWindowTextLength(IntPtr hWnd);[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]public static extern int GetClassName(IntPtr hWnd, System.Text.StringBuilder lpClassName, int nMaxCount);[DllImport("user32.dll")]public static extern bool IsWindowVisible(IntPtr hwnd);[DllImport("user32.dll")]public static extern bool IsWindowEnabled(IntPtr hwnd);[DllImport("user32.dll", EntryPoint = "IsIconic")]public static extern bool IsIconic(IntPtr hWnd);[DllImport("user32.dll", SetLastError = true)]public static extern IntPtr GetParent(IntPtr hwnd);[DllImport("user32.dll", SetLastError = true)]public static extern IntPtr GetWindow(IntPtr hwndParent, int nCmd);[DllImport("user32.dll", EntryPoint = "GetWindowLongA", SetLastError = true)]public static extern long GetWindowLong(IntPtr hwnd, int nIndex);[DllImport("user32.dll", EntryPoint = "PostMessageA", SetLastError = true)]public static extern bool PostMessage(IntPtr hwnd, uint Msg, uint wParam, uint lParam);[DllImport("user32.dll", EntryPoint = "GetWindowThreadProcessId", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]public static extern int GetWindowThreadProcessId(IntPtr hWnd, out long lpdwProcessId);[DllImport("kernel32.dll", SetLastError = true)]public static extern IntPtr OpenProcess( ProcessAccessFlags processAccess, bool bInheritHandle, int processId);[DllImport("kernel32.dll", SetLastError = true)]public static extern bool QueryFullProcessImageName([In]IntPtr hProcess, [In]int dwFlags, [Out]System.Text.StringBuilder lpExeName, ref int lpdwSize);[DllImport("coredll.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto)][return: MarshalAs(UnmanagedType.Bool)]public static extern bool CloseHandle(IntPtr hObject);[DllImport("user32.dll", SetLastError = true)][return: MarshalAs(UnmanagedType.Bool)]public static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);[DllImport("user32.dll")]public static extern int EnumProps(IntPtr hWnd, EnumPropsDelegate lpEnumFunc);public struct WINDOWPLACEMENT{ public int length; public int flags; public int showCmd; public System.Drawing.Point ptMinPosition; public System.Drawing.Point ptMaxPosition; public System.Drawing.Rectangle rcNormalPosition;}[Flags]public enum ProcessAccessFlags : uint{ All = 0x001F0FFF, Terminate = 0x00000001, CreateThread = 0x00000002, VirtualMemoryOperation = 0x00000008, VirtualMemoryRead = 0x00000010, VirtualMemoryWrite = 0x00000020, DuplicateHandle = 0x00000040, CreateProcess = 0x000000080, SetQuota = 0x00000100, SetInformation = 0x00000200, QueryInformation = 0x00000400, QueryLimitedInformation = 0x00001000, Synchronize = 0x00100000}public static string GetWindowText(IntPtr hwnd){ int capacity = GetWindowTextLength(hwnd) * 2; System.Text.StringBuilder lpString = new System.Text.StringBuilder(capacity); GetWindowText(hwnd, lpString, lpString.Capacity); if (lpString.Length > 0) { return lpString.ToString(); } return string.Empty;}#endregion Win32Api

February 6, 2021 · 3 min · jiezi

关于c#:一种圆形识别方案

本文介绍一种圆形的辨认计划。 辨认流程判断是否为关闭图形;依据圆的方程,取输出点集中的1/6、3/6、5/6处的三个点,求得圆的方程,获取圆心及半径;取点集中的局部点,计算点到圆心的间隔与半径的比例,与设定的阈值比拟,得出后果。~~~~实现public static bool IsCircle(List<Point> points, out Point center, out double radius){ int len = points.Count; center = new Point(); radius = 0; // 判断是否为关闭图形 if (!IsClosedFigure(points)) return false; int judgePointNum = len * 50 / 100; if (len < judgePointNum) return false; // 取链表上三个点作为判断圆的依据 Point p1 = points[len / 6]; Point p2 = points[len / 2]; Point p3 = points[len * 5 / 6]; if ((Math.Abs(p1.X - p2.X) < 100 && Math.Abs(p1.Y - p2.Y) < 100) || (Math.Abs(p1.X - p3.X) < 100 && Math.Abs(p1.Y - p3.Y) < 100) || (Math.Abs(p2.X - p3.X) < 100 && Math.Abs(p2.Y - p3.Y) < 100)) return false; // 三个点确定圆的方程,获取圆心坐标及半径 GetCircle(p1, p2, p3, out center, out radius); // 获取圆上均匀分部的多个点,判断其到圆心的间隔与半径之差是否在精度内 for (int i = 0; i < judgePointNum; ++i) { // 获取圆上点 Point p = points[len * i / judgePointNum]; double deviation = Math.Abs(GetDistance(center, p) - radius); // 点在圆上的偏移量与半径的比值若大于固定值,则不为圆 if (deviation/radius > MaxRatio) return false; } return true;}

February 6, 2021 · 1 min · jiezi

关于c#:进击吧Blazor第一章-4数据交互

《进击吧!Blazor!》是自己与张善友老师单干的Blazor零根底入门系列视频,此系列能让一个从未接触过Blazor的程序员把握开发Blazor利用的能力。视频地址:https://space.bilibili.com/48...演示代码:https://github.com/TimChen44/...本系列文章是基于《进击吧!Blazor!》直播内容编写,降级.Net5,改良问题,解说更全面。作者:陈超超Ant Design Blazor 我的项目贡献者,领有十多年从业教训,长期基于.Net技术栈进行架构与开发产品的工作,现就职于正泰团体。邮箱:timchen@live.com欢送各位读者有任何问题分割我,咱们共同进步。 上一次课程咱们实现了ToDo利用的界面制作,这次咱们要将客户端的数据写入数据库,并从数据库中读物咱们须要的数据。 数据交互过程咱们先看一下从客户端到数据库的流程 BlazorBlazor客户端就是咱们上节课做的ToDo程序。 HttpClientHttpClient就是咱们实现网络通讯用的组件,对于这类组件咱们心愿在一个利用中只结构一次,这样防止反复分配资源,因而咱们在Program.cs中进行注册。 public class Program{ public static async Task Main(string[] args) { builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); }}BaseAddress为基地址,这样咱们应用时,Url只须要传入绝对地址即可,此处默认为以后主机的地址。DefaultRequestHeaders 默认HTTP申请头参数Timeout 连贯超时参数 依赖关系注入下面通过服务注入的形式实现了HttpClient全局共享(单例),那么如何应用服务?这里咱们就须要引入一下“依赖关系注入 (DI)”的概念。 DI是一种技术,基本原理是把有依赖关系的类放到容器中,解析出这些类的实例,就是依赖注入。利用可通过将内置服务注入组件来应用这些服务。 利用还可定义和注册自定义服务,并通过 DI 使其在整个利用中可用。 该技术在 Blazor 利用中常用于以下两个方面: 服务生存期决定了服务何时创立,何时销毁,有三种模式: Scoped:Blazor WebAssembly 利用以后没有 DI 范畴的概念。 已注册 Scoped 的服务的行为与 Singleton 服务相似。 然而,Blazor Server 托管模型反对 Scoped 生存期。 在 Blazor Server 利用中,Scoped服务注册的范畴为“连贯”。 因而,即便以后用意是在浏览器中运行客户端,对于范畴应限定为以后用户的服务来说,首选应用 Scoped 服务。 Singleton:DI 创立服务的单个实例。 须要 Singleton 服务的所有组件都会接管同一服务的实例。 ...

February 5, 2021 · 6 min · jiezi

关于c#:Selenium爬虫实战截取网页上的图片

前言同样是为了刷课,没想到工作后仍然和大学一样逃脱不了须要刷网课的命运…… 注释间接说干货了,截取图片,须要截取的图片是什么图片大家都懂(说的就是你,验证码),其余图片的话不须要截取,间接拿到地址下载就行,验证码不行,同样的地址再拜访一次内容就变了。 我不晓得为啥selenium不能间接把特定img元素的图片拿进去,太反人类了。 依据我找到的材料,次要有两种思路,一种是模仿鼠标操作,在验证码下面点击右键,而后抉择另存为,把验证码保留到本地之后再来读取…… 我不了解为啥有这种这么思路清奇的操作,右键另存为的一个很大问题就是你基本没法管制图片存在那里,这也导致这个爬虫程序不具备通用性!所以间接pass掉。 另一种是先对整个网页截图,而后再依照验证码img元素的地位和大小,定位并且裁剪出小的验证码图片来,现实状况下是能够的,然而通过我屡次测试发现不同浏览器裁剪进去图片有不同偏移和缩放,不晓得是哪里出了问题,只能硬编码微调,吐了。只管办法不完满,然而也勉强够用吧,分享一下代码…… 代码这次是用C#(WinForm)做的,尽管只是代码片段,不过截图+裁剪保留局部还是能够参考一下的。 前面的验证码辨认是顺带加上的,用了百度的接口,准确率堪忧。 setStatusMsg1("正在提取验证码");var verifyCode = currentBrowser.WebDriver.FindElement(By.XPath("/html/body/spk-root/spk-login-page/div/section/div[3]/div[2]/div[2]/form/div[3]/div[2]/img"));setStatusMsg2("浏览器截屏");// 设置浏览器大小currentBrowser.WebDriver.Manage().Window.Size = new Size(1280, 800);// 浏览器截屏var screenshot = ((ITakesScreenshot)currentBrowser.WebDriver).GetScreenshot();var screenImagePath = Path.Combine(Path.GetTempPath(), $"{System.Guid.NewGuid().ToString("N")}.jpg");// 保留截屏图片setStatusMsg2("保留截屏");screenshot.SaveAsFile(screenImagePath, ScreenshotImageFormat.Jpeg);// 裁剪验证码setStatusMsg2("裁剪验证码");var codeImagePath = screenImagePath.Replace(".jpg", "_code.jpg");int x, y, width, height;// 应用js来获取图片的地位等信息switch (currentBrowser.BrowserType) { case BrowserEnum.Chrome: x = Convert.ToInt32((long)((IJavaScriptExecutor)currentBrowser.WebDriver).ExecuteScript("return document.querySelector('body > spk-root > spk-login-page > div > section > div.login-body.clearfix > div.login-right > div.form-con > form > div.qr-code > div.qrcode-box.clearfix > img').x")); y = Convert.ToInt32((long)((IJavaScriptExecutor)currentBrowser.WebDriver).ExecuteScript("return document.querySelector('body > spk-root > spk-login-page > div > section > div.login-body.clearfix > div.login-right > div.form-con > form > div.qr-code > div.qrcode-box.clearfix > img').y")); width = verifyCode.Size.Width; height = verifyCode.Size.Height; // 验证码地位调整 //x += 20; //y += 8; // 验证码大小调整 width += 30; height += 15; break; default: x = verifyCode.Location.X; y = verifyCode.Location.Y; width = verifyCode.Size.Width; height = verifyCode.Size.Height; break;}var codeBitmap = new Bitmap(width, height);var codeGraphics = Graphics.FromImage(codeBitmap);var destRec = new Rectangle(0, 0, width, height);var srcRec = new Rectangle(x, y, width, height);setStatusMsg2(srcRec.ToString());codeGraphics.DrawImage(new Bitmap(screenImagePath), destRec, srcRec, GraphicsUnit.Pixel);// 保留验证码图片codeBitmap.Save(codeImagePath, ImageFormat.Jpeg);// 显示图片picVerifyCode.Load(codeImagePath);picVerifyCode.Tag = codeImagePath;// 验证码辨认var result = BaiduAiSdk.VerifyCode(codeImagePath);if (result.Length > 0) { txtVerifyCode.Text = result; FrmTips.ShowTipsSuccess(this, $"验证码辨认胜利,辨认后果:{result}"); var input = currentBrowser.WebDriver.FindElement(By.XPath("/html/body/spk-root/spk-login-page/div/section/div[3]/div[2]/div[2]/form/div[3]/div[2]/input")); input.Clear(); input.SendKeys(result);} else FrmTips.ShowTipsError(this, "验证码辨认失败,请重试!");参考资料Python +Selenium解决图片验证码登录或注册问题:https://www.mscto.com/python/...python网课主动刷课程序-selenium+chromedriver:https://kaiwu.lagou.com/java_...selenium之 定位以及切换frame/iframe:https://blog.csdn.net/huilan_...Python 爬虫利器五之 Selenium 的用法:https://cuiqingcai.com/2599.html欢送交换程序设计实验室专一于互联网热门新技术摸索与团队麻利开发实际,在公众号「程序设计实验室」后盾回复 linux、flutter、c#、netcore、android、kotlin、java、python 等可获取相干技术文章和材料,同时有任何问题都能够在公众号后盾留言~ ...

February 5, 2021 · 1 min · jiezi

关于c#:一篇文章教你如何使用第三方控件构建多步向导界面

点击获取工具>> 利用好的界面控件,往往能做成比拟界面体验成果。在一些界面操作外面,咱们可能把它拆分为几部进行解决,这个时候引入WizardControl向导控件应该是比拟不错的抉择了。多步的解决形式,能够让用户防止一次性输出太多内容的焦躁情绪,也能够针对性的校验局部内容,本文以利用WizardControl控件来设计找回明码的后果来进行介绍,使大家对基于DevExpress的WizardControl向导控件的应用有一个大略的理解。 一、界面成果的布局在个别APP或者基于网络的软件界面外面,都有一个为了帮忙用户找回账号密码的性能,能够让用户自助通过手机、邮件等形式取得充值明码的机会。如个别的APP界面成果如下所示。 然而个别Winform的界面,能够利用向导控件做的更好,其中DevExpress的WizardControl向导控件就是一个很好的抉择。 咱们个别在DevExpress的VS工具栏外面抉择导航布局选项卡,就能够找到对应的WizardControl向导控件了。 最终咱们实现的成果如下所示。 二、控件的应用及代码解决下面介绍了,在在DevExpress的VS工具栏外面抉择导航布局选项卡,就能够找到对应的WizardControl向导控件了。 咱们拖动能这个控件到一个空白的窗体界面上,就能够看到默认有一些界面了,咱们在其中能够看到一个残缺的向导界面成果的。 拖动过去的控件,初始化界面成果都是英文的,能够通过控件属性对其中的文字进行批改即可。 批改后的界面成果如下所示。 而后咱们批改向导控件的一些属性,如图片、文字等内容,最初在其中空白的地位,拖入一些界面控件,实现咱们的界面成果即可。 另外默认的向导控件是三个界面页的,因而咱们能够依据须要减少或者删除一些,如本例我就移除了一个,仅仅应用两个页面来解决明码的找回解决即可。 另外,咱们为了实现向导控件界面的输出验证和解决,咱们往往还须要对其中下一步、实现、勾销、帮忙等事件进行解决,这样能力达到较好的解决成果。 其中局部解决代码如下所示。 private void wizardControl1_NextClick(object sender, DevExpress.XtraWizard.WizardCommandButtonClickEventArgs e){string pageText = e.Page.Text;if(pageText == "验证账号"){if (this.txtMobile.Text.Length == 0 || this.txtValidateCode.Text.Length == 0){MessageDxUtil.ShowTips("请输出手机号码和验证码");e.Handled = true;this.txtValidateCode.Focus();return;}else if(!ValidateUtil.IsValidMobile(this.txtMobile.Text)){MessageDxUtil.ShowTips("请输出正确的手机号码");e.Handled = true;this.txtMobile.Focus();return;}else{bool result = CallerFactory<ISmsCodeService>.Instance.CheckSmsCode(this.txtMobile.Text, this.txtValidateCode.Text);if (!result){MessageDxUtil.ShowTips("验证码校验不正确,请查看验证码是否在无效工夫内。");this.txtValidateCode.Focus();return;e.Handled = true;}}}else if(pageText == "重置明码"){MessageDxUtil.ShowTips(pageText);}} 在这些Next下一步事件外面,有一个代码是须要阻塞下一步的解决的。 e.Handled = true; 这样咱们就能够实现对用户输出的验证解决了,如果解决不通过,那么就停留在这个页面上,让用户校对输出即可。 如果是实现按钮页面,它的解决也是差不多。 private void wizardControl1_FinishClick(object sender, CancelEventArgs e){if (this.txtCorpAccount.Text.Length == 0){this.txtCorpAccount.Focus();MessageDxUtil.ShowTips("公司账号不能为空!");e.Cancel = true;return;}else if(this.txtNewPassword.Text.Length == 0){this.txtNewPassword.Focus();MessageDxUtil.ShowTips("明码不能为空!");e.Cancel = true;return;}else if (!this.txtNewPassword.Text.Equals(this.txtRePassword.Text)){this.txtRePassword.Focus();MessageDxUtil.ShowTips("两次明码不统一!");e.Cancel = true;return;} ...

February 1, 2021 · 1 min · jiezi

关于c#:Unity面向新手超简单的UI框架

前言揭示:为了可能将知识点学得更加透彻、记得更加牢固 我会通过教学解说的形式把常识写下来 因为在过程中会让人从学生变成老师 这个过程会开掘出新的常识和观点 是一个自我思维切换而达成的常识深度开掘和晋升的过程 如果能帮忙到大家那就最好 如果有讲错的中央还请多多指教!我只是一只菜鸡 感激了解! 为什么要应用UI框架游戏中存在十分多的面板 例如:背包面板、商店面板、设置面板、 这些面板之间会须要频繁的调用和切换,例如:背包面板中存在各种物品,咱们鼠标放到物品上会呈现物品信息的提示框,还有设置面板须要按返回键才能够切换回主菜单面板,那咱们如何实现界面间的沟通呢?我之前的做法就是在每个我要用到的面板上都写一个脚本实现对应的性能,置信不少老手开发者都是这样过去的吧。(纳尼菜逼竟是我本人?) 尽管这样做性能是实现了,然而维护性升高了、反复的代码也变多了,为了更加不便的治理和调用场景中的面板 咱们须要写一套残缺的框架来对它们进行束缚不然很容易呈现面板共存,或者切换失败等问题。 恰好SIKI老师有一套面向老手的小型UI框架课程讲得蛮好的,最重要的是简略啊!!! 对我这种老手来说真的十分敌对!咱们一起来学习下吧! 框架的思路先来简略介绍下这个框架的思路吧 ,框架次要实现了面板的读取存储和治理,帮忙咱们更好的进行面板之间的切换治理 首先1、咱们通过Json文件存储咱们所有要用到的面板信息 例如:面板的名字 面板的类型 面板的加载门路 等等,按理论我的项目需要为准 2、创立一个面板抽象类(就是所有面板的基类)来实现面板共有的一些办法,比方面板进入的时候要做的一些事件,面板退出时候要做的一些事件 3、通过代码读取Json文件失去所有面板的信息,而后咱们就能通过这些信息来操作面板 4、框架最外围的中央就是如何高效的治理这些面板 先来走一遍咱们面板的生成和敞开的流程 此时玩家只能操作背包面板,无奈操作人物面板(想想是不是很多游戏都是这样)当咱们想要操作人物面板的时候 咱们须要先敞开背包面板而后能力操作人物面板 这里再画一幅图来解释 当初咱们位于最下面的设置菜单中子菜单界面,此时咱们只能操作子菜单界面,如果咱们想操作设置菜单界面的话 咱们须要先敞开子菜单,能力操作设置菜单 当初子菜单敞开了,咱们就能够操作设置菜单了! 同理如果咱们想操作主菜单 那咱们就必须要敞开设置菜单能力去操作主菜单 所以Siki老师是如何治理面板之间切换关系的呢?理解过数据结构的同学看了下面的图可能马上就懂了!对的就是用堆栈(Stack)来实现 ,堆栈是一个后进先出的对象汇合 后进先出 先进后出?这不恰好能够用来存储管理咱们的面板吗 先进后出 最先进入的是主菜单,所以咱们把他放到了容器底部,而后玩家又点击了设置菜单,于是咱们把他放到主菜单的下面,而后玩家又点击了设置菜单里的子菜单,咱们把子菜单放到了设置菜单的下面 咱们让玩家只能操作栈中的顶部面板,通过Push把面板入栈(面板进入) 通过Pop把顶部面板出栈(面板退出) 这样就轻松实现了面板之间的切换性能了 好吧说实话我感觉我讲的是一坨屎(可能只有我本人能听懂 举荐间接去看Siki老师讲的) 实操思路理了一下!当初咱们一步一步来做吧! 1、创立Json文件,把面板信息写入到Json中首先咱们来实现第一步 咱们通过Json文件存储咱们所有要用到的面板信息 例如:面板的名字 面板的类型 面板的加载门路 等等,按理论我的项目需要为准 在创立Json文件之前,咱们须要先把要用到的面板做成预制体寄存到Resources门路下稍后通过Resources来加载这些咱们要用到的面板,这里我本人新建了一张图作为面板来演示,命名为“SettingPanel”寄存到Resources的UIPanel文件夹下 好当初咱们就来创立一个Json文件(新建一个文本文件 后缀改成.Json就是一个Json文件了,留神咱们Json文件也要放到Resources文件夹下因为咱们稍后会通过Resources来获取它) 并往里面写上咱们面板的信息,这里为了不便小伙伴们的了解我就写简略一点 json文件 { "data": [ {"uiPanelType":"settingPanel","uiPanelPath":"UIPanel/SettingPanel"} ]}这里简略讲下Json文件的格局吧 花括号{} 保留对象:对象能够蕴含各种数据,包含数组。方括号[] 保留数组:数组能够蕴含对象。数据由逗号分隔 ...

January 31, 2021 · 5 min · jiezi

关于c#:C语言特性及发展史

本文依照C#语言的倒退历史,介绍C#每个版本的新增个性,次要参考微软官网文档。理解这些语言个性能够帮忙咱们更高效的编写C#代码。 C# 1.0与Visual Studio .NET 2002一起公布,该版本的C#十分像Java。 类构造接口事件属性委托运算符和表达式语句个性:无效地将元数据或申明信息与代码相关联,从而在运行时应用反射查问个性C# 1.2随Visual Studio .NET 2003一起公布,次要是一些小改良。值得注意的是,从此版本开始,当IEnumerator实现IDisposable时,foreach循环中生成的代码会在IEnumerator上调用Dispose。 C# 2.0与Visual Studio 2005一起公布。自2.0开始,C#打好了根底,开始谋求解决一些重大影响开发者的难点。 泛型:应用泛型优于创立派生自ArrayList的ListInt或强制转换形式partial class匿名办法:delegate运算符创立一个能够转换为委托类型的匿名办法。从C# 3.0开始,可应用lambda表达式创立匿名办法。可空类型:可空类型T?示意其根底类型T的所有值及额定的null值。迭代器:容许应用foreach来查看List(或其它可枚举类型)中的所有项协变和逆变:实现数组类型、委托类型和泛型类型参数的隐式援用转换C# 3.0与Visual Studio 2008一起公布,但残缺性能是在.NET Framework 3.5版本中公布的。此版本标记着C#倒退过程中的重大更改。 主动实现的属性:C# 6及更高版本可像字段一样对其初始化匿名类型查问表达式lambda表达式表达式树扩大办法:无需创立派生类、从新编译或其它形式即可向现有类型增加办法varpartial method:partial class的一部分定义签名,一部分定义实现对象汇合初始化语法:new后应用{}进行初始化C# 4.0随Visual Studio 2010一起公布。 动静绑定:dynamic关键字命名参数/可选参数:命名参数指定参数实参,不需匹配参数列表地位泛型协变和逆变嵌入互操作类型:CLR反对将COM类型信息间接嵌入到托管程序集中,不要求托管程序集从互操作程序集中获取COM类型的类型信息,弛缓了部署难点C# 5.0随Visual Studio 2012一起公布,次要工作是实用于异步编程的async和await模型。 异步成员:语言级别的异步编程模型,外围是Task和Task<T>对象,承受关键字async和await的反对调用方信息个性C# 6.0随Visual Studio 2015一起公布。 动态导入:using static指令when:用于catch语句和switch语句主动属性初始化表达式:属性的get/set拜访器可应用=>简化语法=>运算符Null流传器:仅当操作数的计算结果为非null时,null条件运算符才会将成员拜访?.或元素拜访?[]运算利用于其操作数,否则返回null字符串内插:$特殊字符将字符串文本标识为内插字符串nameof运算符C# 7.0与Visual Studio 2017一起公布。 out变量:能够在办法调用的参数列表中申明out变量,无需独自编写申明语句元组和析构函数:能够创立蕴含多个公共字段的轻量级未命名类型模式匹配:反对is表达式和switch表达式。is模式表达式可在一条指令调配后果:input is int count本地函数:实用于迭代器办法和异步办法,在办法外部申明办法扩大expression bodied成员:可在属性、索引器、结构、析构、get/set拜访器应用=>ref局部变量和返回后果throw表达式:throw可作为表达式而不是语句C# 7.1 7.2 7.3此版本开始C#能够单点发行,编译器有-refout和-refonly两个选项,可用于管制援用程序集生成。 async Main办法:可在Main办法中应用await关键字default文本表达式启用更高效的平安代码private protected拜访修饰符条件ref表达式:条件表达式?:的援用而不是值无需固定即可拜访固定的字段能够重新分配ref本地变量能够应用stackalloc数组上的初始值设定项能够对反对模式的任何类型应用fixed语句能够应用其余泛型束缚C# 8.0专门面向.NET Core的第一个次要C#版本。 readonly成员:可将readonly修饰符用于struct成员默认接口办法:可将成员增加到接口并提供实现模式匹配加强性能:在更多地位应用,联合switch表达式(不是switch语句),可用于属性模式、元组模式、地位模式using申明:带using关键字的变量申明,批示编译器在关闭范畴的开端解决变量动态本地函数可处理的ref构造可空援用类型异步流:创立并以异步形式应用流索引和范畴:为拜访序列中的单个或范畴元素提供了简洁语法。依赖两个新运算符:开端运算符^和范畴运算符..null合并赋值:仅当左操作数为null时,能力应用??=运算符将右操作数赋给左操作数非托管构造类型嵌套表达式中的stackalloc内插逐字字符串的加强性能:$和@程序可任意安顿C# 9.0.NET 5.0反对C# 9.0 record类型:不可变的援用类型,应用值语义实现相等性仅限init的资源库:可为属性和索引器创立init拜访器而非set拜访器,结构完变为只读顶级语句:应用程序中只有一个文件可应用顶级语句模式匹配加强性能:and/or/not,如if (e is not null) ...性能和互操作性调整和实现性能:如在new表达式中省略类型:private List<int> nums = new();反对代码生成器

January 30, 2021 · 1 min · jiezi

关于c#:使用JWT创建安全的ASPNET-Core-Web-API

在本文中,你将学习如何在ASP.NET Core Web API中应用JWT身份验证。我将在编写代码时逐渐简化。咱们将构建两个终结点,一个用于客户登录,另一个用于获取客户订单。这些api将连贯到在本地机器上运行的SQL Server Express数据库。 JWT是什么? JWT或JSON Web Token基本上是格式化令牌的一种形式,令牌示意一种通过编码的数据结构,该数据结构具备紧凑、url平安、平安且自蕴含特点。 JWT身份验证是api和客户端之间进行通信的一种规范形式,因而单方能够确保发送/接管的数据是可信的和可验证的。 JWT应该由服务器收回,并应用加密的平安密钥对其进行数字签名,以便确保任何攻击者都无奈篡改在令牌内发送的无效payload及模仿非法用户。 JWT构造包含三个局部,用点隔开,每个局部都是一个base64 url编码的字符串,JSON格局: Header.Payload.Signature: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiIxIiwicm9sZSI6IkFjY291bnQgTWFuYWdlciIsIm5iZiI6MTYwNDAxMDE4NSwiZXhwIjoxNjA0MDExMDg1LCJpYXQiOjE2MDQwMTAxODV9.XJLeLeUIlOZQjYyQ2JT3iZ-AsXtBoQ9eI1tEtOkpyj8Header:示意用于对秘钥进行哈希的算法(例如HMACSHA256) Payload:在客户端和API之间传输的数据或申明 Signature:Header和Payload连贯的哈希 因为JWT标记是用base64编码的,所以能够应用jwt.io简略地钻研它们或通过任何在线base64解码器。 因为这个非凡的起因,你不应该在JWT中保留对于用户的机密信息。 筹备工作: 下载并装置Visual Studio 2019的最新版本(我应用的是Community Edition)。 下载并装置SQL Server Management Studio和SQL Server Express的最新更新。 开始咱们的教程 让咱们在Visual Studio 2019中创立一个新我的项目。我的项目命名为SecuringWebApiUsingJwtAuthentication。咱们须要抉择ASP.NET Core Web API模板,而后按下创立。Visual Studio当初将创立新的ASP.NET Core Web API模板我的项目。让咱们删除WeatherForecastController.cs和WeatherForecast.cs文件,这样咱们就能够开始创立咱们本人的控制器和模型。 筹备数据库 在你的机器上装置SQL Server Express和SQL Management Studio, 当初,从对象资源管理器中,右键单击数据库并抉择new database,给数据库起一个相似CustomersDb的名称。 为了使这个过程更简略、更快,只需运行上面的脚本,它将创立表并将所需的数据插入到CustomersDb中。 USE [CustomersDb]GO/****** Object: Table [dbo].[Customer] Script Date: 11/9/2020 1:56:38 AM ******/SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [dbo].[Customer]( [Id] [int] IDENTITY(1,1) NOT NULL, [Username] [nvarchar](255) NOT NULL, [Password] [nvarchar](255) NOT NULL, [PasswordSalt] [nvarchar](50) NOT NULL, [FirstName] [nvarchar](255) NOT NULL, [LastName] [nvarchar](255) NOT NULL, [Email] [nvarchar](255) NOT NULL, [TS] [smalldatetime] NOT NULL, [Active] [bit] NOT NULL, [Blocked] [bit] NOT NULL, CONSTRAINT [PK_Customer] PRIMARY KEY CLUSTERED ( [Id] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, _ ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]GO/****** Object: Table [dbo].[Order] Script Date: 11/9/2020 1:56:38 AM ******/SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [dbo].[Order]( [Id] [int] IDENTITY(1,1) NOT NULL, [Status] [nvarchar](50) NOT NULL, [Quantity] [int] NOT NULL, [Total] [decimal](19, 4) NOT NULL, [Currency] [char](3) NOT NULL, [TS] [smalldatetime] NOT NULL, [CustomerId] [int] NOT NULL, CONSTRAINT [PK_Order] PRIMARY KEY CLUSTERED ( [Id] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, _ ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]GOSET IDENTITY_INSERT [dbo].[Customer] ON GOINSERT [dbo].[Customer] ([Id], [Username], [Password], [PasswordSalt], _ [FirstName], [LastName], [Email], [TS], [Active], [Blocked]) _ VALUES (1, N'coding', N'ezVOZenPoBHuLjOmnRlaI3Q3i/WcGqHDjSB5dxWtJLQ=', _ N'MTIzNDU2Nzg5MTIzNDU2Nw==', N'Coding', N'Sonata', N'coding@codingsonata.com', _ CAST(N'2020-10-30T00:00:00' AS SmallDateTime), 1, 1)GOINSERT [dbo].[Customer] ([Id], [Username], [Password], [PasswordSalt], _ [FirstName], [LastName], [Email], [TS], [Active], [Blocked]) _ VALUES (2, N'test', N'cWYaOOxmtWLC5DoXd3RZMzg/XS7Xi89emB7jtanDyAU=', _ N'OTUxNzUzODUyNDU2OTg3NA==', N'Test', N'Testing', N'testing@codingsonata.com', _ CAST(N'2020-10-30T00:00:00' AS SmallDateTime), 1, 0)GOSET IDENTITY_INSERT [dbo].[Customer] OFFGOSET IDENTITY_INSERT [dbo].[Order] ON GOINSERT [dbo].[Order] ([Id], [Status], [Quantity], [Total], [Currency], [TS], _ [CustomerId]) VALUES (1, N'Processed', 5, CAST(120.0000 AS Decimal(19, 4)), _ N'USD', CAST(N'2020-10-25T00:00:00' AS SmallDateTime), 1)GOINSERT [dbo].[Order] ([Id], [Status], [Quantity], [Total], [Currency], [TS], _ [CustomerId]) VALUES (2, N'Completed', 2, CAST(750.0000 AS Decimal(19, 4)), _ N'USD', CAST(N'2020-10-25T00:00:00' AS SmallDateTime), 1)GOSET IDENTITY_INSERT [dbo].[Order] OFFGOALTER TABLE [dbo].[Order] WITH CHECK ADD CONSTRAINT [FK_Order_Customer] _ FOREIGN KEY([CustomerId])REFERENCES [dbo].[Customer] ([Id])GOALTER TABLE [dbo].[Order] CHECK CONSTRAINT [FK_Order_Customer]GO筹备数据库模型和DbContext创立实体文件夹,而后增加Customer.cs: ...

January 30, 2021 · 8 min · jiezi

关于c#:如何创建一个验证请求的API框架

开发一款胜利软件的要害是良好的架构设计。优良的设计不仅容许开发人员轻松地编写新性能,而且还能丝滑的适应各种变动。 好的设计应该关注应用程序的外围,即畛域。 可怜的是,这很容易将畛域与不属于这一层的职责混同。每减少一个性能,就会使了解外围畛域变得更加艰难。同样蹩脚的是,未来就更难重构了。 因而,爱护畛域层不受利用程序逻辑影响是很重要的。其中一个优化是对传入申请的验证。为了避免验证逻辑渗透到畛域级别,咱们心愿在申请达到畛域级别之前验证申请。 在这篇文章中,咱们将学习如何从畛域层中提取验证。在咱们开始之前,本文假如API应用command模式将传入申请转换为命令或查问。本文中所有的代码片段都应用了MediatR。 command模式的益处是将外围逻辑从API层分离出来。大多数实现command模式的库也公开了能够连贯到其中的中间件。这很有用,因为它提供了一个解决方案,能够增加须要与每个命令一起执行的利用程序逻辑。 MediatR申请 应用C# 9中引入的record类型,它能够把申请变成一行代码。另一个益处是,实例是不可变的,这使得所有变得可预测和牢靠。 record AddProductToCartCommand(Guid CartId, string Sku, int Amount) : MediatR.IRequest; 为了散发上述命令,能够将传入的申请映射到控制器中。 [ApiController][Route("[controller]")]public class CustomerCartsController : ControllerBase{ private readonly IMediator _mediator; public CustomerCartsController(IMediator mediator) => _mediator = mediator; [HttpPost("{cartId}")] public async Task<IActionResult> AddProductToCart(Guid cartId, [FromBody] CartProduct cartProduct) { await _mediator.Send(new AddProductToCartCommand(cartId, cartProduct.Sku, cartProduct.Amount)); return Ok(); }}MediatR验证 咱们将应用MediatR管道,而不是在控制器中验证AddProductToCartCommand。 通过应用管道,能够在处理程序解决命令之前或之后执行一些逻辑。在这种状况下,提供一个集中的地位,在命令达到处理程序(畛域)之前在该地位对其进行验证。当命令达到它的处理程序时,咱们不再须要放心命令是否无效。 尽管这看起来是一个微不足道的更改,但它清理了畛域层中每个处理程序。 现实状况下,咱们只心愿在畛域中解决业务逻辑。删除验证逻辑解放了咱们的思维,这样咱们就能够更关注业务逻辑。因为验证逻辑是集中的,它确保所有命令都失去验证,而没有一条命令漏过破绽。 在上面的代码片段中,咱们创立了一个ValidatorPipelineBehavior来验证命令。当命令被发送时,ValidatorPipelineBehavior处理程序在它达到畛域层之前接管命令。ValidatorPipelineBehavior通过调用对应于该类型的验证器来验证该命令是否无效。只有当申请无效时,才容许将申请传递给下一个处理程序。如果没有,则抛出InputValidationException异样。 咱们将看看如何应用FluentValidation在验证中创立验证器。当初,重要的是要晓得,当申请有效时,将返回验证音讯。验证的细节被增加到异样中,稍后将用于创立响应。 public class ValidatorPipelineBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>{ private readonly IEnumerable<IValidator<TRequest>> _validators; public ValidatorPipelineBehavior(IEnumerable<IValidator<TRequest>> validators) => _validators = validators; public Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next) { // Invoke the validators var failures = _validators .Select(validator => validator.Validate(request)) .SelectMany(result => result.Errors) .ToArray(); if (failures.Length > 0) { // Map the validation failures and throw an error, // this stops the execution of the request var errors = failures .GroupBy(x => x.PropertyName) .ToDictionary(k => k.Key, v => v.Select(x => x.ErrorMessage).ToArray()); throw new InputValidationException(errors); } // Invoke the next handler // (can be another pipeline behavior or the request handler) return next(); }}应用FluentValidation进行验证 ...

January 28, 2021 · 3 min · jiezi

关于c#:C基础篇Hello-Wrold

前言揭示:为了可能将知识点学得更加透彻、记得更加牢固 我会通过教学解说的形式把常识写下来 因为在过程中会让人从学生变成老师 这个过程会开掘出新的常识和观点 是一个自我思维切换而达成的常识深度开掘和晋升的过程 如果能帮忙到大家那就最好 如果有讲错的中央还请多多指教!我只是一只菜鸡 感激了解! 1、Hello World程序在学习编程语言之前我要揭示大家一下 学习编程语言最禁忌的一点就是 只看不写 看的时候 大脑:嗯太简略了 我会了! 手:不 你不会 ! 等写的时候就发现 都是些什么玩意 所以咱们肯定要动起手来写 废话不多说 咱们关上vistudio studio编译器 也能够不是VS用你们棘手的就行 新建一个控制台利用我的项目 咱们先从一段简略的代码学起 先来看看执行后果 输入了Hello World! using System;namespace ConsoleApp1{ class Program { static void Main(string[] args) { Console.WriteLine("Hello World!"); Console.ReadKey(); } }}咱们来看看一个简略的C#程序结构 using System : 援用名称为System的命名空间namespace ConsoleApp1 :申明ConsoleApp1命名空间 申明后咱们就能够通过using来援用class Program :申明一个Program类Main :程序的入口点Console.WriteLine() :将信息输入到屏幕(就是咱们的控制台窗口)咱们只所以在控制台窗口看到Hello World! 就是这句话的作用 咱们能够自行批改看看成果 咱们把要输入的语句改一下Console.WriteLine("我只是一只Unity小菜鸡"); 控制台窗口就能看到输入了一句 我只是一只Unity小菜鸡 Console.ReadKey() :期待用户按下任意键 为了防止程序编译完后一闪而过 能够把这句话删掉看看有什么变动认真点看 咱们能够发现在这段代码中所有的语句和表达式都要以;分号结尾像这条语句 结尾的时候都会带一个;分号 ...

January 24, 2021 · 1 min · jiezi

关于c#:进击吧Blazor第一章-2Hello-Blazor

作者介绍 陈超超Ant Design Blazor 我的项目贡献者领有十多年从业教训,长期基于.Net技术栈进行架构与开发产品的工作,Ant Design Blazor 我的项目贡献者,现就职于正泰团体 第二次写专栏,结尾还是不晓得说什么,所以……先来段广告????《进击吧!Blazor!》是自己与张善友老师单干的Blazor零根底入门系列视频,此系列能让一个从未接触过Blazor的程序员把握开发Blazor利用的能力。视频地址:https://space.bilibili.com/48...本系列文章是基于《进击吧!Blazor!》直播内容编写,降级.Net5,改良问题,解说更全面。每一个教程的第一个Demo都是Hello,巧了,Blazor的默认模板就是一个现成的Hello Blazor,咱们就从他的默认模板开始。 环境介绍IDE:Visual Studio 16.8 创立我的项目 抉择Blazor利用设置项目名称,这里我取名“BlazorToDo”是因为接下来第一个残缺Demo是一个待办事项小程序。抉择Blazor利用模式,咱们接下来开发次要以Blazor WebAssembly App进行。ASP.NET Core hosted选项用于管制是否生成带有托管Blazor程序的ASP.NET Core服务端程序,咱们勾上。咱们将BlazorToDo.Server设为启动项,而后启动,应该能看到Hello, world!到这里Hello Blazor我的项目创立结束????我的项目构造下图是我的项目构造 BlazorToDo.ClientBlazor我的项目,自身就是一个Asp.Net Core我的项目,如果只做前端,就能够间接拿这个我的项目进行公布和部署。之后咱们的分享就围绕着这个我的项目进行。 Program.cs程序入口,这里与Web我的项目的差别就是Builder应用了WebAssemblyHostBuilder。 public static async Task Main(string[] args){ var builder = WebAssemblyHostBuilder.CreateDefault(args); builder.RootComponents.Add<App>("#app"); builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); await builder.Build().RunAsync();}_Imports.razor全局导入配置,在这里应用using引入后,相当于在所有razor文件中都进行了引入。 App.razorBlazor的根组件,通过Program.cs中的builder.RootComponents.Add<App>进行映射。 wwwroot动态文件寄存地位,用处和Aps.net core雷同,外面的index.html文件就是主页 <!--index.html--><body> <div id="app">Loading...</div> <div id="blazor-error-ui"> An unhandled error has occurred. <a href="" class="reload">Reload</a> <a class="dismiss">????</a> </div> <script src="_framework/blazor.webassembly.js"></script></body> Program.cs文件中builder.RootComponents.Add<App>("#app");中的选择器#app必须能在index.html中找到正确的元素,不然程序无奈失常显示。 Pages业务组件寄存地位,Blazor都是由组件组成的,页面就是含有路由配置的组件。组件文件扩展名razor,天然应用的是Razor语法,以Index.razor文件为例,代码如下 @page "/"<h1>Hello, world!</h1>Welcome to your new app.<SurveyPrompt Title="How is Blazor working for you?" />Razor语法的应用办法在后续分享中重点介绍,此处就不开展了。 ...

January 22, 2021 · 1 min · jiezi

关于SegmentFault:美化应用的标签式表单这个方法值得Get

点击获取工具>> Tabbed Form (TabForm)提供了许多Web浏览器中的选项卡式UI,与其余选项卡容器不同,Tabbed Form中的选项卡能够嵌入到表单的标题栏中或显示在标题栏的正下方。 您还能够在选项卡旁边显示其余按钮,这些按钮将实现自定义性能。 TIP:您能够应用Form Assistant组件将表单转换为Tabbed Form。 TIP:通过应用DevExpress Project Template Gallery,只需单击即可创立基于Tabbed Form的残缺选项卡UI应用程序。 通过Tabbed Form,您和您的最终用户能够应用"Add ( + )"选项卡来创立有限数量的选项卡。 如果在设计时创立了选项卡,则能够通过将控件增加到相应的内容容器来填充其内容。 如果选项卡是用代码创立的,则能够通过解决专用事件在其中填充内容。 Tabbed Form的次要性能包含: 任意数量的选项卡选项卡能够显示在标题栏的正下方或正下方最终用户能够在运行时应用内置的Add ("+") 按钮增加选项卡选项卡中的图像敞开选项卡中的按钮将选项卡页拖离以后表单来创立独自的表单自定义外观选项卡旁边的自定义按钮

January 20, 2021 · 1 min · jiezi

关于c#:springcloud-使用初谈二网关

这里说的是zuul 服务过滤 自定义过滤器的实现,须要继承ZuulFilter,须要重写实现上面四个办法: 四个具备4个基本特征:过滤类型、执行程序、执行条件、具体操作filterType:返回一个字符串代表过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型,具体如下:pre:能够在申请被路由之前调用routing:在路由申请时候被调用post:在routing和error过滤器之后被调用error:解决申请时产生谬误时被调用filterOrder:通过int值来定义过滤器的执行程序shouldFilter:返回一个boolean类型来判断该过滤器是否要执行,所以通过此函数可实现过滤器的开关。在上例中,咱们间接返回true,所以该过滤器总是失效。run:过滤器的具体逻辑。须要留神,这里咱们通过ctx.setSendZuulResponse(false)令zuul过滤该申请,不对其进行路由,而后通过ctx.setResponseStatusCode(401)设置了其返回的错误码,当然咱们也能够进一步优化咱们的返回,比方,通过ctx.setResponseBody(body)对返回body内容进行编辑等。 最初,总结一下为什么服务网关是微服务架构的重要局部,是咱们必须要去做的起因:不仅仅实现了路由性能来屏蔽诸多服务细节,更实现了服务级别、平衡负载的路由。实现了接口权限校验与微服务业务逻辑的解耦。通过服务网关中的过滤器,在各生命周期中去校验申请的内容,将本来在对外服务层做的校验前移,保障了微服务的无状态性,同时升高了微服务的测试难度,让服务自身更集中关注业务逻辑的解决。实现了断路器,不会因为具体微服务的故障而导致服务网关的阻塞,仍然能够对外服务。 Zuul 和 nginx的性能比照 论断:Zuul的原始性能十分靠近于Nginx。事实上,在启动预热之后,我的测试后果甚至略好一些(重申免责申明-这并非一个庄重的基准性能测试)。Nginx显示出更多的可预测性能(变动较小),可悲的是在Zuul预热期间,咱们经验了一些小故障(150000个申请中的2个,然而您的微服务应该是容错机制的,对吧?)。 Zuul解决Cookie和重定向 本文来源于:程序员ken,专属平台有csdn、思否(SegmentFault)、 简书、 开源中国(oschina)、掘金,转载请注明出处。

January 19, 2021 · 1 min · jiezi

关于c#:反射

元数据元数据是用一系列表来存储的,生成一个程序集或模块时,编译器会创立一个类型定义表、一个字段定义表、一个办法定义表以及其它表。 反射程序运行的时候解析这些元数据表以获取信息,该行为便是反射。反射容许在运行时发现并应用编译时还不理解的类型及其成员。 反射的性能反射会造成编译时无奈保障类型安全性。反射须要重度依赖字符串,所以会丢失编译时的类型平安。例如执行Type.GetType("A"),在一个程序集中查找类型名为“A”的类型,但程序集理论蕴含的类型可能是“AA”,代码会通过编译,但运行时会出错。反射速度慢,应用反射时,类型及其成员的名称在编译时未知,要应用字符串名称标识每个类型及其成员,以便在运行时发现它们。也就是说在扫描程序集的元数据时,反射要一直的执行字符串的搜寻,而字符串的搜寻执行的是不辨别大小写的比拟,这会进一步影响速度。反射调用一个成员时也会对性能产生影响反射调用办法时,首先必须将实参打包成一个数组,在外部反射必须将这些实参解包到线程栈上。此外在调用办法前,CLR必须查看实参具备正确的数据类型,最初CLR还需确保调用者有正确的平安权限来拜访被调用的成员。 *综上所述,最好防止应用反射技术来拜访字段或者调用办法。 获取Type对象的几种形式Type的静态方法GetType:接管一个string参数,必须指定类型的全名(包含命名空间),如果调用程序集没有定义指定的类型,就查找MSCorLib.dll定义的类型,如果还是没找到就返回nullType的静态方法ReflectionOnlyGetType:行为与GetType类似,只是类型会加载到一个“仅反射”上下文中,不能执行构造类型的实例Activator的静态方法CreateInstance:调用该办法能够传递一个Type对象援用,也能够传递标识了想要创立的类型的一个String。其中间接获取一个类型对象的几个重载版本绝对简略,为类型的结构器传递一组实参,办法返回的是对新对象的一个援用。而应用字符串来指定所需类型的几个重载版本要略微简单一些,首先必须指定另一个字符串来标识定义了类型的那个程序集。其次这些版本返回的不是对新对象的援用,而是一个System.Runtime.Remoting.ObjectHandle对象。ObjectHandle类型容许将一个AppDomain中创立的对象传至其它AppDomain,期间不强制对象具体化,要具体化该对象能够调用ObjectHandle对象的Unwrap办法。在一个AppDomain中调用这个办法时,它会将定义了要具体化的类型的程序集加载到这个AppDomain中。如果对象按援用封送就创立代理类型和对象。如果按值封送,对象的正本会被反序列化。Activator的静态方法CreateInstanceFrom:行为与CreateInstance办法类似,不同的是必须通过字符串来指定类型及其程序集。程序集要应用Assembly的LoadFrom(而非Load)办法加载到调用的AppDomain中。因为没有接管Type参数的版本,所以返回的都是ObjectHandle对象的援用,必须调用ObjectHandle的Unwrap办法进行具体化结构泛型类型的实例static void Main(){ //获取泛型类型的类型对象的一个援用 Type temp = typeof(List<>); //应用int类型关闭泛型类型 Type closedType = temp.MakeGenericType(typeof(int)); //结构关闭类型的实例 object o = Activator.CreateInstance(closedType); Console.WriteLine(o.GetType());}运行后果 发现类型成员字段、结构器、办法、属性、事件和嵌套类型都能够被定义为类型的成员。FCL蕴含一个System.Reflection.MemberInfo的类型,封装了一组所有类型都通用的属性。层次结构图如下: 查问一个类型的成员并显示与之相干的一些信息static void Main(){ Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); //遍历AppDomain中加载的所有程序集 foreach (var item in assemblies) { Console.WriteLine("Assembly: {0}", item); //查找程序集中的类型 foreach (var t in item.GetExportedTypes()) { Console.WriteLine("Type: {0}", t); //发现类型成员 const BindingFlags bf = BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static; foreach (var mi in t.GetMembers(bf)) { var typeName = string.Empty; if (mi is Type) typeName = "Type"; else if (mi is FieldInfo) typeName = "FieldInfo"; else if (mi is MethodInfo) typeName = "MethodInfo"; else if (mi is ConstructorInfo) typeName = "ConstructorInfo"; else if (mi is PropertyInfo) typeName = "PropertyInfo"; else if (mi is EventInfo) typeName = "EventInfo"; Console.WriteLine("mi typeName: {0}", typeName); } } }}BindingFlags枚举(筛选返回的成员类型)Default:指定未定义任何绑定标记IgnoreCase:返回与指定字符串匹配的成员(疏忽大小写)DeclaredOnly:只返回被反射的那个类型的成员,疏忽继承的成员Instance:返回实例成员Static:返回动态成员Public:返回公共成员NonPublic:返回非公共成员FlattenHierarchy:返回基类型定义的公共成员和受爱护动态成员遍历反射对象模型图 ...

January 18, 2021 · 3 min · jiezi

关于c#:浅谈Winform程序的界面布局设计

点击获取工具>>从事Winform开发很多年了,因为我的项目的须要,设计过各种各样的界面成果。一般来说,使用传统的界面控件元素,正当设计布局,可能设计出比拟中规中矩的规范界面;利用一些换肤的控件或者局部界面组件,可能设计出绝对难看一些的界面成果,如以前很流行的ActiveSkin、IrisSkin和DotNetSkin等,这些可能对传统的界面元素进行换肤,的确比规范灰色的界面控件难看了很多。不过随着界面控件的组件倒退,目前个别偏向于是用较为大型的控件组,他们除了提供设计得体的界面控件外,还提供了十分多种绚丽多彩的界面款式供选择,如DotNetBar、netadvantage、DevExpress等大型界面控件组。 无论界面设计如何变动,个别根本准则都是为客户提供直观、易用、体验成果较好的界面成果哦,从Office的倒退历程咱们也能够看到整体的界面成果趋势,从开始的规范控件到目前的Ribbon窗体,从单色调变动到绚丽多彩的界面款式,都给咱们提供很好的界面设计参考,大型的界面组件也是模拟这一趋势。言归正传,咱们来谈谈具体一点的货色,目前我趋向于采纳一种基于Ribbon款式的界面,以及一种基于传统界面联合OutLook款式的界面设计。 一、基于Ribbon款式的界面 以上的界面款式,是一种比拟大气、合乎Office界面成果的界面布局,通过把不同的功能块集中在不同的面板上显示,的确简洁、好看很多,本文不反复介绍该界面成果的优劣,咱们次要来集中看看上面的另外一种界面成果。 二、基于OutLook款式的界面设计其实OutLook款式很早就有,也能够在很多公开的控件组中看到,如果仅仅是谋求局部的OutLook界面成果,而不是整体性的计划,那么CodeProject上的这款开源Outlook组件,预计是其中的佼佼者(http://www.codeproject.com/Articles/43181/A-Serious-Outlook-Style-Navigation-Pane-Control)。不过因为需要的是整体性成果,而且还要思考更多控件界面款式的一致性及好看性,因而咱们还是基于DevExpress界面组来设计这样的OutLook界面成果,会显得更加美观大方一点。界面成果如下所示。 以上通过把一个零碎很多相干的功能模块放到一颗树上进行分类展现,对于一个比较复杂的人力资源管理系统或者其余简单性能的零碎,也是一个比拟正当的布局形式,另外OutLook工具条还是能够暗藏起来,节俭左边多文档界面的数据展现空间,这样整体还是比拟正当及好看的。其中左边的布局,还能够通过SplitContainer形式把它分成多个模块,而后客户想哪个数据显示面板大一点,拖动一下就能够了,这样不至于数据比拟多的时候,导致显示布局不好的状况。上面咱们来介绍下如何实现以上的界面布局成果。 创立一个基于DevExpress.XtraEditors.XtraForm基类的窗体。如下代码所示:`public partial class MainForm : DevExpress.XtraEditors.XtraForm{public MainForm(){InitializeComponent();}}` 在界面设计中,在DevExpress工具箱Navigation & Layout外面拖动增加一个BarManager控件到窗体中,并删除默认的工具栏Tools,并增加一些菜单项和状态条数据。如下所示。 增加PanelControl和NavBarControl,增加一些测试性能按钮。因为咱们须要应用MDI多文档界面成果,因而先设置Mainform的IsMdiContainer属性为True。 而后增加一个PanelControl,设置其Dock为Top布局,为该控件ContentImage设置一个背景图片(当时用PS设计好,保留为png格局即可),增加几个小Lable,设置其的图片和文字。 最初拖入一个NavBarControl控件到界面中,设置其Dock为Left布局,通过控件的右键菜单上的“Run Designer"进入设计界面,先轻易增加一些NavBarGroup和NavBarItem我的项目,粗略设置失去界面成果如下所示。 留神,在NavBarcontrol外面,默认是没有一个Panel能够增加一些非凡的控件,如树、按钮等,默认只有BarItem对象能够增加进入。为了在一个NavBarGroup外面增加这样的控件,须要批改NavBarGroup的属性才行,如下所示。 增加DockManager和XtraTabbedMdiManager 控件实现多文档布局,其最终将以Tab形式进行展示。持续在下面的窗体中增加DockManager控件和XTraTabbedMdiManager控件,这两个控件能够实现在左边以Tab形式展示多文档布局,这样对用户操作来说,能够一次性关上多个窗体进行操作,不便很多,也必将好看,是一种常见的布局展示。为了在窗体激活的时候,在顶部显示敞开按钮,其余的不显示,那么须要设置XTraTabbedMdiManager控件的ClosePageButtonShowMode=InActiveTabPageHeader即可实现了。最终Tab成果如下所示。 以上就是我设计的一个零碎界面的具体操作流程,其实很多时候,介绍总是很快,摸索总是很慢,这个就是常识积攒的效率晋升。当然,要设计好一个零碎界面,除了思考界面的布局好看性、还要思考图标的协调性、还有就是整体的框架,要能够比拟好的适应这些布局控件的操作,不能太过臃肿或者难以浏览。 本文转载自博客园-伍华聪[](https://home.cnblogs.com/u/wu...

January 18, 2021 · 1 min · jiezi

关于c#:NET-5网络操作的改进

随着.net 5在11月的公布,当初是议论网络栈中许多改良的好时机。这包含对HTTP、套接字、与网络相干的安全性和其余网络通信的改良。在这篇文章中,我将重点介绍一些版本中更有影响力和更乏味的变动。 HTTP更好的错误处理  自从.net 3.1公布以来,HTTP畛域进行了许多改良和修复。当应用HttpClien时,最受关注的是增加如何辨别超时和勾销。最后,不得不应用自定义的CancellationToken辨别超时和勾销: class Program{ private static readonly HttpClient _client = new HttpClient() { Timeout = TimeSpan.FromSeconds(10) }; static async Task Main() { var cts = new CancellationTokenSource(); try { // Pass in the token. using var response = await _client.GetAsync("http://localhost:5001/sleepFor?seconds=100", cts.Token); } // If the token has been canceled, it is not a timeout. catch (TaskCanceledException ex) when (cts.IsCancellationRequested) { // Handle cancellation. Console.WriteLine("Canceled: " + ex.Message); } catch (TaskCanceledException ex) { // Handle timeout. Console.WriteLine("Timed out: "+ ex.Message); } }}这样做,客户端依然抛出TaskCanceledException(为了兼容),但外部异样是超时时的TimeoutException: ...

January 18, 2021 · 11 min · jiezi

关于c#:C常用工具类如何优雅的使用多线程以及优雅的跨线程的解决方案解决线程间操作无效-从不是创建控件的线程访问它

当你须要通过一个耗时操作获取到数据,并扭转窗体或控件的显示时,该工具能够为你解决窗体假死,以及跨线程的问题。 解决System.InvalidOperationException:“线程间操作有效: 从不是创立控件“”的线程拜访它。” 首先看看在我的我的项目中理论应用://多线程工具this.TaskRun(cross =>{ //多线程代码,申请API List<EmpType> types = ApiRoutes.EmpApi.GetTypeList(out string msg); //跨线程代码块 cross.Invoke(delegate { uiDataGridView1.DataSource = types; uiDataGridView1.Refresh(); });});你只须要创立如下工具类:public static class TaskEx{ /// <summary> /// 启动多线程 /// </summary> public static void TaskRun(this System.Windows.Forms.Control ctrl, Action<Action<Action>> action) { System.Threading.ThreadPool.QueueUserWorkItem(delegate { action.Invoke(b => ctrl.Invoke(b)); }); }}

January 16, 2021 · 1 min · jiezi

关于c#:进击吧Blazor第一章-1初识-Blazor

作者介绍陈超超Ant Design Blazor 我的项目贡献者领有十多年从业教训,长期基于.Net技术栈进行架构与开发产品的工作,Ant Design Blazor 我的项目贡献者,现就职于正泰团体 第一次写专栏,结尾不晓得说什么,所以……先来段广告????《进击吧!Blazor!》是自己与张善友老师单干的Blazor零根底入门系列视频,此系列能让一个从未接触过Blazor的程序员把握开发Blazor利用的能力。视频地址:https://space.bilibili.com/48...本系列文章是基于《进击吧!Blazor!》直播内容编写,降级.Net5,改良问题,解说更全面。系列文章目录第一章 初出江湖 —— ToDo利用开发练手初识 BlazorHello Blazor页面制作数据交互组件开发平安 第二章 仗剑江湖 —— 企业组织绩效数据管理平台开发实战我的项目框架搭建指标保护:增删改查组织机构保护:树数据采集:自定义表格指标剖析:Chart账号与权限站点部署

January 16, 2021 · 1 min · jiezi

关于c#:C中的异步和多线程

许多开发人员对异步代码和多线程以及它们的工作原理和应用办法都有谬误的意识。在这里,你将理解这两个概念之间的区别,并应用c#实现它们。 我:“服务员,这是我第一次来这家餐厅。通常须要4个小时能力拿到食物吗?” 服务员:“哦,是的,学生。这家餐厅的厨房里只有一个厨师。” 我:“……只有一个厨师吗?” 服务员:“是的,学生,咱们有好几个厨师,但每次只有一个在厨房工作。” 我:“所以其余10个衣着厨师服站在厨房里的人……什么都不做吗?厨房太小了吗?” 服务员:“哦,咱们的厨房很大,学生。” 我:“那为什么他们不同时工作呢?” 服务员:“学生,这倒是个好主见,但咱们还没想好怎么做。” 我:“好了,奇怪。然而…嘿…当初的主厨在哪里?我当初没看见有人在厨房里。” 服务员:“是的,学生。有一份订单的厨房用品曾经用完了,所以厨师曾经进行烹饪,站在里面等着送货了。” 我:“看起来他能够一边等一边做饭,兴许送货员能够间接通知他们什么时候到了?” 服务员:“又是一个绝妙的主见,学生。咱们在前面有送货门铃,但厨师喜爱等。我去给你再拿点水来。” 多蹩脚的餐厅,对吧?可怜的是,很多程序都是这样工作的。 有两种不同的办法能够让这家餐厅做得更好。 首先,很显著,每个独自的晚餐订单能够由不同的厨师来解决。每一种都是一个必须按特定程序产生的事件列表(筹备原料,而后混合它们,而后烹饪,等等)。因而,如果每个厨师都致力于解决这一清单上的货色,几份晚餐订单能够同时做出。 这是一个真实世界中的多线程示例。计算机有能力让多个不同的线程同时运行,每个线程负责按特定程序执行一系列流动。 而后还有异步行为。须要明确的是,异步不是多线程的。还记得那个始终在等外卖的厨师吗?真是浪费时间!在期待的过程中,他没有做任何有意义的事件,比方做饭。而且,期待也不会让送货更快。一旦他打电话订购供应品,发货就会随时产生,所以为什么要等呢?相同,送货员只需按门铃,说一句:“嘿,这是你的供应品!” 有很多I/O流动是由代码之外的货色解决的。例如,向近程服务器发送一个网络申请。这就像给餐厅点餐一样。你的代码所做的惟一事件就是进行调用并接管后果。如果抉择期待后果,在这两者之间齐全不做任何事件,那么这就是“同步”行为。 然而,如果你更喜爱在后果返回时被打断/告诉(就像送货员达到时按门铃),同时能够解决其余事件,那么这就是“异步”行为。 只有工作是由不受以后代码间接管制的对象实现的,就能够应用异步代码。例如,当你向硬盘驱动器写入一堆数据时,你的代码并没有执行理论的写入操作。它只是申请硬件执行该工作。因而,你能够应用异步编码开始编写,而后在编写实现时失去告诉,同时持续解决其余事件。 异步的长处在于不须要额定的线程,因而十分高效。 “等等!”你说。“如果没有额定的线程,那么谁或什么在期待后果?代码如何晓得返回的后果?” 还记得那个门铃吗?你的电脑里有一个零碎叫做“中断”零碎,它的工作原理有点像那个门铃。当你的代码开始一个异步流动时,它基本上会装置一个虚构的门铃。当其余工作(写入硬盘驱动器,期待网络响应等)实现时,中断零碎“中断”以后运行的代码并按下门铃,让你的应用程序晓得有一个工作在期待!不须要线程坐在那里期待! 让咱们疾速回顾一下咱们的两种工具: 多线程:应用一个额定的线程来执行一系列流动/工作。 异步:应用同一个线程和中断零碎,让线程外的其余组件实现一些流动,并在流动完结时失去告诉。 UI线程还有一件重要的事件须要晓得的是为什么应用这些工具是好的。在.net中,有一个主线程叫做UI线程,它负责更新屏幕的所有可视局部。默认状况下,这是所有运行的中央。当你点击一个按钮,你想看到按钮被短暂地按下,而后返回,这是UI线程的责任。你的利用中只有一个UI线程,这意味着如果你的UI线程忙着做沉重的计算或期待网络申请之类的事件,那么它不能更新你在屏幕上看到的货色,直到它实现。后果是,你的应用程序看起来像“解冻”——你能够点击一个按钮,但仿佛什么都不会产生,因为UI线程正在忙着做其余事件。 现实状况下,你心愿UI线程尽可能地闲暇,这样你的应用程序仿佛总是在响应用户的操作。这就是异步和多线程的由来。通过应用这些工具,能够确保在其余中央实现沉重的工作,UI线程保持良好和响应性。 当初让咱们看看如何在c#中应用这些工具。 C#的异步操作执行异步操作的代码非常简单。你应该晓得两个次要的关键字:“async”和“await”,所以人们通常将其称为async/await。假如你当初有这样的代码: public void Loopy(){ var hugeFiles = new string[] { "Gr8Gonzos_Home_Movie_In_8k_Res.mkv", // 1 GB "War_And_Peace_In_150_Languages.rtf", // 1.2 GB "Cats_On_Catnip.mpg" // 0.9 GB }; foreach (var hugeFile in hugeFiles) { ReadAHugeFile(hugeFile); } MessageBox.Show("All done!");}public byte[] ReadAHugeFile(string bigFile){ var fileSize = new FileInfo(bigFile).Length; // Get the file size var allData = new byte[fileSize]; // Allocate a byte array as large as our file using (var fs = new System.IO.FileStream(bigFile, FileMode.Open)) { fs.Read(allData, 0, (int)fileSize); // Read the entire file... } return allData; // ...and return those bytes!}在以后的模式中,这些都是同步运行的。如果你点击一个按钮从UI线程运行Loopy(),那么应用程序将仿佛解冻,直到所有三大文件浏览,因为每个“ReadAHugeFile”是要花很长时间在UI线程上运行,并将同步浏览。这可不好!让咱们看看是否将ReadAHugeFile变为异步的这样UI线程就能持续解决其余货色。 ...

January 16, 2021 · 2 min · jiezi

关于c#:项目实战C上位机arduino下位机控制点亮LED灯

若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/112651809 红瘦子(红模拟)的博文大全:开发技术汇合(蕴含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬联合等等)继续更新中…(点击传送门) 开发专栏:我的项目实战 前言 以后比拟风行的arduino开发,联动做一个Demo。 利用构架 上位机:C#上位机通过串口发送接管控制协议,来管制下位机; 下位机:arduino下位机主控,承受上位机串口协定管制GPIO硬件引脚; 硬件电路:面包板LED串220R电路,以arduino引脚驱动; Demo arduino开发板 硬件电路连贯 若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/112651809

January 15, 2021 · 1 min · jiezi

关于c#:WPF平台开发-如何将树编辑器添加到数据网格单元中

点击获取工具>> 问题试图将树编辑器嵌入具备多选性能的网格单元中,如何将视图模型SelectedPerils绑定到弹出树控件中的已查看我的项目? 解决方案据理解,目前的指标是应用带有TreeListView的弹出式编辑器来编辑汇合属性,本文将为大家解释此操作所须要的步骤。 GridControl不反对编辑应用FieldName绑定的汇合属性,您能够更改属性申明,以便它应用对象类型或应用Binding而不是FieldName。请参阅Binding Columns to Data Source Fields,让咱们应用第一个选项:C# `public object SelectedPerils { get; set; }//...SelectedPerils = new List<Peril>();//...((List<Peril>)Portfolios[0].SelectedPerils).Add(Portfolios[0].Perils[0]);((List<Peril>)Portfolios[1].SelectedPerils).Add(Portfolios[1].Perils[1]);((List<Peril>)Portfolios[2].SelectedPerils).Add(Portfolios[2].Perils[0]);` XAML <dxg:GridColumn FieldName="SelectedPerils" /> 咱们倡议应用LookUpEdit在弹出窗口中显示GridControl,应用MultiSelectLookUpEditStyleSettings为其启用多选性能,这是执行此操作的预定义方法。因为您心愿将其默认TableView替换为TreeListView,因而须要申明CellTemplate和PopupContentTemplate:XAML `<dxg:GridColumn FieldName="SelectedPerils"><dxg:GridColumn.CellTemplate><DataTemplate><dxg:LookUpEditDisplayMember="Name"ItemsSource="{Binding RowData.Row.Perils}"Name="PART_Editor"><dxg:LookUpEdit.PopupContentTemplate><ControlTemplate><dxg:GridControl Name="PART_GridControl" SelectionMode="MultipleRow"><dxg:GridControl.View><dxg:TreeListView KeyFieldName="ID" ParentFieldName="ParentID" /></dxg:GridControl.View></dxg:GridControl></ControlTemplate></dxg:LookUpEdit.PopupContentTemplate><dxg:LookUpEdit.StyleSettings><dxg:MultiSelectLookUpEditStyleSettings /></dxg:LookUpEdit.StyleSettings></dxg:LookUpEdit></DataTemplate></dxg:GridColumn.CellTemplate></dxg:GridColumn>` 您的编辑器应该可能抉择嵌套值,因而您须要应用自参考数据结构,这就是为什么在模板中应用KeyFieldName和ParentFieldName属性的起因。 否则,您的LookUpEdit将回绝其ItemsSource之外的值,因为在那里应用DisplayMember 并关上了查找模式。C# `public class Peril {public int ID { get; set; }public int ParentID { get; set; } = -1;//...}//...Perils = new List<Peril>{new Peril { Name = "Earthquake", ID = 0},new Peril { Name = "EQ", ID = 10, ParentID = 0 },new Peril { Name = "FF", ID = 11, ParentID = 0 },new Peril { Name = "Hurricane", ID = 1},new Peril { Name = "HU", ID = 12, ParentID = 1 },new Peril { Name = "TC", ID = 13, ParentID = 1 },new Peril { Name = "Tornado Hail", ID = 2},new Peril { Name = "TH", ID = 14, ParentID = 2 },new Peril { Name = "WS", ID = 15, ParentID = 2 },};` ...

January 15, 2021 · 1 min · jiezi

关于c#:ASPNET-Core中的数据保护

在这篇文章中,我将介绍ASP.NET Core 数据保护零碎:它是什么,为什么咱们须要它,以及它如何工作。 为什么咱们须要数据保护零碎?数据保护零碎是ASP.NET Core应用的一组加密api。加密必须由不受信赖的第三方解决的数据。 这方面的典型例子是身份验证cookie。cookie是在申请之间长久化状态的一种办法。你不心愿每次向服务器申请时都必须提供用户名和明码,这将十分麻烦! 相同,只需向服务器提供一次凭据。服务器验证你的详细信息,并收回一个cookie,表明“他不须要提供任何其余证实,置信他。”对于后续的申请,能够简略地提供该cookie,而不用提供凭据。浏览器主动发送cookie与后续申请,这是web为用户实现晦涩登录体验的形式。cookie是十分敏感的货色。任何蕴含cookie的申请都将被视为原始用户发送的申请,就像原始用户在每个申请中都提供了用户名和明码一样。浏览器中有很多保护措施(例如CORS)来阻止攻击者拜访这些cookie。 然而,这不仅仅是阻止他人失去你的cookie。作为一个网站所有者,你也不心愿用户篡改他们本人的cookie。 身份验证cookie通常不仅仅蕴含通过身份验证的用户的ID或名称。它们通常蕴含各种附加的要求。它蕴含了用户的详细信息。它们能够是实在数据,如名称、电子邮件或电话号码,但它们也能够是与权限相干的申明,如是否是管理员或是否能够编辑。 对于每个申请,通常都须要这些,以确定是否容许用户采取操作。通常蕴含在发送给用户的身份验证cookie中,而不是每次申请都必须从数据库加载。这使得应用程序更加容易——一旦通过从cookie中提取用户主体对用户进行身份验证,应用程序就会确切地晓得用户领有哪些权限。这意味着应用程序必须信赖cookie。如果cookie是明文发送的,那么用户只需编辑这些值,就会裸露应用程序中显著的安全漏洞。 ASP.NET Core数据保护零碎正是为了这个目标而应用的。它对敏感数据(如身份验证cookie)进行加密和解密。通过在响应中返回身份验证cookie之前对其进行加密,应用程序晓得该cookie没有被篡改,并能够信赖其值。 数据保护零碎如何工作?数据保护零碎试图解决一个辣手的问题:如何爱护裸露给攻击者的敏感数据,现实状况下不向开发人员裸露任何密钥,同时遵循加密的最佳实际。 数据保护零碎应用对称密钥加密来爱护数据。应用蕴含随机数据的密钥加密数据,应用雷同的密钥解密数据。 在一个典型的ASP.NET Core应用程序可能有几种不同类型的不相干数据须要加密。例如,除了身份验证cookie之外,可能还须要加密跨站点申请伪造令牌(CSRF)或明码重置令牌。 你能够将雷同的键用于所有这些不同的目标,但这可能会带来问题。例如,如果明码重置令牌不能“意外地”(更有可能是歹意地)用作身份验证令牌,那就好得多。 ASP.NET Core数据保护零碎实现了这一指标。数据保护零碎有一个不能间接应用的父密钥。必须从父密钥派生子密钥,这些子密钥用于加密和解密数据。 应用雷同的purpose字符串从父密钥派生密钥总是会给出雷同的密钥,因而如果你领有父密钥并且晓得purpose字符串,那么总是能够解密已加密的数据。如果密钥是用不同的purpose导出的,那么尝试解密数据将会失败。这样能够保持数据隔离,这对安全性更好。 在大多数状况下,你不用间接与数据保护零碎交互来创立密钥或加密数据。这是由ASP.NET Core外围框架及其附带的库解决的。它们确保在你的应用程序中为每个不同的purpose应用惟一的字符串。如果你违心,你能够创立本人的爱护程序并加密其余数据(见下文),但这不是ASP.NET Core的日常运行所必须的。 我是一个.net框架开发者——这听起来很像<machineKey>?数据保护零碎是ASP.NET Core的一个新性能。,然而爱护身份验证令牌的须要并不是新的,那么咱们以前用的是什么呢?答案是<machineKey>。<machineKey>元素的应用形式与ASP.NET Core数据保护零碎十分类似,配置密钥和密码学套件,用于通过身份验证零碎加密数据(以及其余中央)。可怜的是,应用这个密钥时有些简单,因为它通常是从__machine.config__读取的。必须在运行应用程序的机器上配置。在集群中运行时,必须确保这些键放弃同步,否则可能会产生问题! 在.net Framework 4.5中,咱们能够替换<machineKey>元素及其应用的整个加密管道。 如何治理数据保护密钥?如果对安全性有所理解,那么你可能曾经听到应该定期轮换明码、秘密和证书的说法。如果你的某个机密被泄露了,这能够在肯定水平上缩小影响。这就是为什么签发HTTPS证书的寿命越来越短的起因。 依据你从框架和工具取得的反对,更换秘钥和证书可能会很苦楚,特地是在过渡时期,可能须要同时反对新旧秘钥。 鉴于数据保护对于爱护ASP.NET Core是至关重要的。你不会诧异秘钥轮换是数据保护零碎的默认设置。默认状况下,数据保护的生命周期为90天,但通常不用为此放心。当旧密钥快要过期时,数据保护零碎会主动创立新的密钥。所有可用密钥的汇合称为密匙环。 在这篇文章中,我不会深刻密钥治理的细节。请留神,秘钥轮换是主动产生的,只有你不删除任何旧的键(或显式地撤销它们),那么加密的数据依然能够应用过期的键检索。过期的密钥不能用于加密新数据。 我是否也能够爱护其余数据,还是仅用于身份验证cookie?数据保护零碎由ASP.NET Core隐含地应用并解决认证令牌的加密和解密。它也被ASP.NET Core用来爱护明码重置和MFA令牌。你不须要为这种爱护做任何事件——框架本人解决爱护。 如果你有本人想要加密的长期数据,能够间接应用数据保护api。我将在前面的文章中具体介绍,但以下内容展现了中如何应用IDataProtectionProvider服务(默认在ASP.NET Core apps)加密和解密一些数据: public class MyClass{ // The IDataProtectionProvider is registered by default in ASP.NET Core readonly IDataProtectionProvider _rootProvider; public MyClass(IDataProtectionProvider rootProvider) { _rootProvider = rootProvider; } public void RunSample() { // Create a child key using the purpose string string purpose = "Contoso.MyClass.v1"; IDataProtector protector = provider.CreateProtector(purpose); // Get the data to protect Console.Write("Enter input: "); string input = Console.ReadLine(); // Enter input: Hello world! // protect the payload string protectedPayload = _protector.Protect(input); Console.WriteLine($"Protect returned: {protectedPayload}"); //PRINTS: Protect returned: CfDJ8ICcgQwZZhlAlTZT...OdfH66i1PnGmpCR5e441xQ // unprotect the payload string unprotectedPayload = _protector.Unprotect(protectedPayload); Console.WriteLine($"Unprotect returned: {unprotectedPayload}"); //PRINTS: Unprotect returned: Hello world }}一般来说,这并不是你想要做的事件。我集体只在解决明码重置和相似的令牌时须要它。 ...

January 15, 2021 · 1 min · jiezi

关于c#:改进你的c代码的5个技巧三

本文齐全独立于前两篇文章。如果你喜爱它们,我心愿你也会喜爱这个。在上一篇文章中,我展现了哪种办法更快,并比拟了代码的执行速度。在本文中,我将展现不同代码片段的内存耗费状况。为了显示内存映射和调配图,我应用了CLR profiler 32位版本,和平常一样,我在Windows平台上应用了4GB RAM和Core i3 CPU。内存耗费或调配图可能依据零碎运行的过程而变动。因而,如果你失去一个不同的输入或行为的代码,那么请与咱们分享你的教训。 让咱们开始“改良c#代码的5个技巧:第3局部”的旅程。 StringBuilder耗费的内存比String少在我的上一篇文章中,我曾经展现了在长连贯操作的场景中字符串的速度有多慢。这里咱们会看到一个字符串和StringBuilder的内存调配图。让我来演示一下。上面是我应用字符串和StringBuilder进行雷同操作的代码。 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; using System.IO; using System.Net; using System.Net.NetworkInformation; using System.Threading; using System.Globalization; using System.Data.SqlClient; namespace Test1 { public class Test1 { string Name ; public void Process() { Name = Name + "A"; } } public class Test2 { StringBuilder sb = new StringBuilder(); public void Process() { sb.Append("A"); } } class Program { static void Main(string[] args) { Test1 t = new Test1(); t.Process(); Test2 t1 = new Test2(); t1.Process(); } } } 这是代码执行时的内存调配图。这里咱们从main函数调用两个函数Process();只管它们都有雷同的名称,但它们属于不同的类和Test1.Process解决字符串数据,而Test2.Process()解决StringBuilder数据。在调配图中,咱们能够看到字符串处理函数耗费了Main()函数94%的资源,而Test2类中解决StringBuilder的Process()只耗费了Main()函数的0.21%的资源。 ...

January 14, 2021 · 2 min · jiezi

关于c#:NETC开发工具整理

——工欲善其事必先利其器 1、Visual Studio IDE微软出品的最弱小编译器,没有之一。官网下载地址:https://visualstudio.microsof... 2、JetBrains ReSharper一款Visual Studio IDE开发扩大插件,能够主动生成代码,智能剖析代码,标准开发代码。官网下载地址:https://marketplace.visualstu... 3、OzCode一款Visual Studio IDE开发扩大插件,调试神器。缩小了调试工夫并通过检测和隔离谬误,能够大大的进步工作的生产效率。 4、DevExpress一款第三方控件软件,控件比VS自带的更齐全,更好看。Winfrom、WPF和ASP.NET均可应用。 5、.NET Reflector一款由前微软员工开发的.net反编译软件,能够反编译查看所有.NET代码的源代码。 6、ILSpy一款开源的.Net程序集浏览器和反编译工具,能够反编译dll文件为C#或VB语言,和.NET Reflector比更轻量级。 7、ANTS Memory ProfilerSciTech.NET.Memory.Profiler两款软件内存应用状况剖析软件,不便排查内存透露等软件问题,并优化内存应用。针对C#、VB.Net、或其它.Net程序。 8、Fiddler一款通过代理的抓包软件,能够抓取winFrom软件或者ASP.NET页面调用的http记录,同时能够断点批改入参和出参,便于调试。ps:开始Fiddler代理后,会导致拜访局部网址无奈平安拜访。敞开Fiddler即可恢复正常。批改入参断点:bpu http地址,如 bpu https://segmentfault.com/批改入参断点:bpafter http地址 bpafter https://segmentfault.com/

January 14, 2021 · 1 min · jiezi

关于c#:在NET-Core中使用Channel三

到目前为止,咱们始终在应用所谓的“Unbounded”通道。你会留神到,当咱们创立通道时,咱们这样做: var myChannel = Channel.CreateUnbounded<int>();但实际上,咱们能够这样做: var myChannel = Channel.CreateBounded<int>(1000);这与创立容量无限的列表或数组等其余汇合类型并无太大差异。在咱们的示例中,咱们创立了一个最多包容1000项的Channel。但为什么要限度本人呢?这就是背压的作用。 什么是背压?背压(特地是当波及消息传递/排队时)是指资源(无论是内存、ram、网络)是无限的。咱们应该可能在链条上施加“压力”,试着加重一些压力。至多,让生态系统中的其他人晓得咱们负荷过重,咱们可能须要一些工夫来解决他们的申请。 一般来说,当咱们探讨队列的背压时。简直所有状况下,咱们都在探讨一种办法,通知任何试图在队列中增加更多条目标人,要么他们根本无法再退出任何条目,要么他们须要推后一段时间。更常见的是,咱们探讨的队列是在达到肯定容量时纯正抛弃音讯。这种状况很少产生,然而咱们有这个选项。 那么它是如何与.net Channel一起工作的呢? Channel中的背压当应用通道时,咱们实际上有一个非常简单的办法来减少背压。代码看起来是这样的: var channelOptions = new BoundedChannelOptions(5){ FullMode = BoundedChannelFullMode.Wait};var myChannel = Channel.CreateBounded<int>(channelOptions);咱们能够指定以下残缺模式: 期待 在关上WriteAsync()调用之前,只需让调用者期待。 DropNewest / DropOldest 能够在Channel中拖放最老的或最新的我的项目,为咱们想要增加的项腾出空间。 DropWrite 简略地转储咱们应该写的音讯。 还有另外两段代码须要留神。 你能够调用WaitToWriteAsync(): await myChannel.Writer.WaitToWriteAsync();这让咱们Channel成了有界。当Channel已满时,咱们能够简略地期待,直到有空间。这意味着,即便关上了DropWrite FullMode,咱们也能够通过简略地期待,直到有容量为止,来限度扔在高空上的音讯数量。 咱们应该留神的另一段代码是: var success = myChannel.Writer.TryWrite(i);这容许咱们尝试写入队列,并返回,无论胜利与否。须要留神的是,此办法不是异步的。要么写入信道要么不写入信道,这里没有"如果你再多等一会儿,兴许能够。”  欢送关注我的公众号,如果你有喜爱的外文技术文章,能够通过公众号留言举荐给我。

January 11, 2021 · 1 min · jiezi

关于c#:将WCF迁移到gRPC

应用protobuf-net.Grpc将WCF服务迁徙到gRPC非常简单。在这篇博文中,咱们将看看它到底有多简略。微软对于将WCF服务迁徙到gRPC的官网指南只提到了Gooogle.Protobuf形式,如果你有很多数据契约须要迁徙到.proto格局,这可能会很耗时。然而,通过应用protobuf-net.Grpc咱们可能重用旧的WCF数据契约和服务契约,而只须要做最小的代码更改。 迁徙数据契约和服务契约 在本节中,咱们将应用一个简略的申请响应的组合服务,它能够让你下载给定交易者的单个投资组合或所有投资组合。服务和数据契约的定义如下: [ServiceContract]public interface IPortfolioService{ [OperationContract] Task<Portfolio> Get(Guid traderId, int portfolioId); [OperationContract] Task<List<Portfolio>> GetAll(Guid traderId);}[DataContract]public class Portfolio{ [DataMember] public int Id { get; set; } [DataMember] public Guid TraderId { get; set; } [DataMember] public List<PortfolioItem> Items { get; set; }}[DataContract]public class PortfolioItem{ [DataMember] public int Id { get; set; } [DataMember] public int ShareId { get; set; } [DataMember] public int Holding { get; set; } [DataMember] public decimal Cost { get; set; }}在将数据契约和服务契约迁徙到gRPC之前,我倡议为契约创立一个新的类库。这些契约能够通过我的项目援用或包援用在服务器和客户端之间很容易地共享,这取决于你的WCF解决方案的构造。一旦咱们创立了类库,咱们将源文件进行复制并开始迁徙到gRPC。 ...

January 7, 2021 · 4 min · jiezi

关于c#:AgileConfig如何使用AgileConfigClient读取配置

后面的文章都是介绍AgileConfig服务端曾经控制台是如何工作、如何应用的,其实AgileConfig还有一个重要的组成部分:AgileConfig.Client。 AgileConfig.Client是应用C#编写的一个类库,只有应用它能力跟AgileConfig的服务端配合工作实现实时推送配置信息等性能。 最近有几个同学问我如何集成Client,如何应用Client,看来光是Readme上的示例还是不够的,有必要比拟具体的介绍下如何应用AgileConfig.Client。 上面通过几个示例来演示下如何AgileConfig.Client如何在mvc,控制台,wpf等程序上来读取配置: asp.net core mvc下读取配置mvc我的项目应该是目前应用最宽泛的我的项目,同样它与AgileConfig.Client的集成最深刻。上面来看看如何在mvc我的项目下应用AgileConfig.Client。 装置AgileConfig.ClientInstall-Package AgileConfig.Client当然第一步是应用nuget命令装置最新版的Client库。 批改appsettings.json "AgileConfig": { "appId": "test_app", "secret": "", "nodes": "http://agileconfig.xbaby.xyz:5000" }AgileConfig.Client连贯服务端须要一点必要的信息,咱们把这些信息配置在appsettings.json文件里。节点的名称叫“AgileConfig”,外面配置了: appId 利用idsecret 利用密钥,没有的话留空nodes 节点地址,如果有多个则应用英文逗号(,)分隔AddAgileConfig批改program.cs文件: public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration((context, config) => { //注入AgileConfig Configuration Provider config.AddAgileConfig(); }) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });通过AddAgileConfig扩大办法注入AgileConfigProvider。AgileConfigProvider才是跟配置零碎打交道的组件。如果你想要应用Client的实例进行读取配置,也能够手动实例化一个client而后通过AddAglieConfig的另外一个重载注入进去。 Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration((context, config) => { //注入AgileConfig Configuration Provider var client = new ConfigClient(); config.AddAgileConfig(client); })读取配置通过以上的设置,其实前面的配置读取跟应用appsettings.json没什么区别了。 public HomeController( ILogger<HomeController> logger, IConfiguration configuration, ) { _logger = logger; _IConfiguration = configuration; } /// <summary> /// 应用IConfiguration读取配置 /// </summary> /// <returns></returns> public IActionResult ByIConfiguration() { var userId = _IConfiguration["userId"]; var dbConn = _IConfiguration["db:connection"]; ViewBag.userId = userId; ViewBag.dbConn = dbConn; return View("Configuration"); }管制台下读取配置当然了从实质上来说控制台我的项目跟mvc我的项目没啥区别。同样能够引入ConfigurationBuilder来注入ConfigClient。然而个别咱们应用控制台可能是写个小工具,不必搞的这么简单,间接new一个ConfigClient的实例是最间接的办法。 ...

January 6, 2021 · 2 min · jiezi