2011年9月13日 星期二

西安事变前中国国内的抗日格局

看待蒋介石的抗日,并不是三言两语能说清楚的。历史千万不能像我们的教科书那样,割裂起来看,那样是很容易被忽悠的。我也说个一二点,时间到西安事变,只分析了国内的部分 事情,且蒋介石1932年之前,都是打仗多,还有民国政府的党内约束造成两次下野,政治啊外交啊之类的事情也做得不多。事实不完整,权且留给大家敲砖。

九一八之前:
1、明治维新之后,日本近代工业开始高速发展。《江华条约》之后,工业化和军国化思想更加盛行,海军等近代军种得以高速发展。(中国开始洋务运动,近代工业开始起步,但到 后期,重心都倾向于轻工业,——估计是慈禧太后小女人心理吧。)

2、1892年《甲午战争》,日军大获全胜。(中国签订马关条约,割地若干,赔款2亿多白银。)

3、1900年,日本组团八国联军,“应邀”剿灭义和团。(1901年,中国签订辛丑条约,赔款八国共4亿多白银。)

4、随后日本在朝鲜、东北,和俄国打仗。(中国也参加了,为日俄和平,贡献了旅顺、大连。)

5、1914年一战爆发,日本参展,属于战胜国;同期占领胶济线。(中国也是战胜国,当时的政府主要是袁世凯,签订了二十一条,所以有了1919年的五四运动。)

6、1918年日本出兵西伯利亚,被伟大的俄国击败,192X年铩羽而归,估计元气大伤,小打小闹不算的话,消停了若干年,一直到1928年皇姑屯事件,张作霖拜拜。(1 921年,武昌起义,建立中华民国。因为清政府被推翻,各地的军阀开始闹独立,1922-1924年两次直奉战争。)——张作霖是被北伐军(1924年)“逼”回去东北的 ,正因为和直系有仇,所以才后少帅的东北易帜,和南京国民政府合作。<1921年,中国共产党成立;1922年,苏联建国,中国共产党加入共产国际,接受俄共领导。192 4年国民党“一全”,国共第一次合作,1927年“八七会议”,“枪杆子里出政权”,共产党发动南昌起义及农民暴动——秋收起义。>(蒋介石围剿,未果。随后下野。)

九一八——西安事变前:

7、1931年,九一八事变。(东北易帜后,蒋奉联合,先后经历了中国1929年两次蒋冯战争,1930年中原大战。——中原大战持续大半年,2挑4。蒋、张估计中原大战 受损严重;同时,40年的战争消耗,工业化、军事力量已经远远落后于当时休养生息完毕的日本;蒋张只好退守山海关,收缩防御——这个结论是我猜的。随后,学生抗议,国民党 内讧,蒋介石下野,至翌年复出。)<1930-1935年,为共产国际代表王明期间。此五年历史很空缺,主要大事有两个:1931年11月,成立中华苏维埃,颁布宪法、发 行货币、设计国旗——王明确定苏维埃和国民政府为的“两国之争”;还有一个就是长征。>

8、1932年,一二八事变。(蒋介石1月28日复出——有临危受命的感觉哈——死命抵抗,落败。)1932年,日本在东北成立伪满,建立战略后方,借助东北资源,以战养 战,大力发展军事工业。——东北重工业基地的底子,是日本人打下的。(1932年,蒋汪合作,共同抗日。)1933年,日本人入关,逼近北京、天津。(1933年,蒋介石 “攘外必先安内”,开始围剿苏维埃政权。汪精卫开始对日和谈,主导《塘沽协定》,至1937年七七事变,中日无大的冲突。)<1934年遵义会议后,至1935年,共产党长征。1935年,一二九运动——又是学生哈——要求“停止内战,一致对外”,随后瓦窑堡会议,确定抗日民族统一战线。>

9、1936年,西安事变。国共二次合作,共同抗日。

2010年10月24日 星期日

什么是四爷

人家都叫我四爷。很奇怪,我为什么叫四爷呢?我家我老大,应该是大爷而不是四爷。我之所以叫四爷,是因为在我的心理,四爷是一个伟大而又平常的人物。他就是我的四爷。我崇拜四爷,所以,别人看我常说四爷,就直接叫我四爷了。

