Expression构建DataTable to Entity 映射委托
1 namespace Echofool.Utility.Common { 2 using System; 3 using System.Collections.Generic; 4 using System.Data; 5 using System.Linq.Expressions; 6 using System.Reflection; 7 using System.Reflection.Emit; 8 9 public class DataTableUtility { 10 11 public static IEnumerable<T> Get<T>(DataTable table) where T : new() { 12 if (table == null) { 13 yield break; 14 } 15 if (table.Rows.Count == 0) { 16 yield break; 17 } 18 foreach (DataRow row in table.Rows) { 19 yield return Get<T>(row); 20 } 21 } 22 23 public static T Get<T>(DataRow row) where T : new() { 24 return GenericCache<T>.Factory(row); 25 } 26 27 public class GenericCache<T> where T : new() { 28 static GenericCache() { 29 //Factory = GetFactoryIL(); 这里写错了 Factory = GetFactory(); 30 } 31 public static readonly Func<DataRow, T> Factory; 32 33 private static Func<DataRow, T> GetFactory() { 34 var type = typeof(T); 35 var rowType = typeof(DataRow); 36 var rowDeclare = Expression.Parameter(rowType, "row"); 37 var instanceDeclare = Expression.Parameter(type, "instance"); 38 var newExpression = Expression.New(type); 39 var instanceExpression = Expression.Assign(instanceDeclare, newExpression); 40 var nullEqualExpression = Expression.Equal(rowDeclare, Expression.Constant(null)); 41 var containsMethod = typeof(DataColumnCollection).GetMethod("Contains"); 42 var indexerMethod = rowType.GetMethod("get_Item", BindingFlags.Instance | BindingFlags.Public, null, 43 new[] { typeof(string) }, 44 new[] { new ParameterModifier(1) }); 45 var setExpressions = new List<Expression>(); 46 var properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public); 47 var columns = Expression.Property(Expression.Property(rowDeclare, "Table"), "Columns"); 48 foreach (var propertyInfo in properties) { 49 if (propertyInfo.CanWrite) { 50 var propertyName = Expression.Constant(propertyInfo.Name, typeof(string)); 51 var checkIfContainsColumn = 52 Expression.Call(columns, containsMethod, propertyName); 53 var propertyExpression = Expression.Property(instanceDeclare, propertyInfo); 54 var value = Expression.Call(rowDeclare, indexerMethod, propertyName); 55 var proertyAssign = Expression.Assign(propertyExpression, Expression.Convert(value, propertyInfo.PropertyType)); 56 setExpressions.Add(Expression.IfThen(checkIfContainsColumn, proertyAssign)); 57 } 58 } 59 var checkIfRowIsNull = Expression.IfThenElse(nullEqualExpression, Expression.Empty(), Expression.Block(setExpressions)); 60 var body = Expression.Block(new[] { instanceDeclare }, newExpression, instanceExpression, checkIfRowIsNull, instanceDeclare); 61 return Expression.Lambda<Func<DataRow, T>>(body, rowDeclare).Compile(); 62 } 63 } 64 65 public static T GetByReflection<T>(DataRow dr) where T : new() { 66 var t = new T(); 67 if (dr != null) { 68 foreach (var p in typeof(T).GetProperties()) { 69 if (!dr.Table.Columns.Contains(p.Name)) { 70 continue; 71 } 72 var obj = dr[p.Name]; 73 var set = p.GetSetMethod(); 74 if (set == null) { 75 continue; 76 } 77 p.SetValue(t, obj, null); 78 } 79 } 80 return t; 81 } 82 } 83 }
通过Expression动态构建DataTable映射到实体类,在三层架构中,如果使用的数据层是使用Ado.Net技术,那么加上这个DataTable to Entity的工具类,将为你减少很多代码量。
主要目的是解决DataTable到Entity的映射关系。
1 public class MyClass { 2 public MyClass() { } 3 4 public MyClass(DataRow row) { 5 if (row != null) { 6 if (row.Table.Columns.Contains("Name")) { 7 this.Name = (string)row["Name"]; 8 } 9 if (row.Table.Columns.Contains("Age")) { 10 this.Age = (int)row["Age"]; 11 } 12 } 13 } 14 15 public string Name { get; set; } 16 public int Age { get; set; } 17 18 }
如上定义的实体类MyClass,有一个string类型的Name属性和一个int类型的Age属性。
如果自定义构造函数是可以很方便的从DataRow对象中获取数据填充实体类,但如果涉及的实体类太多,而且如果想通过定义特性标记 来实现一些字段特殊处理,构造函数的方式,需要你写太多的代码,而且很多都是重复的逻辑。
现在使用DataTableUtility.Get<MyClass>.Get(row);就能很方便的获取一个实体类。
现在使用DataTableUtility.Get<MyClass>.Get(table);就能很方便的获取一个实体类集合。
sqlserver 数据库里面金额类型为什么不建议用float,实例告诉你为什么不能。
项目当中如果设计到金额类型的数据,你是否有考虑过为什么不能用float类型。
这里举个例子:
1
2
3
4
5
6
7
8
9
10
|
DECLARE @price1 FLOAT ;
SET @price1 = 1;
SET @price1 = ( @price1 * 7.1 ) / 7 - @price1 * 0.1
SELECT @price1;
DECLARE @price2 DECIMAL ;
SET @price2 = 1;
SET @price2 = ( @price2 * 7.1 ) / 7 - @price2 * 0.1
SELECT @price2;
|
执行看看结果如何:
0.914285714285714
1
这里做个记录,开发中遇到的小问题。
sql server 多行数据合并成一列
首先是源数据:
select (CONVERT(varchar(100),cip.CheckIn_StartTime, 23)+' - '+CONVERT(varchar(100),cip.CheckIn_EndTime, 23)+' '+CONVERT(varchar(100),cip.Rental_Price)) as content from CheckInPeriod cip
然后我们加上合并语句:
select Stuff((select ',' +Convert(varchar(255),content) from ( select (CONVERT(varchar(100),cip.CheckIn_StartTime, 23)+' - '+CONVERT(varchar(100),cip.CheckIn_EndTime, 23)+' '+CONVERT(varchar(100),cip.Rental_Price)) as content from CheckInPeriod cip ) tba for XML path('')),1,1,'') as content
结果就是这样的:
可以自定义各种符号。
C# 字符串大写转小写,小写转大写,数字保留,其他除外
又是一道面试题,我只想到两种方式:
第一种:循环字符串,判断每个字符串的类型,再根据类型对该字符进行操作(转大写、转小写、不变或舍弃)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
static void Main( string [] args)
{ //大写转小写,小写转大写,数字保留,其他除外
string str = "Aa Bb 123!@#" ; //测试字符串
string newStr = string .Empty; //用于存放新字符串
//循环字符串
foreach ( char item in str)
{
if (item >= 'a' && item <= 'z' )
{
//小写字母转大写
newStr += item.ToString().ToUpper();
}
else if (item >= 'A' && item <= 'Z' )
{
//大写字母转小写
newStr += item.ToString().ToLower();
}
else if (item >= '0' && item <= '9' )
{
//数字不变
newStr += item.ToString();
}
}
//打印
System.Console.WriteLine(newStr);
System.Console.ReadLine();
} |
第二种:将字符串转为byte[],循环byte[],使用ASCII码进行判断
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
static void Main( string [] args)
{ //大写转小写,小写转大写,数字保留,其他除外
string str = "Aa Bb 123!@#" ; //测试字符串
string newStr = string .Empty; //用于存放新字符串
//字符串-->byte[]
ASCIIEncoding ascii = new ASCIIEncoding();
byte [] bytes = ascii.GetBytes(str);
//循环byte[]
foreach ( byte item in bytes)
{
//临时存放
byte [] temp = new byte [] { item };
if (item >= 97 && item <= 122)
{
//小写字母转大写
newStr += ascii.GetString(temp).ToUpper();
}
else if (item >= 65 && item <= 90)
{
//大写字母转小写
newStr += ascii.GetString(temp).ToLower();
}
else if (item >= 48 && item <= 57)
{
//数字不变
newStr += ascii.GetString(temp);
}
}
//打印
System.Console.WriteLine(newStr);
System.Console.ReadLine();
} |
备注:数字,字母的ASCII码对照表
1
2
3
4
5
|
/* 0~9数字对应十进制48-57 a~z字母对应的十进制97-122十六进制61-7A A~Z字母对应的十进制65-90十六进制41-5A */ |
结果打印:
从0开始用U盘制作启动盘装Windows10系统(联想R720笔记本)并永久激活方法
一,制作U盘启动盘
随着个人电脑的“飞入寻常百姓家”,喜欢DIY电脑的发烧友们也越来越多。
安装系统是DIY最基本的要求,很容易做到;
那么如果要求用U盘装系统呢,你可能会说简单,直接下载个老毛桃或是大白菜一类的软件一键就搞定了;
那么如果要求用系统自带的命令行工具制作U盘启动安装盘呢?
工具/原料:
U盘一个(4G可能不够用,最好8G)
系统iso镜像一个(这里用Win10企业版)
方法/步骤:
1,把要制作成U盘启动安装盘的U盘,插入到电脑的USB接口中,确保资源管理器已经正确识别U盘。下图中是小编的8G的U盘,实际有效容量是7.60G。
2,右键左下角开始按钮,选择“命令提示符(管理员)”。
3,在命令行中输入“diskpart”(不包括双引号,下同)后按回车键,此命令是Windows系统自带的硬盘分区工具。
4,在命令行中输入“list disk”后按回车键,此命令用于显示电脑上所有的硬盘(注意,diskpart会把U盘也看成硬盘),从“大小”一栏中一下就能看到U盘被看做了“磁盘 1”,这一步非常重要,因为后面会格式化,所以一定要仔细确定哪个是U盘并记住U盘的编号。
5,在命令行中输入“select disk 1”后按回车键,此命令用于选择接下来要操作的磁盘,这里的“1”就是小编的U盘编号(从上一步所得)。
6,在命令行中输入“clean”后按回车键,此命令用于清除U盘上的所有数据,所以在执行此步骤之前,如果U盘中有重要数据,务必备份,否则会被清除无法恢复。
7,在命令行中输入“create part pri”后按回车键,此命令是“create partition primary”的简写形式,作用是在U盘上创建主分区。
8,在命令行中输入“select part 1”后按回车键,此命令是“select partition 1”的简写形式,作用是选择分区1,也就是上一步创建的主分区。
9,在命令行中输入“format fs=fat32 quick”后按回车键,此命令用于快速格式化主分区为fat32文件系统格式。
10,在命令行中输入“active”后按回车键,此命令用于把当前分区标志为“活动”。
11,在命令行中输入“exit”后按回车键,此命令用于退出diskpart分区工具。
整个过程截图如下:
OK了,现在U盘已经变成可启动U盘了。你只需要把下载好的Win10系统的iso文件解压到U盘中即可。是的,就是解压iso文件,任何解压软件都可以,关键是解压到U盘的根目录中。
接下来就是设置从U盘启动了,启动之后就自动开始安装Win10系统,过程和使用光盘一致。祝你DIY愉快!
注意事项:纵观整个过程,最重要的就是创建一个活动主分区。
参考链接:https://jingyan.baidu.com/article/8cdccae9577e0e315413cd87.html
二,下载 cn_windows_10_enterprise_2015_ltsb_x64_dvd_6848425.iso
可以去windows 官网下载Windows 10,然而我是在这里下载的 https://msdn.itellyou.cn/ ,打开页面,左侧菜单找到“操作系统”,点击展开“Windows 10”,右边栏选择“中文-简体”,找到“Windows 10 Enterprise 2015 LTSB (x64) - DVD (Chinese-Simplified)”点击详细信息。
直接用迅雷或者其他下载工具下载:
ed2k://|file|cn_windows_10_enterprise_2015_ltsb_x64_dvd_6848425.iso|3907538944|38E47AB92B6D97DF2BE602BBC9969D34|/
下载到本地是 cn_windows_10_enterprise_x64_dvd_6846957.iso 就是简体中文的Windows 10 企业版压缩包。
解压缩,将里面的文件全部拷贝到前面制作好的U盘根目录下。
三,下载Intel Raid模式驱动(固态硬盘驱动) 如果电脑没有装固态硬盘则跳过此步骤
因为我的笔记本是 “512G固态硬盘+1T普通硬盘” ,针对固态硬盘需要Intel Raid模式驱动。
最近使用联想R720笔记本用户反应在重装系统的时候无法识别硬盘的现象,是怎么回事呢?出现这样的问题是由于R720出厂系统的BIOS内,SATA Controller Mode默认设置的是为Intel RST Premium模式,该模式会将硬盘组成磁盘阵列的模式(Raid模式),而原版的Window 10安装镜像默认没有Raid模式的驱动导致的,当然我们可以按下面方法进行修复。
解决方法:
下载Intel Raid模式驱动,将驱动安装包解压缩后将整个文件夹完整的放到到系统安装U盘的根目录下,然后在安装系统选择硬盘时,加载此驱动。(该驱动分为32位和64位,分别对应32位系统和64位系统吗,下载地址:http://pan.baidu.com/s/1o8QghFs)。
下载后是 f6flpy.rar ,解压缩后包含两个 f6flpy-x64,f6flpy-x86,根据你要装系统的电脑选择64位(f6flpy-x64),或者32位(f6flpy-x86),拷贝到上一步制作U盘的根目录下。
四,从U盘启动,装Windows 10 企业版系统
1,将要装系统的电脑C盘(包含桌面)上的个人文件及数据备份到其他盘。然后关机。插入U盘(前面制作好启动分区的U盘,里面包含系统全部安装文件)。
2,开机,然后连续按开机设置键(联想是F12),进入启动菜单(Boot Menu),找到USB启动项。按回车,重启及进入U盘开始安装系统。
3,到了选择“您想将Windows安装在哪里?”的时候要小心了。看准主分区(原C盘),其它磁盘分区不要动,一面数据丢失。
因为我的C盘是在固态硬盘中,所以到这里是看不见的。于是就用到了上面第三步中提到的Intel Raid模式驱动。点击“加载驱动程序”,然后“浏览”,找到存放Raid驱动的文件夹,默认文件名为“f6flpy-x86”或“f6flpy-x64”,选择该文件,然后确定。
耐心等待检测到Raid模式驱动程序,点击下一步后,出现读取条开始加载此驱动。(如果提示报错建议重新加载该驱动多试几次,并且驱动文件存放的路径最好为全英文路径)。
在加载成功后会跳回之前选择硬盘的界面,此时已经可以正常显示出机器内的固态硬盘,开始正常安装即可!
好了,后面就是按照步骤操作就行了,没啥可说的了。祝你一切顺利!
五,检查更新系统驱动
重装系统后,进入新系统桌面。去官网(我用的联想笔记本,地址是 http://support.lenovo.com.cn/lenovo/wsi/Modules/NewDrive.aspx )点击“立即安装驱动”下载联想驱动管家。或者驱动精灵等。安装好后检查更新一遍驱动就好了。
六,Win10企业版永久激活
win10企业版永久激活方法?win10企业版是针对企业用户推出的版本,随着win10系统的不断完善,现在越来越多的人选择升级win10,升级完系统就需要激活它。那么今天就为大家分享一下怎么永久激活win10企业版。
1、右键点击桌面左下角"windows"图标,点击打开“命令提示符”。
2、复制命令:slmgr.vbs /upk,按回车确定,弹出窗口显示“成功地卸载了产品密钥”。
3、复制命令:slmgr /ipk NPPR9-FWDCX-D2C8J-H872K-2YT43,按回车确定,弹出窗口显示“成功的安装了产品密钥NPPR9-FWDCX-D2C8J-H872K-2YT43”。
4、复制命令:slmgr /skms zh.us.to,按回车确定,弹出窗口显示“密钥管理服务计算机名成功的设置为zh.us.to”。
5、复制命令:slmgr /ato,按回车确定,弹出框口提示“成功激活产品”。
以上就是如何使用win10激活密钥永久激活win10企业版的方法。
参考链接:http://www.xitongzhijia.net/xtjc/20180125/118672.html
—— 致敬周末两天装系统踩过的坑……
纯CSS打造淘宝导航菜单栏
店铺装修-PC端-基础页-首页-装修页面:编辑“菜单”模块-显示设置,粘贴如下CSS:
/* 导航条背景色*/ .skin-box-bd .menu-list{background: none repeat scroll 0 0 #3F7FCE;} /*首页/店铺动态背景色*/ .skin-box-bd .menu-list .link{ background: none repeat scroll 0 0 #3F7FCE; color: #C2D5ED; font-family: 微软雅黑,黑体; font-weight: bold; font-size: small;} /*首页/店铺动态右边线*/ .skin-box-bd .menu-list .menu{ border-width: 0 1px 0 0; border-color: #3871B7; border-style: solid; background: #3F7FCE; font-size: 14px;} .skin-box-bd .menu-list .menu-hover .link{background: none repeat scroll 0 0 #3487ed;} /*首页/店铺动态文字颜色*/ .skin-box-bd .menu-list .menu .link .title{color:#fff} .skin-box-bd .menu-list .menu-selected .link .title{background: none repeat scroll 0 0 #3F7FCE;} .skin-box-bd .menu-list .menu-hover .link .title{background: none repeat scroll 0 0 #3487ed;} /*下拉菜单图标*/ .skin-box-bd .menu-list .menu .link .popup-icon{ height: 12px; width: 12px; background: url(//gdp.alicdn.com/tps/i1/T18WsRFcpdXXXPXsT8-51-381.gif) -14px -179px no-repeat; } .skin-box-bd .menu-list .menu-hover .link .popup-icon{ height: 12px; width: 12px; background: url(//gdp.alicdn.com/tps/i1/T18WsRFcpdXXXPXsT8-51-381.gif) -14px -199px no-repeat; } /*二级菜单*/ .menu-popup-cats .sub-cat{background: none repeat scroll 0 0 #2c5990;} .menu-popup-cats .sub-cat-hover{background: none repeat scroll 0 0 #3487ed;color: #FFF;} .menu-popup-cats li.sub-cat-hover::before{content: '%3e';} /*所有分类背景色*/ .skin-box-bd .all-cats .link{background: none repeat scroll 0 0 #ff4400;padding: 0 15px;} /*所有分类文字颜色*/ .skin-box-bd .all-cats .title{ color: #f5f5f5; font-family: 微软雅黑,黑体; font-weight: bold; font-size: small; } /*所有分类-下拉菜单图标*/ .skin-box-bd .all-cats .link .popup-icon { height: 12px; width: 12px; background: url(//gdp.alicdn.com/tps/i1/T18WsRFcpdXXXPXsT8-51-381.gif) 0 -220px no-repeat; } .skin-box-bd .all-cats-hover .link .popup-icon { height: 12px; width: 12px; background: url(//gdp.alicdn.com/tps/i1/T18WsRFcpdXXXPXsT8-51-381.gif) 0 -240px no-repeat; } /*所有分类-二级菜单*/ .skin-box-bd .popup-content .cats-tree .fst-cat{background: none repeat scroll 0 0 #2c5990;} .skin-box-bd .popup-content .cats-tree .cat-hd-hover{background: none repeat scroll 0 0 #3487ed;color: #FFF;} /*所有分类-三级菜单*/ .skin-box-bd .popup-content .cats-tree .fst-cat .snd-pop .snd-cat-hd a{ background: none repeat scroll 0 0 #2c5990;color: #C2D5ED; } .skin-box-bd .popup-content .cats-tree .fst-cat .snd-pop .snd-cat-hd-hover a{background: none repeat scroll 0 0 #3487ed;color: #FFF;}
自定义导航示例:https://hotshop.bbs.taobao.com/detail.html?postId=7000589
进入CSS导航在线生成工具页面(http://taobaokaidian.com/tool/dhcss/ 如果不能点击打开,请复制网址到时浏览器中打开),
想了解更多样式,可以来这里学习css : http://www.w3cschool.cn/css_intro.html
C# Winform开发以及控件开发的需要注意的,被人问怕了,都是基础常识
我是搞控件开发的,经常被人问,所以把一些问题记录了下来!如果有人再问,直接把地址丢给他看。
一、 经常会有人抱怨Winform界面闪烁,下面有几个方法可以尽可能的避免出现闪烁
1.控件的使用尽量以纯色为主,尽量不使用背景图,或者把大图改成小图,或者图片不缩放绘制,或者直接用不透明的纯色背景色(Winform控件透明是伪透明,是通过截取父容器背景来实现的,所以效率比较低,而且有时候会有延迟。而且多个透明控件叠加的时候不能分层显示出各个控件的透明效果)
2.自定义控件中使用双缓冲。
3.窗体边框最好不要设置为None,保留窗体最大化最小化动画,可以避免最小化恢复时候的界面闪烁。可能会有人说我的窗体是自定义美化的,边框为None了。其实可以通过拦截消息重绘非客户区,实现边框不为None的时候重绘整个窗体的。 网上也有很多教程
二、自定义控件时候需要注意的
1.控件重绘的时候尽可能的处理e.ClipRectangle,减少不必要的绘图操作,标准重绘都应该在Paint事件里处理,用事件里的e.Graphics。
而不是在随便个地方就用CreateGraphics()来绘制,需要刷新的时候调用 Invalidate() 如果能计算重绘区域最好
2.使用双缓冲,在构造函数里加入这两行代码 减少闪烁
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
或者
DoubleBuffered = true;
3.如果你开发dll组件给别人用,记得项目属性里,生成,选择 XML文档文件,生成///<summary> 代码注释。到时候把dll给别人用的时候也把Xml带上,放到和dll同一个目录,这样别人开发的时候就有注释提示了
三、其他开发问题
1.多线程操作控件请使用控件的Invoke或者BeginInvoke调用
不要总想着其他线程中直接操作控件,会出现很多奇葩问题的。
Control.CheckForIllegalCrossThreadCalls 这个属性就是掩耳盗铃,就和 SetProcessWorkingSetSize(将内存强制压到虚拟内存里,给硬盘增加压力) 用来释放内存一样。当初不知道谁传出来的,误导一群人!
正常的多线程操作控件是
this.Invoke(new MethodInvoker(() => {
//UI操作代码
}));
或者用 async 语法 异步编程
不过还有人用很古老的写法,定义委托,判断 InvokeRequired在调用Invoke,虽然也可以,但是浪费时间。
还有 Application.DoEvents(); 也是个远古代码,能不用就不要用
使用线程的时候记得设置线程的 IsBackground=true; 程序关闭之后,线程能自动退出
2. 颜色System.Drawing.Color 这个结构体 是可以支持设置透明度的。可以3个或者4个值,Color.FromArgb(),4个值的时候是 Alpha,Red,Green,Blue. 第一个就是透明度的参数 0-255
3.如果你想把窗体最大化的时候全屏,遮住任务栏,请把窗体边框设置为None
4.控件布局的时候活用Dock和Anchor,这两个属性是互斥的
5.单行的TextBox的高度受字体影响,不能单独改。如果想美化边框效果,请把TextBox的边框隐藏了,放到Panel里,Panel在加个边框背景美化。
6.Label换行只要有\r\n就会换行的,如果要自动换行,先把AutoSize改成false,设置好宽度。字符超过宽度就会换行的。
7.System.Windows.Forms.Timer 这个是执行在主线程的,本质是控件消息循环里的一个定时消息,不要用来做耗时的操作。耗时操作请用 System.Threading.Timer和 System.Timers.Timer
8.Winform 对DPI支持的不完善,虽然.NET Framework 4.6 中有EnableWindowsFormsHighDpiAutoResizing。但是你必须所有控件用原生控件。
如果你用的不是.Net.4.6 而且使用了第三方控件,为了不影响布局,建议把里面的字体单位都改成像素,容器控件包括窗体的AutoScaleMode属性改成None。这样至少界面布局基本正常,高DPI里只是模糊了些
9.使用非托管资源最好显式调用Dispose释放资源,比如图片,文件读取等等。
this.BackgroundImage = global::WinFormsTest.Properties.Resources.bt;
Properties.Resources这个对象的图片属性,每次访问会创建一个图片副本,如果多个控件使用同一张图片,建议手动写代码设置,先设置到一个静态字段里,再引用这个图片字段。
10. try 不要乱用,能解决问题的能不加try的就不要加try,太多try容易导致异常不好定位。一般对于不确定是否异常的才需要加try,比如文件读取,网络连接等等,另外一种是一般开发底层框架的可以确定异常类型,可以配合throw new Exception,用来提示开发者调用出错的信息。另外异常可以全局捕获在 Application.Run加try和ThreadException事件记录日志。
之前看到有些人写一大堆try,程序运行靠try维持,简单的错误没有判断过滤掉,靠try来忽略。导致整个程序卡的一比!
四、一些VS快捷键
1.代码+Tab+tab VS代码快速生成补全,比如 if 再按两下Tab就可以生成if(){}。 mb + Tab+tab= MessageBox.Show("Test"); try、switch、事件绑定+=等等。很多代码都可以用这种方式快速生成。
2. F12 转定义,Ctrl+R+R 重命名, Ctrl + F 除了查找之外,还可以做正则表达式的简单验证,因为匹配结果可以染色。
其他问题自己先去百度吧!
最后问一下:Winform还有多少人用,很多人都转WPF了吧?另外.net的跨平台UI有没有意义?