- Notifications
You must be signed in to change notification settings - Fork1.3k
全龄段友好的C#万能工具库,码数吐司库,包含一些常用的操作类,大都是静态类,加密解密,反射操作,权重随机筛选算法,分布式短id,表达式树,linq扩展,文件压缩,多线程下载,硬件信息,字符串扩展方法,日期时间扩展操作,中国农历,大文件拷贝,图像裁剪,验证码,断点续传,集合扩展、Excel导出等常用封装。诸多功能集一身,代码量不到2MB!
License
ldqk/Masuit.Tools
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
全龄段友好的C#.NET万能工具库,不管你是菜鸟新手还是骨灰级玩家都能轻松上手,这个库包含一些常用的操作类,大都是静态类,加密解密,反射操作,树结构,文件探测,权重随机筛选算法,分布式短id,表达式树,linq扩展,文件压缩,多线程下载,硬件信息,字符串扩展方法,日期时间扩展操作,中国农历,大文件拷贝,图像裁剪,验证码,断点续传,集合扩展、Excel导出等常用封装。
诸多功能集一身,代码量不到2MB!官网教程
项目开发模式:日常代码积累+网络搜集
⭐⭐⭐喜欢这个项目的话就Star、Fork、Follow素质三连关♂注一下吧⭐⭐⭐
关于本项目,如果你有任何不懂的地方或使用过程中遇到任何问题,可以直接提issue或私信联系我,我会为你提供完全免费的技术指导,当然,如果你觉得不好意思接受免费的指导,想适当打赏我也是不会拒绝的!🤣🤣🤣
本项目已得到JetBrains的支持!
一旦使用本开源项目以及引用了本项目或包含本项目代码的公司因为违反劳动法(包括但不限定非法裁员、超时用工、雇佣童工等)在任何法律诉讼中败诉的,一经发现,本项目作者有权利追讨本项目的使用费(公司工商注册信息认缴金额的2-5倍作为本项目的授权费),或者直接不允许使用任何包含本项目的源代码!人力外包公司或007公司需要使用本类库,请联系作者进行商业授权!其他企业或个人可随意使用不受限。007那叫用人,也是废人。8小时工作制才可以让你有时间自我提升,将来有竞争力。反对007,人人有责!
操作系统:Windows 11 23H2及以上版本
开发工具:VisualStudio2022 v17.8及以上版本
SDK:.Net Core 2.1.0及以上所有版本
PM> Install-Package Masuit.Tools.Net通用项目推荐首选包
PM> Install-Package Masuit.Tools.Abstraction.NET Core项目推荐首选包
PM> Install-Package Masuit.Tools.Core请注意:这是.NET Framework 4.5的专用版本,相比4.6.2及.NET Core的版本,阉割了Redis、HTML、文件压缩、ASP.NET扩展、硬件监测、Session扩展等一些功能。如果你的项目版本高于4.6.2,请务必使用上述版本的包,以享受完整的功能体验!
PM> Install-Package Masuit.Tools.Net45AspNetCore项目推荐首选包ASP.NET Core Web专用包,包含Masuit.Tools.Core的全部功能,并且增加了一些对ASP.NET Core Web功能的额外支持。
Excel导入导出的专用独立包
mongodb的封装操作类独立包
工具库需要用到外部配置节,.NET Framework项目配置在web.config/app.config的AppSettings配置节中,.NET Core项目配置在appsettings.json中:
- EmailDomainWhiteList,邮箱校验需要用到的白名单域名正则表达式,数组形式,每个元素支持正则表达式,若未配置,则不启用邮箱校验白名单,示例:
["^\\w{1,5}@qq.com","^\\w{1,5}@163.com","^\\w{1,5}@gmail.com","^\\w{1,5}@outlook.com"] - EmailDomainBlockList,邮箱校验需要用到的黑名单域名正则表达式,数组形式,每个元素支持正则表达式,且黑名单优先级高于白名单,若未配置,则不启用邮箱校验黑白名单
publicStartup(IConfiguration configuration){configuration.AddToMasuitTools();// 若未调用,则默认自动尝试加载appsettings.json}
https://replit.com/@ldqk/MasuitToolsDemo?v=1#main.cs
DisposableDictionary:可被Disposable的字典类型,用于存放Value是Disposable类型的数据,用法和普通字典一致
NullableConcurrentDictionary/NullableDictionary:Key可为null的字典类型,用法和普通字典一致
ConcurrentHashSet:并发HashSet,用法和HashSet一致
ConcurrentLimitedQueue:定长并发队列,特点是长度是固定的,用法与ConcurrentQueue一致
ConcurrentHashQueue:线程安全的唯一队列,特点是元素是唯一的,用法与ConcurrentQueue一致
LimitedQueue:定长队列,特点是长度是固定的,用法与Queue一致
HashQueue:唯一队列,特点是元素是唯一的,用法与Queue一致
LargeMemoryStream:超大内存流,最大可支持1TB数据,推荐当数据流大于2GB时使用,用法与MemoryStream一致
PooledMemoryStream:池化内存流,可内存复用,用法与MemoryStream一致,性能比MemoryStream好
ITree<T>:树形实体接口约束,实现该接口可让类型实现一些树形操作
ChineseCalendar:中国农历类型,可以实现天干地支节气等数据的获取
Clay/DynamicFactory:粘土动态类型,可实现类似js的弱类型编程
RadarChart:雷达图类型,可用于做数据分析或用户行为画像
Circle:圆形类型,可实现⚪的相交相切相离的判断
Sphere:球体类型,可实现计算球体上两点的弧长计算,相交相切相离的判断
MimeMapper:mime类型映射
VersionNumber:版本号类型,比System.Version功能更多一点,用法一致
具体用法,可参阅后文详细示例:
var(isMatch,match)="337845818@qq.com".MatchEmail();// 可在appsetting.json中添加EmailDomainWhiteList和EmailDomainBlockList配置邮箱域名黑白名单正则表达式数组,如"EmailDomainBlockList": ["^\\w{1,5}@qq.com","^\\w{1,5}@163.com","^\\w{1,5}@gmail.com","^\\w{1,5}@outlook.com"]boolisInetAddress="114.114.114.114".MatchInetAddress();// 匹配IP地址boolisUrl="http://masuit.org/20/history".MatchUrl();// 匹配urlboolisPhoneNumber="15205201520".MatchPhoneNumber();// 匹配手机号boolisLandline="01088888888".MatchLandline();// 匹配座机号boolisIdentifyCard="312000199502230660".MatchIdentifyCard();// 校验中国大陆身份证号boolisCNPatentNumber="200410018477.9".MatchCNPatentNumber();// 校验中国专利申请号或专利号,是否带校验位,校验位前是否带“.”,都可以校验,待校验的号码前不要带CN、ZL字样的前缀boolisUSCC="200410018477.9".MatchUSCC();// 校验企业统一社会信用代码
floatload=SystemInfo.CpuLoad;// 获取CPU占用率longphysicalMemory=SystemInfo.PhysicalMemory;// 获取物理内存总数longmemoryAvailable=SystemInfo.MemoryAvailable;// 获取物理内存可用率doublefreePhysicalMemory=SystemInfo.GetFreePhysicalMemory();// 获取可用物理内存doubletemperature=SystemInfo.GetCPUTemperature();// 获取CPU温度intcpuCount=SystemInfo.GetCpuCount();// 获取CPU核心数varipAddress=SystemInfo.GetLocalIPs();// 获取本机所有IP地址stringlocalUsedIp=SystemInfo.GetLocalUsedIP();// 获取本机当前正在使用的IP地址IList<string>macAddress=SystemInfo.GetMacAddress();// 获取本机所有网卡mac地址stringosVersion=Windows.GetOsVersion();// 获取操作系统版本RamInforamInfo=SystemInfo.GetRamInfo();// 获取内存信息varcpuSN=SystemInfo.GetCpuInfo()[0].SerialNumber;// CPU序列号vardriveSN=SystemInfo.GetDiskInfo()[0].SerialNumber;// 硬盘序列号// 快速方法varcpuInfos=CpuInfo.Locals;// 快速获取CPU的信息varramInfo=RamInfo.Local;// 快速获取内存的信息vardiskInfos=DiskInfo.Locals;// 快速获取硬盘的信息varbiosInfo=BiosInfo.Local;// 快速获取主板的信息// 获取进程的CPU和内存占用率varprocess=Process.GetProcessById(1234);// pid获取varcpuUsage=process.GetProcessCpuUsage();varmemory=process.GetProcessMemory();varprocesses=Process.GetProcessesByName("msedge");// 进程名获取foreach(varpinprocesses){varcpu=p.GetProcessCpuUsage();varmem=p.GetProcessMemory();Console.WriteLine($"Process{p.ProcessName} CPU:{cpu}%, Memory:{mem}MB");}
stringhtml=@"<link href='/Content/font-awesome/css' rel='stylesheet'/> <!--[if IE 7]> <link href='/Content/font-awesome-ie7.min.css' rel='stylesheet'/> <![endif]--> <script src='/Scripts/modernizr'></script> <div id='searchBox' role='search'> <form action='/packages' method='get'> <span class='user-actions'><a href='/users/account/LogOff'>退出</a></span> <input name='q' id='searchBoxInput'/> <input id='searchBoxSubmit' type='submit' value='Submit' /> </form> </div>";strings=html.HtmlSanitizerStandard();// 清理后:<div><span><a href="/users/account/LogOff">退出</a></span></div>strings=html.HtmlSanitizerCustom();// 自定义清理
类似于各大系统优化软件的加速球功能
Windows.ClearMemorySilent();
varnum=123.45.ToChineseMoney();// 壹佰贰拾叁元肆角伍分varnum=123.45.ToChineseNumber();// 一百二十三点四五
可用于生成短id,短hash,随机字符串等操作,纯数学运算。
NumberFormaternf=newNumberFormater(36);//内置2-94进制的转换//NumberFormater nf = new NumberFormater("0123456789abcdefghijklmnopqrstuvwxyz");// 自定义进制字符,可用于生成验证码,自定义字符可支持任意进制,你传1w个字符进去那就支持一万进制(手动狗头)strings36=nf.ToString(12345678);longnum=nf.FromString("7clzi");Console.WriteLine("12345678的36进制是:"+s36);// 7clziConsole.WriteLine("36进制的7clzi是:"+num);// 12345678vars=newNumberFormater(91).ToString(newRandom().Next(100000,int.MaxValue));//配合随机数生成随机字符串
//扩展方法形式调用varbin=12345678.ToBase(36);// 10进制转36进制:7clzivarnum="7clzi".FromBase(36);// 36进制转10进制:12345678
//超大数字的进制转换varnum="e6186159d38cd50e0463a55e596336bd".FromBaseBig(16);// 大数字16进制转10进制Console.WriteLine(num);// 十进制:305849028665645097422198928560410015421Console.WriteLine(num.ToBase(64));// 64进制:3C665pQUPl3whzFlVpoPqZ,22位长度Console.WriteLine(num.ToBase(36));// 36进制:dmed4dkd5bhcg4qdktklun0zh,25位长度Console.WriteLine(num.ToBase(7));// 7进制:2600240311641665565300424545154525131265221035,46位长度Console.WriteLine(num.ToBase(12));// 12进制:5217744842749978a756b22135b16a5998a5,36位长度Console.WriteLine(num.ToBase(41));// 41进制:opzeBda2aytcEeudEquuesbk,24位长度
如果你想让进制符支持emoji,NumberFormater是不支持的,不过如果你确实有这么骚的需求,我还准备了UnicodeFormater类,用于支持emoji,用法和NumberFormater一模一样,并且,UnicodeFormater的功能包含NumberFormater的功能,但是,性能比NumberFormater差了许多。
varformater=newUnicodeFormater("😀😁😂🤣😃😄😅😆😉😊😋😎😍😘🥰😗😙🥲😚🙂🤗🤩🤔🤨😑😶😶🌫🙄😏😣😥😮");vars=formater.ToString(1234567890);// 😄🌫😶😋😋varnum=formater.FromString(s);// 1234567890
HiPerfTimertimer=HiPerfTimer.StartNew();for(inti=0;i<100000;i++){//todo}timer.Stop();Console.WriteLine("执行for循环100000次耗时"+timer.Duration+"s");
doubletime=HiPerfTimer.Execute(()=>{for(inti=0;i<100000;i++){//todo}});Console.WriteLine("执行for循环100000次耗时"+time+"s");
// 实例调用varsf=SnowFlake.GetInstance();stringid=sf.GetUniqueId();// rcofqodori0wvarsfn=SnowFlakeNew.GetInstance();// 改良版雪花id,对时间回拨不敏感stringid=sfn.GetUniqueId();// vmbq8q3s3zul// 静态调用stringid=SnowFlake.NewId;// rcofqodori0wstringshortId=sf.GetUniqueShortId(8);// qodw9728stringid=SnowFlakeNew.NewId;// 改良版雪花id,对时间回拨不敏感// 全局设置SnowFlake.SetMachienId(1);// 设置机器idSnowFlake.SetInitialOffset(4219864516915105792);// 设置起始偏移量SnowFlake.SetNumberFormater(newNumberFormater("0123456789abcdefghijklmnopqrstuvwxyz._-!"));// 设置数制格式化器SnowFlakeNew.SetMachienId(1);// 设置机器idSnowFlakeNew.SetInitialOffset(4219864516915105792);// 设置起始偏移量SnowFlakeNew.SetNumberFormater(newNumberFormater("0123456789abcdefghijklmnopqrstuvwxyz._-!"));// 设置数制格式化器
varset=newHashSet<string>();doubletime=HiPerfTimer.Execute(()=>{for(inti=0;i<1000000;i++){set.Add(SnowFlake.NewId);}});Console.WriteLine(set.Count==1000000);//TrueConsole.WriteLine("产生100w个id耗时"+time+"s");//2.6891495s
ChineseCalendar.CustomHolidays.Add(DateTime.Parse("2018-12-31"),"元旦节");//自定义节假日ChineseCalendartoday=newChineseCalendar(DateTime.Parse("2018-12-31"));Console.WriteLine(today.ChineseDateString);// 二零一八年十一月廿五Console.WriteLine(today.AnimalString);// 生肖:狗Console.WriteLine(today.GanZhiDateString);// 干支:戊戌年甲子月丁酉日Console.WriteLine(today.DateHoliday);// 获取按公历计算的节假日...
Expression<Func<string,bool>>where1= s=>s.StartsWith("a");Expression<Func<string,bool>>where2= s=>s.Length>10;Func<string,bool>func=where1.And(where2).AndIf(!string.IsNullOrEmpty(name),s=>s==name).Compile();// And和AndIf可供选择,满足条件再执行Andboolb=func("abcd12345678");//true
Expression<Func<string,bool>>where1= s=>s.StartsWith("a");Expression<Func<string,bool>>where2= s=>s.Length>10;Func<string,bool>func=where1.Or(where2).OrIf(!string.IsNullOrEmpty(name),s=>s==name).Compile();// Or和OrIf可供选择,满足条件再执行Orboolb=func("abc");// true
queryable.WhereIf(!string.IsNullOrEmpty(name),e=>e.Name==name).WhereIf(()=>age.HasValue,e=>e.Age>=age);// IQueryable的WhereIf扩展函数,满足条件再执行Where
vartmp=newTemplate("{{name}},你好!");tmp.Set("name","万金油");strings=tmp.Render();//万金油,你好!
vartmp=newTemplate("{{one}},{{two}},{{three}}");strings=tmp.Set("one","1").Set("two","2").Set("three","3").Render();// 1,2,3
vartmp=newTemplate("{{name}},{{greet}}!");tmp.Set("name","万金油");strings=tmp.Render();// throw 模版变量{{greet}}未被使用
varlist=newList<MyClass>(){newMyClass(){Name="张三",Age=22},newMyClass(){Name="李四",Age=21},newMyClass(){Name="王五",Age=28}};vartable=list.Select(c=>new{姓名=c.Name,年龄=c.Age}).ToDataTable();// 将自动填充列姓名和年龄
.NET Framework
MemoryStreamms=SevenZipCompressor.ZipStream(newList<string>(){@"D:\1.txt","http://ww3.sinaimg.cn/large/87c01ec7gy1fsq6rywto2j20je0d3td0.jpg",});//压缩成内存流
SevenZipCompressor.Zip(newList<string>(){@"D:\1.txt","http://ww3.sinaimg.cn/large/87c01ec7gy1fsq6rywto2j20je0d3td0.jpg",},zip);//压缩成zipSevenZipCompressor.UnRar(@"D:\Download\test.rar",@"D:\Download\");//解压rarSevenZipCompressor.Decompress(@"D:\Download\test.tar",@"D:\Download\");//自动识别解压压缩包SevenZipCompressor.Decompress(@"D:\Download\test.7z",@"D:\Download\");
ASP.NET Core
Startup.cs
services.AddSevenZipCompressor();
构造函数注入ISevenZipCompressor
privatereadonlyISevenZipCompressor_sevenZipCompressor;publicTest(ISevenZipCompressor sevenZipCompressor){_sevenZipCompressor=sevenZipCompressor;}
使用方式同.NET Framework版本
LogManager.LogDirectory=AppDomain.CurrentDomain.BaseDirectory+"/logs";LogManager.Event+=info=>{//todo:注册一些事件操作};LogManager.Info("记录一次消息");LogManager.Error(newException("异常消息"));
varmtd=newMultiThreadDownloader("https://attachments-cdn.shimo.im/yXwC4kphjVQu06rH/KeyShot_Pro_7.3.37.7z",Environment.GetEnvironmentVariable("temp"),"E:\\Downloads\\KeyShot_Pro_7.3.37.7z",8);mtd.Configure(req=>{req.Referer="https://masuit.com";req.Headers.Add("Origin","https://baidu.com");});mtd.TotalProgressChanged+=(sender,e)=>{vardownloader=senderasMultiThreadDownloader;Console.WriteLine("下载进度:"+downloader.TotalProgress+"%");Console.WriteLine("下载速度:"+downloader.TotalSpeedInBytes/1024/1024+"MBps");};mtd.FileMergeProgressChanged+=(sender,e)=>{Console.WriteLine("下载完成");};mtd.FileMergedComplete+=(sender,e)=>{Console.WriteLine("文件合并完成");};mtd.Start();//开始下载//mtd.Pause(); // 暂停下载//mtd.Resume(); // 继续下载
varenc="123456".MDString();// MD5varenc="123456".MDString("abc");// MD5加盐varenc="123456".MDString2();// MD5两次varenc="123456".MDString2("abc");// MD5两次加盐varenc="123456".MDString3();// MD5三次varenc="123456".MDString3("abc");// MD5三次加盐stringaes="123456".AESEncrypt();// AES加密为密文strings=aes.AESDecrypt();//AES解密为明文stringaes="123456".AESEncrypt("abc");// AES密钥加密为密文strings=aes.AESDecrypt("abc");//AES密钥解密为明文stringenc="123456".DesEncrypt();// DES加密为密文strings=enc.DesDecrypt();//DES解密为明文stringenc="123456".DesEncrypt("abcdefgh");// DES密钥加密为密文strings=enc.DesDecrypt("abcdefgh");//DES密钥解密为明文RsaKeyrsaKey=RsaCrypt.GenerateRsaKeys();// 生成RSA密钥对stringencrypt="123456".RSAEncrypt(rsaKey.PublicKey);// 公钥加密strings=encrypt.RSADecrypt(rsaKey.PrivateKey);// 私钥解密strings="123".Crc32();// 生成crc32摘要strings="123".Crc64();// 生成crc64摘要strings="123".SHA256();// 生成SHA256摘要// 零宽字符串,通常用作文章暗水印,以一种看不见的字符插入到文本中,使攻击者无法直接识别文本内容,从而起到保护文章的作用,可通过代码把水印还原出来取证。stringpub="hello,world!";stringhidden="ldqk";varstr=pub.InjectZeroWidthString(hidden);// 扩展函数调用:将"ldqk"以零宽字符串的方式隐藏在"hello,world!"中varstr=ZeroWidthCodec.Encrypt(pub,hidden);// 类调用:将"ldqk"以零宽字符串的方式隐藏在"hello,world!"中vardec=str.DecodeZeroWidthString();// 扩展函数调用:将包含零宽字符串的密文解密出隐藏字符串"ldqk"vardec=ZeroWidthCodec.Decrypt(str);// 类调用:将包含零宽字符串的密文解密出隐藏字符串"ldqk"varenc=hidden.EncodeToZeroWidthText();// 扩展函数调用:将字符串编码成零宽字符串varenc=ZeroWidthCodec.Encode(str);// 类调用:将字符串编码成零宽字符串
publicclassMyClass{[IsEmail]//可在appsetting.json中添加EmailDomainWhiteList配置邮箱域名白名单,逗号分隔publicstringEmail{get;set;}[IsPhone]publicstringPhoneNumber{get;set;}[IsLandline]publicstringLandline{get;set;}[IsIPAddress]publicstringIP{get;set;}[MinValue(0,ErrorMessage="年龄最小为0岁"),MaxValue(100,ErrorMessage="年龄最大100岁")]publicintAge{get;set;}[ComplexPassword]//密码复杂度校验,默认最小长度6,最大长度30,必须包含数字、字母、特殊符号publicstringPassword{get;set;}[ComplexPassword(MustNumber=true,MustLetter=true,MustSymbol=true)]//密码复杂度校验,默认最小长度6,最大长度30,手动配置必须包含数字、字母、特殊符号publicstringPassword{get;set;}[ComplexPassword(4,12)]//密码复杂度校验,配置最小长度4,最大长度12publicstringPassword{get;set;}[EnumOf]// 检测是否是有效枚举值publicMyEnumMyEnum{get;set;}[MinItemsCount(1)]// 检测集合元素最少1个publicList<string>Strs{get;set;}[UnifiedSocialCreditCode]// 校验企业统一社会信用代码publicstringUSCC{get;set;}}
List<string>srcs="html".MatchImgSrcs().ToList();// 获取html字符串里所有的img标签的src属性varimgTags="html".MatchImgTags();//获取html字符串里的所有的img标签varstr="html".RemoveHtmlTag();// 去除html标签...
boolinRange="192.168.2.2".IpAddressInRange("192.168.1.1","192.168.3.255");// 判断IP地址是否在这个地址段里boolisPrivateIp="172.16.23.25".IsPrivateIP();// 判断是否是私有地址boolisExternalAddress="http://baidu.com".IsExternalAddress();// 判断是否是外网的URL//以下需要配置baiduAKstringisp="114.114.114.114".GetISP();// 获取ISP运营商信息PhysicsAddressphysicsAddress="114.114.114.114".GetPhysicsAddressInfo().Result;// 获取详细地理信息对象Tuple<string,List<string>>ipAddressInfo="114.114.114.114".GetIPAddressInfo().Result;// 获取详细地理信息集合uintnumber=ipAddress.ToUInt32();// IP地址转10进制uintnumber="114.114.114.114".IPToID();// IP地址转10进制
publicclassMyClass{publicstringA{get;set;}publicbool?B{get;set;}publicint?C{get;set;}}vara=newMyClass(){A="aa"};varb=newMyClass(){B=true};varc=newMyClass(){C=3};varmerge=a.Merge(b,c);// 合并后对象:A = "aa",B = true,C = 3
varlist=newList<MyClass>(){newMyClass(){Email="1@1.cn"},newMyClass(){Email="1@1.cn"},newMyClass(){Email="1@1.cn"}};List<MyClass>classes=list.DistinctBy(c=>c.Email).ToList();Console.WriteLine(classes.Count==1);//True
[Flags]publicenumMyEnum{[Display(Name="读")][Description("读")][EnumDescription("读取操作","读","zh-CN")]// 多语言枚举描述[EnumDescription("Read","Read","en-US")]Read=1,[Display(Name="写")][Description("写")]Write=2,Delete=4,All=8}
Dictionary<int,string>dic1=typeof(MyEnum).GetDictionary();// 获取枚举值和字符串表示的字典映射vardic2=typeof(MyEnum).GetDescriptionAndValue();// 获取字符串表示和枚举值的字典映射stringdesc=MyEnum.Read.GetDescription();// 获取Description标签stringdisplay=MyEnum.Read.GetDisplay();// 获取Display标签的Name属性varvalue=typeof(MyEnum).GetValue("Read");//获取字符串表示值对应的枚举值
varop=MyEnum.Read|MyEnum.Write|MyEnum.Delete;varenums=op.Split();// 拆分枚举值,得到枚举数组,这个函数建议使用在按位定值的枚举
定长队列:如果是.NET5及以上,推荐使用框架自带的Channel实现该功能
LimitedQueue<string>queue=newLimitedQueue<string>(32);// 声明一个容量为32个元素的定长队列ConcurrentLimitedQueue<string>queue=newConcurrentLimitedQueue<string>(32);// 声明一个容量为32个元素的线程安全的定长队列
线程安全的HashSet:
varset=newConcurrentHashSet<string>();// 用法和hashset保持一致
唯一队列(入队时自动去重),用法和Queue一致:
varqueue=newHashQueue<int>();// 入队操作Console.WriteLine(queue.Enqueue(1));// TrueConsole.WriteLine(queue.Enqueue(2));// TrueConsole.WriteLine(queue.Enqueue(1));// False (重复元素)// 查看队列状态Console.WriteLine($"Count:{queue.Count}");// 2Console.WriteLine($"Contains 2:{queue.Contains(2)}");// True// 出队操作Console.WriteLine(queue.Dequeue());// 1Console.WriteLine(queue.Dequeue());// 2// 批量操作varitems=new[]{1,2,3,2,4,1};queue.EnqueueRange(items);Console.WriteLine($"Count after EnqueueRange:{queue.Count}");// 4// 使用限制大小的队列varlimitedQueue=newHashQueue<string>();limitedQueue.EnqueueWithLimit("A",3);limitedQueue.EnqueueWithLimit("B",3);limitedQueue.EnqueueWithLimit("C",3);limitedQueue.EnqueueWithLimit("D",3);// 会自动移除"A"foreach(variteminlimitedQueue){Console.WriteLine(item);// 输出: B, C, D}
线程安全的唯一队列:
varset=newConcurrentHashQueue<string>();// 用法同上
MyClassmyClass=newMyClass();PropertyInfo[]properties=myClass.GetProperties();// 获取属性列表myClass.SetProperty("Email","1@1.cn");//给对象设置值myClass.DeepClone();// 对象深拷贝,带嵌套层级的myClass.ToDictionary();// 对象转字典myClass.ToDynamic();// 对象转换成动态可扩展类型
newEmail(){SmtpServer="smtp.masuit.com",// SMTP服务器SmtpPort=25,// SMTP服务器端口EnableSsl=true,//使用SSLUsername="admin@masuit.com",// 邮箱用户名Password="123456",// 邮箱密码Tos="10000@qq.com,10001@qq.com",//收件人Subject="测试邮件",//邮件标题Body="你好啊",//邮件内容}.SendAsync(s=>{Console.WriteLine(s);// 发送成功后的回调});// 异步发送邮件
"base64".SaveDataUriAsImageFile();// 将Base64编码转换成图片usingImageimage=Image.Load(@"D:\1.jpg");image.MakeThumbnail(@"D:\2.jpg",120,80,ResizeMode.BoxPad);//生成缩略图varnewBmp=image.BWPic(image.Width,image.Height);//转换成黑白varnewBmp=image.CutImage(newRectangle(0,0,1600,900));//裁剪varnewBmp=image.CutAndResize(newRectangle(0,0,1600,900),160,90);//裁剪并缩放varnewBmp=image.ResizeImage(160,90);//改变大小varnewBmp=image.RevPicLR();//左右镜像varnewBmp=image.RevPicUD();//上下镜像varnewBmp=image.LDPic(10);//调整光暗varnewBmp=image.RePic();//反色处理varnewBmp=image.Relief();//浮雕处理vargif=Image.Load(@"D:\1.gif");gif.GetFrames(@"D:\frames\");// 解压gif每帧图片varmarker=ImageWatermarker(stream);stream=maker.AddWatermark("水印文字","字体文件",字体大小,color,水印位置,边距);// 给图片添加水印stream=maker.AddWatermark(水印图片,水印位置,边距,字体大小,字体);// 给图片添加水印
varborderInfo=newImageBorderRemover(ToleranceMode.Channel).DetectBorders(原始图片);// 检测图片是否包含纯色边框newImageBorderRemover(ToleranceMode.Channel).RemoveBorders(原始图片,保存图片);// 移除图片的纯色边框并另存为
vardelta=ColorDeltaE.CIE1976(color1,color2);// 计算两个颜色的CIE1976色差vardelta=ColorDeltaE.CIE1994(color1,color2);// 计算两个颜色的CIE1994色差vardelta=ColorDeltaE.CIE2000(color1,color2);// 计算两个颜色的CIE2000色差vardelta=ColorDeltaE.CMC(color1,color2);// 计算两个颜色的CMC(l:c)色差
// 图像相似度对比varhasher=newImageHasher();varhash1=hasher.DifferenceHash256("图片1");// 使用差分哈希算法计算图像的256位哈希varhash2=hasher.DifferenceHash256("图片2");// 使用差分哈希算法计算图像的256位哈希//var hash1 = hasher.AverageHash64("图片1"); // 使用平均值算法计算图像的64位哈希//var hash2 = hasher.AverageHash64("图片2"); // 使用平均值算法计算图像的64位哈希//var hash1 = hasher.DctHash("图片1"); // 使用DCT算法计算图像的64位哈希//var hash2 = hasher.DctHash("图片2"); // 使用DCT算法计算图像的64位哈希//var hash1 = hasher.MedianHash64("图片1"); // 使用中值算法计算给定图像的64位哈希//var hash2 = hasher.MedianHash64("图片2"); // 使用中值算法计算给定图像的64位哈希varsim=ImageHasher.Compare(hash1,hash2);// 图片的相似度,范围:[0,1]varimageFormat=stream.GetImageType();// 获取图片的真实格式
最佳实践案例,以图搜图:https://github.com/ldqk/ImageSearch
Install-Package Masuit.Tools.DigitalWatermarkerInstall-Package OpenCvSharp4.runtime.win
用法参阅:Masuit.Tools.DigitalWatermarker
Randomrnd=newRandom();intnum=rnd.StrictNext();//产生真随机数doublegauss=rnd.NextGauss(20,5);//产生正态高斯分布的随机数vars=newNumberFormater(62).ToString(newRandom().Next(100000,int.MaxValue));//生成随机字符串
vardata=newList<WeightedItem<string>>(){newWeightedItem<string>("A",1),newWeightedItem<string>("B",3),newWeightedItem<string>("C",4),newWeightedItem<string>("D",4),};varitem=data.WeightedItem();//按权重选出1个元素varlist=data.WeightedItems(2);//按权重选出2个元素
varselector=newWeightedSelector<string>(newList<WeightedItem<string>>(){newWeightedItem<string>("A",1),newWeightedItem<string>("B",3),newWeightedItem<string>("C",4),newWeightedItem<string>("D",4),});varitem=selector.Select();//按权重选出1个元素varlist=selector.SelectMultiple(3);//按权重选出3个元素
list.WeightedItems(3,e=>e.Price);// 按价格权重选出3个元素list.WeightedBy(e=>e.Price);// 按价格权重选出1个元素
/// <summary>/// 按Id添加或更新文章实体/// </summary>publicoverridePostSavePost(Postt){DataContext.Set<Post>().AddOrUpdate(t=>t.Id,t);returnt;}
"13123456789".Mask();// 131****5678"admin@masuit.com".MaskEmail();// a****n@masuit.com
// Attribute的方式为json序列化时进行数据脱敏publicclassMyClass{[JsonConverter(typeof(MaskEmailConverter))]// 请注意命名空间,使用Newtonsoft.Json请导入Masuit.Tools.Systems命名空间,使用System.Text.Json请导入Masuit.Tools.Systems.Text.Json命名空间publicstringEmail{get;set;}[JsonConverter(typeof(MaskConverter))]// 请注意命名空间,使用Newtonsoft.Json请导入Masuit.Tools.Systems命名空间,使用System.Text.Json请导入Masuit.Tools.Systems.Text.Json命名空间publicstringPhoneNumber{get;set;}}
varlist=newList<string>(){"1","3","3","3"};list.AddRangeIf(s=>s.Length>1,"1","11");// 将被添加元素中的长度大于1的元素添加到listlist.AddRangeIfNotContains("1","11");// 将被添加元素中不包含的元素添加到listlist.RemoveWhere(s=>s.Length<1);// 将集合中长度小于1的元素移除list.InsertAfter(0,"2");// 在第一个元素之后插入list.InsertAfter(s=>s=="1","2");// 在元素"1"后插入vardic=list.ToDictionarySafety(s=>s);// 安全的转换成字典类型,当键重复时只添加一个键vardic=list.ToConcurrentDictionary(s=>s);// 转换成并发字典类型,当键重复时只添加一个键vardic=list.ToDictionarySafety(s=>s, s=>s.GetHashCode());// 安全的转换成字典类型,当键重复时只添加一个键varv=dic[x=>x.Key.Contains("1")];// 字典根据条件取值dic[x=>x.Key.Contains("1")]=2;// 字典根据条件赋值varv=dic[(key,value)=>key.Contains("1")];// 字典根据条件取值dic[(key,value)=>key.Contains("1")]=2;// 字典根据条件赋值varv=dic[key=>key.Contains("1")];// 字典根据key条件取值dic[key=>key.Contains("1")]=2;// 字典根据key条件赋值varv=dic[value=>value>0];// 字典根据value条件取值dic[value=>value>0]=2;// 字典根据value条件赋值dic.AddOrUpdate("4",4);// 添加或更新键值对dic.AddOrUpdate(newDictionary<string,int>(){["5"]=5,["55"]=555});// 批量添加或更新键值对dic.AddOrUpdate("5",6,(s,i)=>66);// 如果是添加,则值为6,若更新则值为66dic.AddOrUpdate("5",6,666);// 如果是添加,则值为6,若更新则值为666dic.GetOrAdd("7",77);// 字典获取或添加元素dic.GetOrAdd("7",()=>77);// 字典获取或添加元素dic.AsConcurrentDictionary();// 普通字典转换成并发字典集合vartable=list.ToDataTable();// 转换成DataTable类型table.AddIdentityColumn();//给DataTable增加一个自增列table.HasRows();// 检查DataTable 是否有数据行table.ToList<T>();// datatable转Listvarset=list.ToHashSet(s=>s.Name);// 转HashSetvarcts=newCancellationTokenSource(100);//取消口令awaitlist.ForeachAsync(async i=>{awaitTask.Delay(100);Console.WriteLine(i);},cts.Token);// 异步foreachawaitlist.ForAsync(async(item,index)=>{awaitTask.Delay(100);Console.WriteLine(item+"_"+index);},cts.Token);// 异步for,带索引编号awaitlist.SelectAsync(async i=>{awaitTask.Delay(100);returni*10;});// 异步Selectawaitlist.SelectAsync(async(item,index)=>{awaitTask.Delay(100);returnitem*10;});// 异步Select,带索引编号strings=list.Join(",");//将字符串集合连接成逗号分隔的单字符串varmax=list.MaxOrDefault();// 取最大值,当集合为空的时候不会报错varmax=list.MaxOrDefault(selector);// 取最大值,当集合为空的时候不会报错varmax=list.MaxOrDefault(selector,default);// 取最大值,当集合为空的时候不会报错varmax=list.MinOrDefault();// 取最小值,当集合为空的时候不会报错varmax=list.MinOrDefault(selector);// 取最小值,当集合为空的时候不会报错varmax=list.MinOrDefault(selector,default);// 取最小值,当集合为空的时候不会报错varstdDev=list.Select(s=>s.ConvertTo<int>()).StandardDeviation();// 求标准差varpages=queryable.ToPagedList(1,10);// 分页查询varpages=awaitqueryable.ToPagedListAsync(1,10);// 分页查询varnums=Enumerable.Range(1,10).ExceptBy(Enumerable.Range(5,10), i=>i);// 按字段取差集varnums=Enumerable.Range(1,10).IntersectBy(Enumerable.Range(5,10), i=>i);// 按字段取交集varnums=Enumerable.Range(1,10).SequenceEqual(Enumerable.Range(5,10), i=>i);// 判断序列相等varnums=Enumerable.Range(1,10).OrderByRandom();// 随机排序// 多个集合取交集varlist=newList<List<MyClass>>(){newList<MyClass>(){newMyClass(){Name="aa",Age=11},newMyClass(){Name="bb",Age=12},newMyClass(){Name="cc",Age=13},},newList<MyClass>(){newMyClass(){Name="bb",Age=12},newMyClass(){Name="cc",Age=13},newMyClass(){Name="dd",Age=14},},newList<MyClass>(){newMyClass(){Name="cc",Age=13},newMyClass(){Name="dd",Age=14},newMyClass(){Name="ee",Age=15},},};varsect=list.IntersectAll(m=>m.Name);// new MyClass(){Name="cc",Age=13}varlist=newList<List<int>>(){new(){1,2,3},new(){2,3,4},new(){3,4,5}};varsect=list.IntersectAll();// [3]// 集合元素改变其索引位置list.ChangeIndex(item,3);// 将元素item的索引位置变为第3个list.ChangeIndex(t=>t.Id=="123",2);// 将id为123的元素的索引位置变为第2个varitem=list.Percentile(50);// 取第50%分位数的元素// 比较两个集合的差异var(adds,removes,updates)=list1.CompareChanges(list2,x=>x.Id);// 按Id字段比较两个集合的差异,返回新增、删除、更新的元素var(adds,removes,updates)=list1.CompareChanges(list2,x=>x.Id+x.Name);// 按Id和Name字段比较两个集合的差异,返回新增、删除、更新的元素var(adds,removes,updates)=list1.CompareChangesPlus(list2,x=>x.Id+x.Name);// 按Id和Name字段比较两个集合的差异,返回新增、删除、更新的元素,其中updates返回的每个元素包含了旧值和新值
varmimeMapper=newMimeMapper();varext=mimeMapper.GetExtensionFromMime("image/jpeg");// .jpgvarmime=mimeMapper.GetMimeFromExtension(".jpg");// image/jpegContentType常量库:vartype=ContentType.Exe;// application/octet-streamvartype=ContentType.Jpeg;// image/jpegvartype=DefaultMimeItems.Items.FirstOrDefault(t=>t.Extension=="jpg");// image/jpeg
varweeks=DateTime.Now.GetWeekAmount();// 获取当前所在年一共有多少周varweek=DateTime.Now.WeekOfYear();// 获取当前所在年的第几周varweek=DateTime.Now.WeekOfYear(DayOfWeek.Monday);// 获取当前所在年的第几周,并指定星期几是每周第一天doublemilliseconds=DateTime.Now.GetTotalMilliseconds();// 获取毫秒级时间戳doublemicroseconds=DateTime.Now.GetTotalMicroseconds();// 获取微秒级时间戳doublenanoseconds=DateTime.Now.GetTotalNanoseconds();// 获取纳秒级时间戳doubleseconds=DateTime.Now.GetTotalSeconds();// 获取秒级时间戳doubleminutes=DateTime.Now.GetTotalMinutes();// 获取分钟级时间戳varindate=DateTime.Parse("2020-8-3").In(DateTime.Parse("2020-8-2"),DateTime.Parse("2020-8-4"));//trueDateTimetime="2021-1-1 8:00:00".ToDateTime();//字符串转DateTime//时间段计算工具varrange=newDateTimeRange(DateTime.Parse("2020-8-3"),DateTime.Parse("2020-8-5"));range.Union(DateTime.Parse("2020-8-4"),DateTime.Parse("2020-8-6"));//连接两个时间段,结果:2020-8-3~2020-8-6range.In(DateTime.Parse("2020-8-3"),DateTime.Parse("2020-8-6"));//判断是否在某个时间段内,truevar(intersected,range2)=range.Intersect(DateTime.Parse("2020-8-4"),DateTime.Parse("2020-8-6"));//两个时间段是否相交,(true,2020-8-3~2020-8-4)range.Contains(DateTime.Parse("2020-8-3"),DateTime.Parse("2020-8-4"));//判断是否包含某个时间段,truerange.GetUnionSet(List<DateTimeRange>);// 根据某个时间段查找在某批时间段中的最大并集range.GetMaxTimePeriod(List<DateTimeRange>);// 获取一批时间段内存在相互重叠的最大时间段varrange=DateTime.Now.GetCurrentWeek();// 获取当前时间所在周的时间区间:2024-08-05 00:00:00~2024-08-11 23:59:59varrange=DateTime.Now.GetCurrentMonth();// 获取当前时间所在月的时间区间:2024-08-01 00:00:00~2024-08-31 23:59:59varrange=DateTime.Now.GetCurrentYear();// 获取当前时间所在年的时间区间:2024-01-01 00:00:00~2024-12-31 23:59:59varrange=DateTime.Now.GetCurrentQuarter();// 获取当前时间所在季度的时间区间:2024-07-01 00:00:00~2024-09-30 23:59:59varrange=DateTime.Now.GetCurrentLunarMonth();// 获取当前时间所在农历月的时间区间:2024-08-04 00:00:00~2024-09-02 23:59:59varrange=DateTime.Now.GetCurrentLunarQuarter();// 获取当前时间所在农历季度的时间区间:2024-08-04 00:00:00~2024-10-31 23:59:59varrange=DateTime.Now.GetCurrentLunarYaer();// 获取当前时间所在农历年的时间区间:2024-02-10 00:00:00~2025-01-28 23:59:59varrange=DateTime.Now.GetCurrentSolar();// 获取当前时间所在季节的时间区间:2024-08-07 00:00:00~2024-11-06 23:59:59varrange=DateTime.Now.GetCurrentRange(DateRangeType.Week);// 获取当前时间所在周的时间区间:2024-08-05 00:00:00~2024-08-11 23:59:59varrange=DateTime.Now.GetCurrentRange(DateRangeType.Month);// 获取当前时间所在月的时间区间:2024-08-01 00:00:00~2024-08-31 23:59:59varrange=DateTime.Now.GetCurrentRange(DateRangeType.Quarter);// 获取当前时间所在季度的时间区间:2024-07-01 00:00:00~2024-09-30 23:59:59varrange=DateTime.Now.GetCurrentRange(DateRangeType.Year);// 获取当前时间所在年的时间区间:2024-01-01 00:00:00~2024-12-31 23:59:59varrange=DateTime.Now.GetCurrentRange(DateRangeType.LunarMonth);// 获取当前时间所在农历月的时间区间:2024-08-04 00:00:00~2024-09-02 23:59:59varrange=DateTime.Now.GetCurrentRange(DateRangeType.LunarQuarter);// 获取当前时间所在农历季度的时间区间:2024-08-04 00:00:00~2024-10-31 23:59:59varrange=DateTime.Now.GetCurrentRange(DateRangeType.LunarYear);// 获取当前时间所在农历年的时间区间:2024-02-10 00:00:00~2025-01-28 23:59:59varrange=DateTime.Now.GetCurrentRange(DateRangeType.Solar);// 获取当前时间所在季节的时间区间:2024-08-07 00:00:00~2024-11-06 23:59:59...
stream.SaveAsMemoryStream();// 任意流转换成内存流stream.ToArray();// 任意流转换成二进制数组stream.ToArrayAsync();// 任意流转换成二进制数组stream.ShuffleCode();// 流洗码,在流的末端随即增加几个空字节,重要数据请谨慎使用,可能造成流损坏// 池化内存流,用法与MemorySteam保持一致usingvarms=PooledMemoryStream();// 大型内存流,最大可支持1TB内存数据,推荐当数据流大于2GB时使用,用法与MemorySteam保持一致usingvarms=LargeMemoryStream();//文件流快速复制FileStreamfs=newFileStream(@"D:\boot.vmdk",FileMode.OpenOrCreate,FileAccess.ReadWrite);{//fs.CopyToFile(@"D:\1.bak");//同步复制大文件fs.CopyToFileAsync(@"D:\1.bak");//异步复制大文件stringmd5=fs.GetFileMD5Async().Result;//异步获取文件的MD5stringsha1=fs.GetFileSha1();//异步获取文件的SHA1}memoryStream.SaveFile("filename");// 将内存流转储成文件
1.2345678901.Digits8();// 将小数截断为8位1.23.ConvertTo<int>();// 小数转int1.23.ConvertTo<T>();// 小数转T基本类型boolb=1.23.TryConvertTo<T>(outresult);// 小数转T基本类型varnum=1.2345.ToDecimal(2);//转decimal并保留两位小数1.23.ChangeTypeTo<T>();//小数转T基本类型,ConvertTo和ChangeTypeTo的区别在于:ConvertTo只适用于基元类型的互转,ChangeTypeTo不仅适用于基元类型的互转还支持数组、字符串的转换(Parse),ConvertTo的性能更高type.IsPrimitive();// 判断类型是否是值类型type.IsSimpleType();// 判断类型是否是常见的简单类型,基元类型为 Boolean、 Byte、 SByte、 Int16、 UInt16、 Int32、 UInt32、 Int64、 UInt64、 IntPtr、 UIntPtr、 Char、 Double 、 Single、枚举、Nullable<T>。type.IsSimpleArrayType();// 判断类型是否是常见类型的 数组形式 类型type.IsSimpleListType();// 判断类型是否是常见类型的 泛型形式 类型myClass.ToJsonString();//序列化成json字符串strings=null;boolb=s.IsNullOrEmpty();//判断字符串是否为空boolb=s.NotNullOrEmpty();//判断字符串不为空stringstr=s.IfNullOrEmpty("aa");//如果为空则返回aastringstr=s.IfNullOrEmpty(()=>"aa");//如果为空则返回aa,延迟执行boolcontains=s.Contains(new[]{"aa","bb"});// 检测字符串中是否包含列表中的关键词(快速匹配)boolcontains=s.ContainsSafety(new[]{"aa","bb"});// 检测字符串中是否包含列表中的关键词(安全匹配),没有计时攻击风险boolcontains=s.EndsWith(new[]{"aa","bb"});// 检测字符串中是否以列表中的任意关键词结尾boolcontains=s.StartsWith(new[]{"aa","bb"});// 检测字符串中是否以列表中的任意关键词开头stringstr=s.Take(10);// 取字符串前10个字符boolemoji=s.MatchEmoji();// 匹配字符串是否包含emojivarwidth=str.StringWidth(14);// 计算字符串以14号字体大小的渲染宽度像素varwidth=str.StringWidth("微软雅黑",14);// 计算字符串以14号字体大小的微软雅黑字体的渲染宽度像素varwidth=str.CharacterCount();// 获取字符串的字符数varwidth=str.BytesCount();// 获取字符串的字节数vars="🤔1🥳a👨👩👧👦啊";Console.WriteLine("长度:"+s.Length);// 18Console.WriteLine("宽度:"+s.StringWidth());// 7Console.WriteLine("字节数:"+s.BytesCount());// 38Console.WriteLine("字符数:"+s.CharacterCount());// 6vars="aa".ToSBC();// 转换为全角vars="aa".ToDBC();// 转换为半角
IniFileini=newIniFile("X:\\filename.ini");// 需要绝对路径,否则会写到C:\Windows目录下去ini.SetValue(section,key,value);// 写值varvalue=ini.GetValue(section,key);// 读值varvalue=ini.GetValue<Enum>(section,key);// 读值并转换类型varsections=ini.GetSections();// 获取所有配置节varsection=ini.GetSection(section);// 获取配置节varmyclass=ini.GetSection<MyClass>(section);// 获取指定配置节并绑定到对象ini.ClearAllSection();// 清空所有配置节ini.ClearSection(section);// 清空配置节ini.Save();// 保存ini文件ini.Reload();// 重新加载ini文件classMyClass{[IniProperty("str_value")]// 设置别名publicstringStringValue{get;set;}}
应用场景:计算两个多边形的相似度,用户画像之类的
varpoints=RadarChartEngine.ComputeIntersection(chart1,chart2);//获取两个多边形的相交区域points.ComputeArea();//计算多边形面积
基本接口类:ITreeChildren:带Children属性的接口
ITreeParent:带Parent属性的接口
ITree:继承ITreeParent和ITreeChildren,同时多了Name属性
ITreeEntity:继承ITreeChildren,同时多了Id和ParentId属性
相关扩展方法:
trees.Filter(func);// 从树形集合中过滤trees.Flatten();// 将数据平铺开tree.AllChildren();// 获取所有的子级tree.AllParent();// 获取所有的父级tree.IsRoot();// 是否是根节点tree.IsLeaf();// 是否是叶子节点tree.Level();// 所处深度/层级tree.Path();// 全路径vartree=list.ToTree();//集合元素继承自ITreeEntity<T,TKey>或ITreeEntity<T>的集合转换成树形结构vartree=list.ToTree(c=>c.Id, c=>c.Pid);//集合元素继承自ITreeParent<T>, ITreeChildren<T>的集合转换成树形结构vartree=list.ToTreeGeneral(c=>c.Id, c=>c.Pid);//一般的集合转换成树形结构
需要额外依赖包:Masuit.Tools.Excel
varstream=list.Select(item=>new{姓名=item.Name,年龄=item.Age,item.Gender,Avatar=Image.FromStream(filestream)//图片列}).ToDataTable().ToExcel("Sheet1");//自定义列名导出varstream=list.ToDataTable("Sheet1").ToExcel("文件密码");
- 图片列支持Stream、Bitmap、IEnumerable
<Stream>、IEnumerable<Bitmap>、IDictionary<string,Stream>、IDictionary<string,MemoryStream>、IDictionary<string,Bitmap>类型; - 其中,如果是IDictionary类型的图片列,字典的键为图片超链接的完整url;
- 默认字段名作为列名导出;
- 若list是一个具体的强类型,默认会先查找每个字段的Description标记,若有Description标记,则取Description标记作为列名显示
- 具体的强类型,若属性被打上ExcelIgnore或EpplusIgnore标记,则该属性不会被导出;若需要设置字段的格式化输出,可以使用ExcelColumn属性进行标记,也可以通过参数传入一个字典来设置列的格式化输出;
- ToExcel方法支持DataTable、List
<DataTable>、Dictionary<string, DataTable>类型的直接调用
获取指定实体的变更
varchanges=dbContext.GetChanges<TEntity>();//获取变更字段信息varadded=dbContext.GetAdded<TEntity>();//获取添加的实体字段信息varremoved=dbContext.GetRemoved<TEntity>();//获取被移除的实体字段信息varallchanges=dbContext.GetAllChanges<TEntity>();//获取增删改的实体字段信息
获取所有实体的变更
varchanges=dbContext.GetChanges();//获取变更字段信息varadded=dbContext.GetAdded();//获取添加的实体字段信息varremoved=dbContext.GetRemoved();//获取被移除的实体字段信息varallchanges=dbContext.GetAllChanges();//获取增删改的实体字段信息
对比信息包含属性信息、旧值、新值、实体信息、键信息、变更状态等
SQL Server:
上下文注入Interceptor即可在任何查询时使用nolock查询
services.AddDbContext<TContext>(opt=>opt.UseSqlserver("ConnString", builder=>builder.AddInterceptors(newWithNoLockInterceptor(true)));// 启用全局nolock查询services.AddDbContext<TContext>(opt=>opt.UseSqlserver("ConnString", builder=>builder.AddInterceptors(newWithNoLockInterceptor()));// 按需启用全局nolock查询// 按需启用全局nolock查询,执行单个nolock查询awaitdbContext.Users.Where(x=>x.Name=="aaa").WithNolock().ToListAsync();
其他通用数据库:
nolock本质是开启一个读未提交级别的事务,此时的查询性能最好,但有可能会读取到脏数据。
dbcontext.NoLock(ctx=>ctx.Users...ToList());// 开启一个nolock上下文,上下文范围内自动nolock// 执行单个nolock查询awaitdbcontext.Users.Where(x=>x.Name=="aaa").ToListWithNoLockAsync();awaitdbcontext.Users.Where(x=>x.Name=="aaa").FirstOrDefaultWithNoLockAsync();awaitdbcontext.Users.Where(x=>x.Name=="aaa").SingleOrDefaultWithNoLockAsync();awaitdbcontext.Users.AnyWithNoLockAsync(x=>x.Name=="aaa");awaitdbcontext.Users.AllWithNoLockAsync(x=>x.Name=="aaa");awaitdbcontext.Users.CountWithNoLockAsync(x=>x.Name=="aaa");// 如果在上下文开启了重试机制,执行单个nolock查询需要开启策略查询services.AddDbContext<TContext>(opt=>opt.UseNpgsql("ConnString", builder=>builder.EnableRetryOnFailure(10));// 执行策略dbcontext.ExecutionStrategy(stg=>stg.NoLock(ctx=>ctx.Users...ToList()));dbcontext.ExecutionStrategy(ctx=>ctx.Users.Where(x=>x.Name=="aaa").ToListWithNoLockAsync());
// 如果你现在正在写类似这样的代码:dbcontext.Category.Include(c=>c.Children).ThenInclude(c=>c.Children).ThenInclude(c=>c.Children).ThenInclude(c=>c.Children);// 那么可以改成这样:dbcontext.Category.IncludeRecursive(4, c=>c.Children);// 自动Include 4次
a.Next(func1).Next(func2).Next(func3);"123".Next(s=>s.ToInt32()).Next(x=>x*2).Next(x=>Math.Log(x));
该解释器针对类属性被DeserializeOnlyJsonPropertyAttribute/SerializeIgnoreAttribute标记的,在反序列化的时候生效,在序列化的时候忽略;被SerializeOnlyJsonPropertyAttribute/DeserializeIgnoreAttribute标记的,在序列化的时候生效,在反序列化的时候忽略
publicclassClassDto{// 序列化时忽略这个属性/反序列化时加载这个属性[DeserializeOnlyJsonProperty]//[SerializeIgnore]publicstringMyProperty{get;set;}// 反序列化时忽略这个属性/序列化时加载这个属性[SerializeOnlyJsonProperty]//[DeserializeIgnore]publicintNum{get;set;}}// Newtonsoft.JsonJsonConvert.SerializeObject(newMyClass(),newJsonSerializerSettings(){ContractResolver=newDeserializeOnlyContractResolver()// 配置使用DeserializeOnlyContractResolver解释器});// System.Text.JsonJsonSerializer.Serialize(object,newJsonSerializerOptions(){TypeInfoResolver=newSerializeIgnoreResolver()});
如果是WebAPI全局使用:
//在Startup.ConfigureServices中services.AddMvc().AddNewtonsoftJson(options=>{varresolver=newDeserializeOnlyContractResolver();resolver.NamingStrategy=newCamelCaseNamingStrategy();options.SerializerSettings.ContractResolver=resolver;});
该解释器针对某个属性设置多个别名,反序列化时支持多个别名key进行绑定,弥补官方JsonProperty别名属性只能设置单一别名的不足
publicclassClassDto{[FallbackJsonProperty("MyProperty","a","b")]publicstringMyProperty{get;set;}publicintNum{get;set;}}JsonConvert.SerializeObject(newMyClass(),newJsonSerializerSettings(){ContractResolver=newFallbackJsonPropertyResolver()// 配置使用FallbackJsonPropertyResolver解释器});
该解释器是DeserializeOnlyContractResolver和FallbackJsonPropertyResolver的融合版
用法:引入包:Masuit.Tools.AspNetCore
PM> Install-Package Masuit.Tools.AspNetCoreStartup配置:
app.UseBodyOrDefaultModelBinder();
在action的参数模型前打上标记:[FromBodyOrDefault]即可,示例代码如下:
[HttpGet("query"),HttpPost("query")]publicIActionResultQuery([FromBodyOrDefault]QueryModelquery){returnOk(...);}[HttpGet("query"),HttpPost("query")]publicIActionResultQuery([FromBodyOrDefault]intid,[FromBodyOrDefault]stringname){returnOk(...);}
vardis="12345678".HammingDistance("1234567");vardis=newSimHash("12345678").HammingDistance(newSimHash("1234567"));
varencoding=newFileInfo(filepath).GetEncoding();// 获取文件编码(扩展调用)varencoding=stream.GetEncoding();// 获取流的编码(扩展调用)varencoding=TextEncodingDetector.GetEncoding(filepath);// 获取文件编码(类调用)// 多种方式,任君调用vardetector=newFileInfo(filepath).DetectFiletype();// 扩展调用//var detector=File.OpenRead(filepath).DetectFiletype(); // 流扩展调用//var detector=FileSignatureDetector.DetectFiletype(filepath); // 类调用detector.Precondition;//基础文件类型detector.Extension;//真实扩展名detector.MimeType;//MimeTypedetector.FormatCategories;//格式类别
| 扩展名 | 说明 |
|---|---|
| 3GP | 3GPP, 3GPP 2 |
| 7Z | 7-Zip |
| APK | ZIP based Android Package |
| AVI | Audio-Video Interleave |
| SH | Shell Script |
| BPLIST | Binary Property List |
| BMP, DIB | Bitmap |
| BZ2 | Bunzip2 Compressed |
| CAB | Microsoft Cabinet |
| CLASS | Java Bytecode |
| CONFIG | .NET Configuration File |
| CRT, CERT | Certificate |
| CUR | Cursor |
| DB | Windows Thumbs.db Thumbnail Database |
| DDS | DirectDraw Surface |
| DLL | Windows Dynamic Linkage Library |
| DMG | Apple Disk Mount Image |
| DMP | Windows Memory Dump File |
| DOC | Microsoft Office Word 97-2003 Document |
| DOCX | Microsoft Office Word OpenXML Document |
| EPUB | e-Pub Document |
| EXE | Windows Executive |
| FLAC | Loseless Audio |
| FLV | Flash Video |
| GIF | Graphics Interchage Format |
| GZ | GZ Compressed |
| HDP | HD Photo(JPEG XR) Image |
| HWP | Legacy HWP, HWPML, CFBF HWP |
| ICO | Icon |
| INI | Initialization File |
| ISO | ISO-9660 Disc Image |
| LNK | Windows Shortcut Link |
| JP2 | JPEG 2000 Image |
| JPG, JPEG | Joint Photographic Experts Group Image |
| LZH | LZH Compressed |
| M4A | MP4 Container Contained Audio Only |
| M4V | MP4 Container Contained Video |
| MID | Midi Sound |
| MKA | Matroska Container Contained Audio Only |
| MKV | Matroska Container Contained Video |
| MOV | QuickTime Movie Video |
| MP4 | MP4 Container Contained Contents |
| MSI | Microsoft Installer |
| OGG | OGG Video or Audio |
| ODF | OpenDocument Formula |
| ODG | OpenDocument Graphics |
| ODP | OpenDocument Presentation |
| ODS | OpenDocument Spreadsheet |
| ODT | OpenDocument Text |
| PAK | PAK Archive or Quake Archive |
| PDB | Microsoft Program Database |
| Portable Document Format | |
| PFX | Microsoft Personal Information Exchange Certificate |
| PNG | Portable Network Graphics Image |
| PPT | Microsoft Office PowerPoint 97-2003 Document |
| PPTX | Microsoft Office PowerPoint OpenXML Document |
| PPSX | Microsoft Office PowerPoint OpenXML Document for Slideshow only |
| PSD | Photoshop Document |
| RAR | WinRAR Compressed |
| REG | Windows Registry |
| RPM | RedHat Package Manager Package |
| RTF | Rich Text Format Document |
| SLN | Microsoft Visual Studio Solution |
| SRT | SubRip Subtitle |
| SWF | Shockwave Flash |
| SQLITE, DB | SQLite Database |
| TAR | pre-ISO Type and UStar Type TAR Package |
| TIFF | Tagged Image File Format Image |
| TXT | Plain Text |
| WAV | Wave Audio |
| WASM | Binary WebAssembly |
| WEBM | WebM Video |
| WEBP | WebP Image |
| XAR | XAR Package |
| XLS | Microsoft Office Excel 97-2003 Document |
| XLSX | Microsoft Office Excep OpenXML Document |
| XML | Extensible Markup Language Document |
| Z | Z Compressed |
| ZIP | ZIP Package |
让动态类型支持属性访问器和索引器调用
varobj=DynamicFactory.NewObject();obj.Name="Masuit";obj.Age=18;obj["Gender"]="男" obj.MyClass=DynamicFactory.WithObject(new{X=10,Y=20,Z=newList<int>{1,2,3,4,5}});Assert.Equal(obj.Name,obj["Name"]);Assert.Equal(obj["Gender"],obj.Gender);Assert.Equal(obj["MyClass"]["X"],obj.MyClass.X);Assert.Equal(obj.MyClass.Z[2],obj["MyClass"]["Z"][2]);
普通类型转换成动态类型
varobj=new{Name="Masuit"}.ToDynamic();obj.Age=18;obj.MyClass=new{X=10,Y=20,Z=newList<int>{1,2,3,4,5}}.ToDynamic();obj.Prop="test";_=obj-"Prop";// 删除属性_=obj+"Prop";// 增加属性Assert.Equal(obj.Name,obj["Name"]);Assert.Equal(obj["MyClass"]["X"],obj.MyClass.X);
// 要求系统WindowsDefender没有被停掉varresult=WindowsDefenderScanService.ScanFile(@"Y:\1.exe");// 扫描文件varresult=WindowsDefenderScanService.ScanDirectory(@"Y:\");// 扫描文件夹varresult=WindowsDefenderScanService.ScanStream(stream);// 扫描文件流// 要求C:\Windows\System32\amsi.dll文件存在,可在WindowsDefender停止时工作AmsiScanService.Scan(stream);// 扫描文件流AmsiScanService.Scan(@"Y:\1.exe");// 扫描文件AmsiScanService.Scan(bytes);// 扫描二进制数组
varcode=ValidateCode.ValidateCode(6);// 生成6位长度的验证码varstream=code.CreateValidateGraphic();// 生成验证码图片流
varitem=cache.Get<T>(key);// 获取值varitem=cache.GetOrAdd<T>(key,value);// 获取或添加值varitem=cache.GetOrAdd<T>(key,valueFactory);// 获取或添加值cache.Set<T>(key,value);// 设置值cache.AddOrUpdate<T>(key,value,valueFactory);// 添加或更新值
varitem=ViewData.GetValue<T>(key);//获取对象varitem=ViewData.GetValueOrDefault<T>(key,defaultValue);//获取对象varitem=ViewData.GetValueOrDefault<T>(key,defaultValueFactory);//获取对象
CurrentContext<T>.SetData(value);//设置值varitem=CurrentContext<T>.GetData();//获取值CurrentContext.SetData(value);//设置值varitem=CurrentContext.GetData<T>();//获取值
包:Masuit.Tools.AspNetCore
// 自动扫描注册服务services.AutoRegisterServices();// 需要自动注册的服务打上ServiceInject标记即可。[ServiceInject(ServiceLifetime.Scoped)]publicclassMyClass:MyInterface{...}[ServiceInject(ServiceLifetime.Scoped)]publicclassMyService{...}
集成案例:https://masuit.org/1889/history
vartext1="<h1>你好 UEditorPlus</h1><p>UEditorPlus 是基于 UEditor 二次开发的富文本编辑器,让 UEditor <span style=\"color: #E36C09;\">焕<span style=\"color: #0070C0;\">然</span><span style=\"color: #31859B;\"><span style=\"color: #00B050;\">一</span><span style=\"color: #FF0000;\">新</span></span></span></p><table data-sort=\"sortDisabled\"><tbody><tr class=\"firstRow\"><td valign=\"top\" style=\"word-break: break-all;\" rowspan=\"1\" colspan=\"3\">我是表格</td></tr><tr><td width=\"273\" valign=\"top\" style=\"word-break: break-all;\">如果</td><td width=\"273\" valign=\"top\" style=\"word-break: break-all;\">有一天</td><td width=\"273\" valign=\"top\" style=\"word-break: break-all;\">我离开了</td></tr><tr><td valign=\"top\" colspan=\"1\" rowspan=\"1\" style=\"word-break: break-all;\">怎么才能</td><td valign=\"top\" colspan=\"1\" rowspan=\"1\" style=\"word-break: break-all;\">证明我</td><td valign=\"top\" colspan=\"1\" rowspan=\"1\" style=\"word-break: break-all;\">曾经来过</td></tr></tbody></table><h2>公式支持</h2><p><img src=\"https://r.latexeasy.com/image.svg?%5Cint%20%5Cfrac%7B1%7D%7Bx%7D%20dx%20%3D%20%5Cln%20%5Cleft%7C%20x%20%5Cright%7C%20%2B%20C\" data-formula-image=\"%5Cint%20%5Cfrac%7B1%7D%7Bx%7D%20dx%20%3D%20%5Cln%20%5Cleft%7C%20x%20%5Cright%7C%20%2B%20C\"/></p><p><br/></p>";vartext2="<p>UEditorPlus 是基于 UEditor 二次开发的富文本编辑器,让 UEditor <span style=\"color: #E36C09;\">焕<p style=\"color: #0070C0;\">然</p><span style=\"color: #31859B;\"><span style=\"color: #00B050;\">一</span><span style=\"color: #FF0000;\">新</span></span></span></p><table data-sort=\"sortDisabled\"><tbody><tr class=\"firstRow\"><td valign=\"top\" style=\"word-break: break-all;\" rowspan=\"1\" colspan=\"3\">我是表格</td></tr><tr><td width=\"273\" valign=\"top\" style=\"word-break: break-all;\">如果</td><td width=\"273\" valign=\"top\" style=\"word-break: break-all;\">有一天</td><td width=\"273\" valign=\"top\" style=\"word-break: break-all;\">我离开了</td></tr><tr><td valign=\"top\" colspan=\"1\" rowspan=\"1\" style=\"word-break: break-all;\">怎么才能</td><td valign=\"top\" colspan=\"1\" rowspan=\"1\" style=\"word-break: break-all;\">证明我</td><td valign=\"top\" colspan=\"1\" rowspan=\"1\" style=\"word-break: break-all;\">曾经来过</td></tr></tbody></table><pre class=\"brush:html;toolbar:false\"><div>\r\n <span>这里是HTML标签</span>\r\n</div></pre><h2>公式支持23333333</h2><p><img src=\"https://r.latexeasy.com/image.svg?%5Cint%20%5Cfrac%7B1%7D%7Bx%7D%20dx%20%3D%20%5Cln%20%5Cleft%7C%20x%20%5Cright%7C%20%2B%20C\" data-formula-image=\"%5Cint%20%5Cfrac%7B1%7D%7Bx%7D%20dx%20%3D%20%5Cln%20%5Cleft%7C%20x%20%5Cright%7C%20%2B%20C\"/></p><p><br/></p>";var(html1,html2)=text1.HtmlDiff(text2);// 对比两段文本并分别生成差异vardiffs=TextDiffer.Compute(text1,text2);// 对比两段文本并分别生成差异详细记录varpatches=DiffPatch.FromDiffs(diffs);// 根据差异信息生成补丁patches.ToText();// 根据补丁记录重建文本(stringnewText,bool[]results)=patches.Apply(text1);// 将变更补丁应用到原始文本1,并返回是否应用成功vartext1=diffs.Text1();// 根据差异信息还原文本1vartext2=diffs.Text2();// 根据差异信息还原文本2vardelta=diffs.ToDelta();// 根据差异信息生成类似于git差异的差分记录vardiffs=text1.FromDelta(delta);// 根据差分信息生成差异记录
集成案例:https://masuit.org/tools/loan
支持多次提前还款和多次调整利率,同时支持提前还款时变更贷款方式和缩短年限,如有利率调整或提前还款计划,因银行计算受实时利率或提前还款违约金影响,本试算模型的计算结果和银行结果大约有1‰的误差,结果仅供参考,请以银行结果为准。
模拟案例:贷款100万,初始利率6.27%,等额本息方式,贷30年,首次还款时间2021-2-1。
利率调整:2022-1-1利率调整为5.92%,LPR调整2023-1-1利率调整为5.85%,LPR调整2023-9-25利率调整为4.3%,政策因素银行自动调整2025-1-1利率调整为4.2%,LPR调整2026-1-1利率调整为4.1%,LPR调整
提前还款计划:2022-10-23提前还款10万,贷款方式不变,2023-10-11提前还款10万并缩短年限(实际目前银行政策不允许),2025-10-12提前还款10万并修改为等额本金方式,2026-10-14提前还款10万并以等额本金方式+缩短年限(实际目前银行政策不允许)。
计算代码如下:
var(totalInterest,actualInterest,savedInterest,totalRepayment,actualPayment,paymentPlans)=newLoanModel(1000000,0.0627m,360,DateTime.Parse("2021-2-1")){RateAdjustments=newDictionary<DateTime,decimal?>(){[DateTime.Parse("2022-1-1")]=0.0592m,// 调整前月供6170.19,调整后月供5948.53[DateTime.Parse("2023-1-1")]=0.058m,// 调整前月供5948.53,调整后月供5273.92[DateTime.Parse("2023-9-25")]=0.043m,// 调整前月供5273.92,调整后月供4496.91,调整次月还款5118.55[DateTime.Parse("2025-1-1")]=0.042m,// 调整前月供4496.91,调整后首月4457.15[DateTime.Parse("2026-1-1")]=0.041m,// 调整前月供4762.47,调整后月供4702,调整次月还款8.87元(还款方式改为了等额本金)},Prepayments=newList<PrepaymentOption>(){new(DateTime.Parse("2022-10-23"),100000m,false,LoanType.EquivalentInterest),// 提前还款前月供5948.53,提前还款后月供5339.85new(DateTime.Parse("2023-10-11"),100000m,true,LoanType.EquivalentInterest),// 提前还款前月供5273.92,提前还款后月供4493.84,期数减少64期new(DateTime.Parse("2025-10-12"),100000m,false,LoanType.EquivalentPrincipal),// 提前还款前月供4771.56,提前还款后月供首月4762.47,每月递减60.4元new(DateTime.Parse("2026-10-14"),100000m,true,LoanType.EquivalentPrincipal),// 提前还款前月供4260.28,提前还款后月供首月4251.44,每月递减8.84元,期数减少38期}}.Payment();
计算结果:总利息totalInterest:1221266.8实际支付利息actualInterest:403845.58提前还款节省利息savedInterest:817421.22总提前还款totalRepayment:400000.00实际还款总额actualPayment:1403845.58总还款期数paymentPlans:258期,List类型,每条记录可以展示当期的利率,利息,本金,剩余本金等信息
在ASP.NET Core中通过MVC/WebAPI应用程序传输文件数据时使用断点续传以及多线程下载支持。
它提供了ETag标头以及Last-Modified标头。 它还支持以下前置条件标头:If-Match,If-None-Match,If-Modified-Since,If-Unmodified-Since,If-Range。
从.NET Core2.0开始,ASP.NET Core内部支持断点续传。 因此只是对FileResult做了一些扩展。 只留下了“Content-Disposition” Inline的一部分。 所有代码都依赖于基础.NET类。
在你的控制器中,你可以像在FileResult一样的方式使用它。
usingMasuit.Tools.Mvc;usingMasuit.Tools.Mvc.ResumeFileResult;
privatereadonlyMimeMappermimeMapper=newMimeMapper();// 推荐使用依赖注入publicActionResultResumeFileResult(){varpath=Server.MapPath("~/Content/test.mp4");returnnewResumeFileResult(path,mimeMapper.GetMimeFromPath(path),Request);}publicActionResultResumeFile(){returnthis.ResumeFile("~/Content/test.mp4",mimeMapper.GetMimeFromPath(path),"test.mp4");}publicActionResultResumePhysicalFile(){returnthis.ResumePhysicalFile(@"D:/test.mp4",mimeMapper.GetMimeFromPath(@"D:/test.mp4"),"test.mp4");}
要使用ResumeFileResults,必须在Startup.cs的ConfigureServices方法调用中配置服务:
usingMasuit.Tools.AspNetCore.ResumeFileResults.Extensions;
publicvoidConfigureServices(IServiceCollectionservices){services.AddResumeFileResult();}
然后在你的控制器中,你可以像在FileResult一样的方式使用它。
点击查看代码
usingMasuit.Tools.AspNetCore.ResumeFileResults.Extensions;
privateconststringEntityTag="\"TestFile\"";privatereadonlyIHostingEnvironment_hostingEnvironment;privatereadonlyDateTimeOffset_lastModified=newDateTimeOffset(2016,1,1,0,0,0,TimeSpan.Zero);/// <summary>////// </summary>/// <param name="hostingEnvironment"></param>publicTestController(IHostingEnvironment hostingEnvironment){_hostingEnvironment=hostingEnvironment;}[HttpGet("content/{fileName}/{etag}")]publicIActionResultFileContent(boolfileName,booletag){stringwebRoot=_hostingEnvironment.WebRootPath;varcontent=System.IO.File.ReadAllBytes(Path.Combine(webRoot,"TestFile.txt"));ResumeFileContentResultresult=this.ResumeFile(content,"text/plain",fileName?"TestFile.txt":null,etag?EntityTag:null);result.LastModified=_lastModified;returnresult;}[HttpGet("content/{fileName}")]publicIActionResultFileContent(boolfileName){stringwebRoot=_hostingEnvironment.WebRootPath;varcontent=System.IO.File.ReadAllBytes(Path.Combine(webRoot,"TestFile.txt"));varresult=newResumeFileContentResult(content,"text/plain"){FileInlineName="TestFile.txt",LastModified=_lastModified};returnresult;}[HttpHead("file")]publicIActionResultFileHead(){ResumeVirtualFileResultresult=this.ResumeFile("TestFile.txt","text/plain","TestFile.txt",EntityTag);result.LastModified=_lastModified;returnresult;}[HttpPut("file")]publicIActionResultFilePut(){ResumeVirtualFileResultresult=this.ResumeFile("TestFile.txt","text/plain","TestFile.txt",EntityTag);result.LastModified=_lastModified;returnresult;}[HttpGet("stream/{fileName}/{etag}")]publicIActionResultFileStream(boolfileName,booletag){stringwebRoot=_hostingEnvironment.WebRootPath;FileStreamstream=System.IO.File.OpenRead(Path.Combine(webRoot,"TestFile.txt"));ResumeFileStreamResultresult=this.ResumeFile(stream,"text/plain",fileName?"TestFile.txt":null,etag?EntityTag:null);result.LastModified=_lastModified;returnresult;}[HttpGet("stream/{fileName}")]publicIActionResultFileStream(boolfileName){stringwebRoot=_hostingEnvironment.WebRootPath;FileStreamstream=System.IO.File.OpenRead(Path.Combine(webRoot,"TestFile.txt"));varresult=newResumeFileStreamResult(stream,"text/plain"){FileInlineName="TestFile.txt",LastModified=_lastModified};returnresult;}[HttpGet("physical/{fileName}/{etag}")]publicIActionResultPhysicalFile(boolfileName,booletag){stringwebRoot=_hostingEnvironment.WebRootPath;ResumePhysicalFileResultresult=this.ResumePhysicalFile(Path.Combine(webRoot,"TestFile.txt"),"text/plain",fileName?"TestFile.txt":null,etag?EntityTag:null);result.LastModified=_lastModified;returnresult;}[HttpGet("physical/{fileName}")]publicIActionResultPhysicalFile(boolfileName){stringwebRoot=_hostingEnvironment.WebRootPath;varresult=newResumePhysicalFileResult(Path.Combine(webRoot,"TestFile.txt"),"text/plain"){FileInlineName="TestFile.txt",LastModified=_lastModified};returnresult;}[HttpGet("virtual/{fileName}/{etag}")]publicIActionResultVirtualFile(boolfileName,booletag){ResumeVirtualFileResultresult=this.ResumeFile("TestFile.txt","text/plain",fileName?"TestFile.txt":null,etag?EntityTag:null);result.LastModified=_lastModified;returnresult;}
以上示例将为您的数据提供“Content-Disposition:attachment”。 当没有提供fileName时,数据将作为“Content-Disposition:inline”提供。另外,它可以提供ETag和LastModified标头。
[HttpGet("virtual/{fileName}")]publicIActionResultVirtualFile(boolfileName){varresult=newResumeVirtualFileResult("TestFile.txt","text/plain"){FileInlineName="TestFile.txt",LastModified=_lastModified};returnresult;}
基于EntityFrameworkCore和Lucene.NET实现的全文检索搜索引擎:Masuit.LuceneEFCore.SearchEngine
开源博客系统:Masuit.MyBlogs
About
全龄段友好的C#万能工具库,码数吐司库,包含一些常用的操作类,大都是静态类,加密解密,反射操作,权重随机筛选算法,分布式短id,表达式树,linq扩展,文件压缩,多线程下载,硬件信息,字符串扩展方法,日期时间扩展操作,中国农历,大文件拷贝,图像裁剪,验证码,断点续传,集合扩展、Excel导出等常用封装。诸多功能集一身,代码量不到2MB!
Topics
Resources
License
Code of conduct
Contributing
Security policy
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Uh oh!
There was an error while loading.Please reload this page.