注:

这篇文章是关于关键字四爷的测试文章。特此说明。

 

标签:

2010年8月19日 星期四

Winform开发的利器autoMapper

很多年没有在这儿写技术博客了。有些生疏,朋友们见谅。

引子

估计有不少写.Net的朋友也是和我一样,平时主要以WebForm开发位置,遇到WinForm开发的时候,总会遇到一些本来在WebForm下面很熟练的问题,在WinForm下面却麻烦重重了。

我也刚开始写WinForm,时间不长。希望在这个过程中遇到的一些问题和解决办法,可以一一拿出来和朋友们分享。

场景

有如下一个及其简单的场景:

1、主界面(Main)中有一项需要在另外一个Item编辑窗口(ItemEdit)中编辑;

2、用户可以在窗口中对Item中的一些属性就行修改,保存后回到主窗口,这时主窗口在不刷新数据库的情况下,可以显示用户最新的编辑内容;

3、用户也可能编辑部分内容后放弃了继续编辑,此时主窗口的内容应该保持不变。

非AutoMapper的一些解决办法

为实现上述需求,通常,编辑界面的构造函数中,添加一个参数用于传递待编辑对象即可。如

public ItemEdit(Entity entity){}






上述需求如果在WebForm中很容易实现。因为WebForm的界面之间在不使用浏览器脚本的情况下,是相互独立的,没有通信。但对于WinForm,在实现场景需求3的时候,由于Entity是引用类型,如Entity被绑定到控件,用户一旦编辑后,实体将被同步修改,即便用户取消,在主界面中实体也已经被修改了。



 




一种相对ugly的解决办法是,在ItemEdit中,对象不绑定到控件,而在加载时手动为控件赋值,同时,在用户确定保存的时候,再从控件中依次取值,并依次赋值到Entity中。如




private TextBox tbxName = new TextBox();
private void ItemEdit_Load(object sender, EventArgs e)
{
tbxName.Text = _entity.Name;
}
private Button btvSave = new Button();
private void btnSave_Click(object sender, EventArgs e)
{
_entity.Name = tbxName.Text;
Save(_entity);
}






在使用WinForm的时候,更常用的方式是采用控件绑定的方式。如:




private TextBox tbxName = new TextBox();
private Button btvSave = new Button();

private void ItemEdit_Load(object sender, EventArgs e)
{
tbxName.DataBings.Add("Text",_entity,"Name");
}

private void btnSave_Click(object sender, EventArgs e)
{
Save(_entity);
}








很明显,如果采用第二种方法,_entity的值将是和控件的中绑定的属性同步的。如果要避免这种情况,我们在页面编辑时,需要使用另外一个对象,以避免编辑时的实体与传入的entity存在引用关系。你也可以使用下面的这种方式,——如果在Entity有几十个属性的时候,你也不觉得麻烦的话,——下面的内容你也不需要在遇到了。




Entity _entityForEdit = new Entity();
_entityForEdit.Name = _entity.Name;



AutoMapper的解决办法



在这里,我们采用AutoMapper来觉得这种问题。为了方便,我采用一个简单的测试用例的方式来说明。





using AutoMapper;
using NUnit.Framework;

namespace RQQuery.Client.Test
{
[TestFixture]
public class AutoMapperTest
{
[Test]
public void MainTest()
{
const string name = "Entity From Main.";
var entityForSave = new Entity {Name = name};
var codeForSave = entityForSave.GetHashCode();
var itemEditSaved = new ItemEdit(entityForSave);
itemEditSaved.Edit();
itemEditSaved.Save();
//期望Name值被修改。
Assert.AreEqual("Entity is changed.", entityForSave.Name,"修改不成功");
//期望引用关系不被破坏。
Assert.AreEqual(codeForSave, entityForSave.GetHashCode(), "引用关系丢失");

var entityForCancel = new Entity { Name = name };
var codeForCancel = entityForSave.GetHashCode();
var itemEditCanceled = new ItemEdit(entityForCancel);
itemEditCanceled.Edit();
itemEditCanceled.Cancel();
//期望Name值没有被修改。
Assert.AreEqual(name, entityForCancel.Name,"已被修改");
//期望引用关系不被破坏。
Assert.AreEqual(codeForCancel, entityForSave.GetHashCode(), "引用关系丢失");
}
}

public class Entity
{
public string Name { get; set; }
}

public class ItemEdit
{
private readonly Entity _entity;
private readonly Entity _entityForEdit;

public ItemEdit(Entity entity)
{
_entity = entity;

Mapper.CreateMap<Entity, Entity>();

//使用Mapper.Map<TSource,TDistination>(TEntity entity),获取新的实例。
_entityForEdit = Mapper.Map<Entity, Entity>(_entity);
}

public void Edit()
{
_entityForEdit.Name = "Entity is changed.";
}

public void Save()
{
//使用Mapper.Map<TSource,TDistination>(TEntity entity, TDistination distinationEntity),
//将从entity中取值,并复制给distinationEntity。
Mapper.Map<Entity,Entity>(_entityForEdit, _entity);

//you can save _entity here.
//....
}

public void Cancel()
{
//do nothing.
}
}
}






上述MainTest方法,即模拟主界面的操作过程。代码是最好的注释,其余的就不详细解释了。



在使用AutoMapper的时候,通过Mapper.CreateMap方法,创建实体的映射关系。




Mapper.CreateMap<Entity, Entity>();



我们在这里,将Entity自己映射为Entity。如果不声明这个映射,在使用Mapper.Get的时候,我们也可以获得对象,但AutoMapper将总是创建一个新的实例来完成映射



Mapper.CreateMap第一个参数为源类型,第二个参数为目标类型。在映射时,如果源类型的属性与目标类型中的属性对应,即可完成映射;如果属性不同,可以通过ForMember、Ignore等方法声明对关系进行声明。更多用法的详细说明,可参考文档(我没有找到更详细的,你有的话,可以告诉我。 )。代码是最好的注释,IDE工具智能感知一下,用起来还是比较顺手的。或者google之。



 



----------------------------------------分隔线后面是精华----------------------------------



重点注意



A:在对实体映射赋值时,只带source一个参数的Map方法,AutoMapper将创建新的实例作为返回值。




_entityForEdit = Mapper.Map<Entity, Entity>(_entity);






B:在对实体映射赋值时,使用带Distination的Map方法,AutoMapper将source实体的值映射到destination上,并不创建新的实例。此时也有返回值,与destination相同。在这里,我们将_entityForEdit的值直接赋给_entity,以保证引用关系的不被破坏。(如采用A中的方法,则HashCode测试将不通过。)




Mapper.Map<Entity,Entity>(_entityForEdit, _entity);


--EOF--

2010年8月17日 星期二

关于一个插件,折腾48小时后的叨叨

上周日晚上,因为想在Ankhsvn上面集成一个IssueTracker,到CollabNet上面的那个desktop-vs。没有什么详细的说明,只有一个界面,感觉挺好的,和VSTF差不多。既然是Desktop,应该是单机版的,我也只需要一个这样的就满足要求了,毕竟只是为了任务速记。

好不容易下载下来了,安装时却死活都安装不上。

于是,48小时的杯具就诞生了。

1、先根据错误activity的log信息,以为是VS 9.0下面的devenv在干扰,卸载了Visual Studio 2008。不行。

2、错误信息变成了VS 10.0下面你的Devenv。担心是不是什么组件出错了,但log日志毕竟不如微软官方的那么详细。咬咬牙,把Visual Studio 2010修复了一下。(耗时N久)还是不行。

3、一狠心,重装了Visual Studio 2010。这下总算可以了,desktop-vs可以安装上了,结果发现原来这个是Collabnet的一系列集成方案中的一个插件,还要装一个集成服务才行。可惜,文档(好像没有文档)里面语焉不详,只有下载页面的说明才有这些痕迹。谁又能细想?

那就只好不管了。找到了一个Artifacts,正好可以单机版的。可惜是文件管理的,而且不能和ankhsvn集成。忍忍只好将就了。

因为卸载了Visual Studio 2010,之前安装的很多组件都出现了问题。重装组件时出现了一些重叠的东西,第二天,把常用的插件卸载后重新安装了Visual Studio 2010。但到使用的时候,Visual Studio提示了如下的错误:

---------------------------
Microsoft Visual Studio
---------------------------
The 'Visual Studio Explorers and Designers Package' package did not load correctly.

The problem may have been caused by a configuration change or by the installation of another extension. You can get more information by running the application together with the /log parameter on the command line, and then examining the file 'C:\Users\myname\AppData\Roaming\Microsoft\VisualStudio\10.0\ActivityLog.xml'.

Continue to show this error message?
---------------------------
是(Y)   否(N)  
---------------------------

---------------------------
Microsoft Visual Studio
---------------------------
The 'VSTS for Database Professionals Sql Server Data-tier Application' package did not load correctly.

The problem may have been caused by a configuration change or by the installation of another extension. You can get more information by running the application together with the /log parameter on the command line, and then examining the file 'C:\Users\myname\AppData\Roaming\Microsoft\VisualStudio\10.0\ActivityLog.xml'.

Continue to show this error message?
---------------------------
是(Y)   否(N)  
---------------------------

---------------------------
Microsoft Visual Studio
---------------------------
The 'RadLangSvc.Package, RadLangSvc.VS, Version=10.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91' package did not load correctly.

The problem may have been caused by a configuration change or by the installation of another extension. You can get more information by running the application together with the /log parameter on the command line, and then examining the file 'C:\Users\myname\AppData\Roaming\Microsoft\VisualStudio\10.0\ActivityLog.xml'.

Continue to show this error message?
---------------------------
是(Y)   否(N)  
---------------------------

---------------------------
Microsoft Visual Studio
---------------------------
The 'Language Package' package did not load correctly.

The problem may have been caused by a configuration change or by the installation of another extension. You can get more information by running the application together with the /log parameter on the command line, and then examining the file 'C:\Users\myname\AppData\Roaming\Microsoft\VisualStudio\10.0\ActivityLog.xml'.

Continue to show this error message?
---------------------------
是(Y)   否(N)  
---------------------------

不勾(Google)不知道,勾完才发现,这些问题从2005年开始就有了。 这从另外一个方面说明这是无解的。

再经历一天一夜,24小时后,也就是刚才,我总算确认了,这个是无解的。

唯一欣慰的是,如果使用/SafeMode模式启动,VS是正常的。

安装的插件太多,重装之后,VS又是直接使用之前安装过的插件,这造成我根本就无法判断是哪个插件除了错。

就在刚才反复清理“控制面板->程序”,发现了这个Artifacts。卸载之后再正常启动Devenv,这个世界就清净了。

48小时,走了一圈,回到了原地。还是没有找到被集成到Ankhsvn中的IssueTracker。也许有时间会自己按照desktop-vs的方式,写一个单机版的。大致上能覆盖如下需求就行了:

1、以数据库文件(Sqlite3,etc。)保存。通过Ankhsvn配置issue数据库。

2、通过Ankhsvn增删改查Issue内容。

Enhance:

3、Commit时,可以通过修改相应Issue的状态。

Enhance More:

4、除了独立数据库直接操作外,还可以提供一些Socket供多个用户同时使用,这样可以符合团队开发的要求。

5、也可以提供一些接口,给Subversion调用。

绕来绕去,直接说吧,如果有一款能够Subversion、Trac集成的VS插件,该是个多美妙的事情啊!

2010年8月16日 星期一

试用一下Live Writer的代码插件功能

看一下C# 的效果。

public static void HelloWorld()
{
Console.WriteLine("hello world.");
}





还不错。



再来个SQL




Select Money From Wallet Where Amount > 100;



基本还行吧。



再来个图片呢?



猪八戒



换个行之后看一下效果。换个行之后看一下效果。换个行之后看一下效果。换个行之后看一下效果。换个行之后看一下效果。换个行之后看一下效果。换个行之后看一下效果。



换个行之后看一下效果。换个行之后看一下效果。换个行之后看一下效果。换个行之后看一下效果。换个行之后看一下效果。换个行之后看一下效果。换个行之后看一下效果。



嗯。差不多了。不折腾了。总的说来还行。

2010年8月6日 星期五

诡异的连接,1e100.net

莫名的发现电脑上有很多连接到*.1e100.net的。





域名是不断变化的。根域名没有泛解析,而且试了几个二级域名,发现也并不是每个都能解析。可能是按照一定规律随机生成的,生命周期很短。


找个可以解析的,解析出来居然是google的服务器地址,还显然不都是同一个IP。









IP138查询结果:





想来,google提供了免费的dns服务器,只要用它的dns服务器,就能很快得到最新的IP地址,当google如果不停的产生随机域名的时候,google的服务基本都能正常服务。所以,是google在做什么悄悄的行动,还是有可能的。


那么,谷歌想做的是什么?拯救劳苦大众?

2010年8月5日 星期四

Entity Framework中支持timestamp

Visual Studio 2010中的Entity Framework算是一个亮点之作。最近刚好用到。


在EF中设计模型的时候,发现Type中并没有Timestamp这个类型。当然,EF是支持多数据库的,这种MSSQL特有的类型,没有也很正常。但我从MSSQL中通过导入Table,发现生成的Model中将Timestamp列转换成了Binary,Nullable为False,长度为8,设置了Concurrency Mode为Fixed,StoreGenratedPattern为Computed。而我反向从Model中为Version列设置此类型后,在数据库中生成的列为Binary类型,且新生成对象Insert时,会提示此列为Null不能插入。这等于是说,EF并没有为这列Binary按照StoreGenratedPattern的定义,自动Computed新值。


这也许是一个不大不小的Bug,我在修改Version为其他的类型,且设置Computed时,同样有该错误。


System.Data.SqlClient.SqlException: Cannot insert the value NULL into column 'Version', table 'XXXX.dbo.XXXXSet'; column does not allow nulls. INSERT fails.


寻寻觅觅,并没有找到真正的解决方案。参照AndyPotts,有个不完美的解决方案,就是在生成脚本的模板中,强制写成MSSQL中支持的Timestamp类型。


我参照了上述文章中的做法,约定数据库中使用Version的字段,都设置为TimeStamp。做法如下:


1、设置Version的Property如下



2、创建一个C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\Microsoft\Entity Framework Tools\DBGen\SSDLToSQL10.tt的拷贝到同目录下,并重命名为:MySSDLToSQL10.tt。这样在EF设计器属性中,会及时刷新出现该模板文件(无需重新启动程序)。



修改MySSDLToSQL10.tt。AndyPotts说是第151行,我现在用的版本是在165行。不过你可以直接查找这行需要修改的代码:


[<#=Id(prop.Name)#>] <#=prop.ToStoreType()#> <#=WriteIdentity(prop, targetVersion)#> <#=WriteNullable(prop.Nullable)#><#=(p < entitySet.ElementType.Properties.Count - 1) ? "," : ""#>


然后修改为:


[<#=Id(prop.Name)#>] <#if (string.Compare(prop.Name,"Version",true) == 0) { #>TIMESTAMP<# } else { #><#=prop.ToStoreType()#><# } #> <#=WriteIdentity(prop, targetVersion)#> <#=WriteNullable(prop.Nullable)#><#=(p < entitySet.ElementType.Properties.Count - 1) ? "," : ""#>


代码中的Version,你可以修改为你模型中所约定的属性名称。


通过上述修改后,MSSQL的脚本中,将Version列生成为Timestamp类型。数据库端的自动计算就不用担心了,而在APP里面,由于是Fixed和Computed类型的,也可以完成ADD、Insert、Update时的程序逻辑。


另:我当前使用的Visual Studio 2010 Ultimate版本中,SSDLToMySQL.tt模板有严重的Bug。如果模型中创建了任何关联(Association),生成脚本的时候,有时都会出现错误。似乎是配置文件中的Entity找不到。但有时,又是正常的。原因未知。