访问博客,发现杀毒软件弹出病毒警告,直觉告诉我,站点可能被挂马了。果不其然,FTP登录到服务器一看,很多.htm和.js文件都被改了,而且被改的文件还很多,里面都插入了指向恶意站点的链接。感觉像是用程序遍历的,包括每个子目录里面的文件都无一幸免。索性把站点搞了一次大清理,该删的文件删了,该备份的地方备份了。不排除是站点的程序有漏洞,或者是虚拟主机被感染病毒的可能。在此强烈BS一下挂马之人,我将用我余生中的小部分时间,和这种无耻的挂马行为对抗到底!
Visual Studio IDE配色方案
对于咱们代码民工来说,每天都要面对电脑,而平时眼睛盯得最多的,莫过于Visual Studio集成开发环境了。而Visual Studio的默认背景色颜色是白色的,久而久之,眼睛最容易疲劳。所以,一个好的配色方案,能减少屏幕对眼睛的刺激,也能减缓疲劳。经过长久的收集和摸索,老衲收藏了几种十分不错的配色方案,颜色都很柔和,不刺激眼睛,相当的绿色和环保。下面一一和大家分享一下:
所有的配色方案,都采用的是微软的Consolas字体,这可是微软官方推荐的编程御用字体哦~!效果怎样大家可以自己看了,反正我一直用它。
第一种配色方案(BlueTheme)浅绿色,也是老衲最喜欢的一种颜色。基本上字体颜色都没怎么变,只是改了背景色,色彩柔和。
第二种配色方案(YellowTheme)浅黄,也没改字体颜色,只是该了背景,浅黄,颜色不刺眼
第三种配色方案(GrayTheme)浅灰色
第四种配色方案(DarkTheme)黑色主题,这是一个国外哥们推荐的,很黑很酷
所有的配色方案,我都打包上传了,也就是Visual Studio IDE的配置文件,通过Tools->Import and Export Settings可以方便的导入和导出配置,用以切换主题。
大家还有什么好的配色方案,欢迎分享~
HTC Touch Pro 的重力感应功能
HTC Touch Pro带的重力感应功能很实用,不过一直在寻思能否找到重力感应器的SDK。在网上搜罗了一大圈,都没结果,看来厂商并不希望公开这样的接口。果不其然,在一个国外的网站上,发现了一篇有趣的文章:
http://scottandmichelle.net/scott/comments.html?entry=784
I spent a couple of sleepless hours last night writing a little Sensor Test for my new HTC Diamond. It’s a small app that lets you move a circle around the screen by tilting the device.
Exciting, eh? Well, the fun is in getting it to work. I asked HTC if they provide a development kit (SDK) for the tilt sensor, and they said “No”, so I had to figure it out myself by digging around (and trying to remember what I knew of ARM assembly). I’m just happy I managed to figure it out, and so others can write interesting games with it, I’m giving the source code to what I figured out away. Have fun, create something with it.
相当搞笑,这位哥们本来打算要求HTC提供这样的SDK开发包,想不到被HTC无情的拒绝了,于是一怒之下,把重力感应相关的库文件给反向工程了,并公开了源码。这下可好了,咱们可以开动大脑,设计更多的和重力相关的有趣的应用了。研究了这位外国哥们的代码,重力感应器相关的API,主要包含在一个叫做”HTCSensorSDK.dll”的动态库里面,该动态库主要输出的两个函数分别是:HTCSensorOpen和HTCSensorClose ,用于打开重力感应器和关闭重力感应器。当重力感应器打开之后,可以对手机当前位置的变化进行监视,其实是通过检测注册表的某个键值实现的,具体的路径在Software\HTC\HTCSensor\GSensor的EventChanged。在打开重力感应器的情况下,当这个键的值发生变化,意味着手机的位置已经发生了变动。手机位置的定义包括六种情况,以地平线位置作为参考,可分为:手机正面(屏幕)向上、手机正面(屏幕)向下、手机正面(屏幕)向左、手机正面(屏幕)向右、手机正面(屏幕)向前、手机正面(屏幕)向后。而这六种位置在注册表键EventChanged中均有不同的值表示。
为了方便应用,我将开启/关闭 重力感应器的代码抽取了出来,做成一个动态连接库,暴露的接口如下:
<span class="lnum"> 1: </span><span class="kwrd">extern</span> <span class="str">"C"</span> __declspec(dllexport) BOOL EnableGSensor();
<span class="lnum"> 2: </span><span class="kwrd">extern</span> <span class="str">"C"</span> __declspec(dllexport) BOOL DisableGSensor();
这样就能方便的开启和关闭重力感应器了。
下面就可以用简单的MFC Dialog程序来测试重力感应了:
定义注册表路径和被监视的键值
<span class="lnum"> 1: </span><span class="preproc">#define</span> SN_GSENSOR_ROOT HKEY_LOCAL_MACHINE
<span class="lnum"> 2: </span><span class="preproc">#define</span> SN_GSENSOR_PATH _T(<span class="str">"Software\\HTC\\HTCSensor\\GSensor"</span>)
<span class="lnum"> 3: </span><span class="preproc">#define</span> SN_GSENSOR_VALUE _T(<span class="str">"EventChanged"</span>)
定义注册表值掩码,以及6个不同位置的值
<span class="lnum"> 1: </span><span class="preproc">#define</span> SN_GSENSOR_BITMASK 0xF
<span class="lnum"> 2: </span>
<span class="lnum"> 3: </span><span class="preproc">#define</span> orIENTATION_LANDSCAPE 0
<span class="lnum"> 4: </span><span class="preproc">#define</span> orIENTATION_REVERSE_LANDSCAPE 1
<span class="lnum"> 5: </span><span class="preproc">#define</span> orIENTATION_PORTRAIT 2
<span class="lnum"> 6: </span><span class="preproc">#define</span> orIENTATION_UPSIDE_DOWN 3
<span class="lnum"> 7: </span><span class="preproc">#define</span> orIENTATION_FACE_DOWN 4
<span class="lnum"> 8: </span><span class="preproc">#define</span> orIENTATION_FACE_UP 5
定义注册表值变化的Windows Message类型
<span class="lnum"> 1: </span><span class="preproc">#define</span> WM_EVENTCHANGED (WM_USER + 1)
在消息映射宏中,定义响应自定义消息WM_EVENTCHANGED的处理函数
<span class="lnum"> 1: </span>ON_MESSAGE(WM_EVENTCHANGED,OnEventChanged)
这样,我们就可以在Dialog程序的初始化函数里面实现相应的代码:
<span class="lnum"> 1: </span>BOOL CTestDlg::OnInitDialog()
<span class="lnum"> 2: </span>{
<span class="lnum"> 3: </span> CDialog::OnInitDialog();
<span class="lnum"> 4: </span>
<span class="lnum"> 5: </span> <span class="rem">// Set the icon for this dialog. The framework does this automatically</span>
<span class="lnum"> 6: </span> <span class="rem">// when the application's main window is not a dialog</span>
<span class="lnum"> 7: </span> SetIcon(m_hIcon, TRUE); <span class="rem">// Set big icon</span>
<span class="lnum"> 8: </span> SetIcon(m_hIcon, FALSE); <span class="rem">// Set small icon</span>
<span class="lnum"> 9: </span>
<span class="lnum"> 10: </span> <span class="rem">// TODO: Add extra initialization here</span>
<span class="lnum"> 11: </span> g_hSensorEvent = NULL;
<span class="lnum"> 12: </span>
<span class="lnum"> 13: </span> RegistryNotifyWindow(
<span class="lnum"> 14: </span> SN_GSENSOR_ROOT,
<span class="lnum"> 15: </span> SN_GSENSOR_PATH,
<span class="lnum"> 16: </span> SN_GSENSOR_VALUE,
<span class="lnum"> 17: </span> GetSafeHwnd(),
<span class="lnum"> 18: </span> WM_EVENTCHANGED,
<span class="lnum"> 19: </span> SN_GSENSOR,
<span class="lnum"> 20: </span> NULL,
<span class="lnum"> 21: </span> &g;_hSensorEvent);
<span class="lnum"> 22: </span>
<span class="lnum"> 23: </span> gSensorWrapper.EnableGSensor();
<span class="lnum"> 24: </span>
<span class="lnum"> 25: </span> <span class="kwrd">return</span> TRUE; <span class="rem">// return TRUE unless you set the focus to a control</span>
<span class="lnum"> 26: </span>}
RegistryNotifyWindow函数,通过监视注册表的指定路径下,指定键值的变化,向我们的窗口发送WM_EVENTCHANGED消息,而我们在消息映射宏中所定义的OnEventChanged函数,就用来响应和处理这样的自定义消息。
最后,在我们的OnEventChanged函数中,就可以获得当前手机的位置了:
<span class="lnum"> 1: </span>afx_msg LRESULT CHangupPhoneDlg::OnEventChanged(WPARAM wParam, LPARAM lParam)
<span class="lnum"> 2: </span>{
<span class="lnum"> 3: </span> nLastEvent = (wParam & SN_GSENSOR_BITMASK);
<span class="lnum"> 4: </span>
<span class="lnum"> 5: </span> <span class="kwrd">switch</span> (nLastEvent)
<span class="lnum"> 6: </span> {
<span class="lnum"> 7: </span> <span class="kwrd">case</span> orIENTATION_LANDSCAPE:
<span class="lnum"> 8: </span> szMessage = _T(<span class="str">"Last Event: 正面向右"</span>);
<span class="lnum"> 9: </span> <span class="kwrd">break</span>;
<span class="lnum"> 10: </span> <span class="kwrd">case</span> orIENTATION_REVERSE_LANDSCAPE:
<span class="lnum"> 11: </span> szMessage = _T(<span class="str">"Last Event: 正面向左"</span>);
<span class="lnum"> 12: </span> <span class="kwrd">break</span>;
<span class="lnum"> 13: </span> <span class="kwrd">case</span> orIENTATION_PORTRAIT:
<span class="lnum"> 14: </span> szMessage = _T(<span class="str">"Last Event: 正面向后"</span>);
<span class="lnum"> 15: </span> <span class="kwrd">break</span>;
<span class="lnum"> 16: </span> <span class="kwrd">case</span> orIENTATION_UPSIDE_DOWN:
<span class="lnum"> 17: </span> szMessage = _T(<span class="str">"Last Event: 正面向前"</span>);
<span class="lnum"> 18: </span> <span class="kwrd">break</span>;
<span class="lnum"> 19: </span> <span class="kwrd">case</span> orIENTATION_FACE_DOWN:
<span class="lnum"> 20: </span> szMessage = _T(<span class="str">"Last Event: 正面向下"</span>);
<span class="lnum"> 21: </span> <span class="kwrd">break</span>;
<span class="lnum"> 22: </span> <span class="kwrd">case</span> orIENTATION_FACE_UP:
<span class="lnum"> 23: </span> szMessage = _T(<span class="str">"Last Event: 正面向上"</span>);
<span class="lnum"> 24: </span> <span class="kwrd">break</span>;
<span class="lnum"> 25: </span> <span class="kwrd">default</span>:
<span class="lnum"> 26: </span> szMessage = _T(<span class="str">"Last Event: Unknown"</span>);
<span class="lnum"> 27: </span> <span class="kwrd">break</span>;
<span class="lnum"> 28: </span> }
<span class="lnum"> 29: </span>
<span class="lnum"> 30: </span> <span class="kwrd">this</span>->GetDlgItem(IDC_DISPLAY)->SetWindowTextW(szMessage);
<span class="lnum"> 31: </span>
<span class="lnum"> 32: </span>
<span class="lnum"> 33: </span> <span class="kwrd">return</span> 0L;
<span class="lnum"> 34: </span>}
启动测试程序,翻转手机到不同的位置,就能在Dialog框中,实时看到当前手机位置状态,Cool!
测试程序比较简单,就不放上来了,把封装的重力感应器的动态库放上来,供有兴趣的同学下载。
可以进行测试的手机型号:多普达(Dopod) Touch Diamond、多普达(Dopod) Touch Pro 或者 HTC Touch Diamond 和 HTC Touch Pro.
我的开发测试环境: Windows Vista 64bit, Visual Studio 2008 SP1, Windows Mobile 6.0 Professional SDK.
C# IDE Mobile – Write your C# code anywhere!
最近败了个QWERTY全键盘的HTC Touch pro,全键盘的感觉不错,输入速度比以前靠触摸笔点屏幕快多了。装了个Python的Windows mobile版本,没事学着写Python玩玩。一日突发奇想,要是能在PPC手机上写C#的程序并能运行起来,那就太棒了。果然不出我所料,国外已经有大侠已经做好了这个东东,一个运行在Windows Mobile手机上的简单的C# IDE,让你可以随时在你的PPC手机上写C#的程序。这是作者自己实现的一个简单IDE,现在已经支持的功能如下:
可以创建基于图形用户界面的程序
可创建方法和类
可以调用所有的.NET Compact Framework的类。
执行文件操作
运行进程
使用.NET 2.0中的范型
支持C#的控制语句,包括循环、条件判断……
IDE的使用非常简单,写入你的代码,然后可以立即运行,看到结果。
简单的例子,如下:
<span class="lnum"> 1: </span><span class="kwrd">using</span> System.Windows.Forms;
<span class="lnum"> 2: </span><span class="kwrd">namespace</span> TestNS
<span class="lnum"> 3: </span>{
<span class="lnum"> 4: </span> <span class="kwrd">class</span> TestCL
<span class="lnum"> 5: </span> {
<span class="lnum"> 6: </span> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> Main()
<span class="lnum"> 7: </span> {
<span class="lnum"> 8: </span> MessageBox.Show(<span class="str">"Hello Timothy!"</span>);
<span class="lnum"> 9: </span> }
<span class="lnum"> 10: </span> }
<span class="lnum"> 11: </span>}
点击菜单下面的Debug->Run,运行结果截图如下:
IDE自带一些简单的功能, 包括插入代码模板,编辑(复制、粘贴、剪切)功能,还支持插件功能。
软件下载地址: http://www.geocities.com/hrowson/wm5_software/cs_ide_mobile.zip
Code Sample: http://www.geocities.com/hrowson/wm5_software/cs_ide_mobile_samples.zip
用户手册、帮助文档地址: http://www.geocities.com/hrowson/wm5_software/cs_ide_mobile_manual/index.htm
作者主页:http://www.geocities.com/hrowson/wm5_software/index.htm
赶紧下载吧,write your C# code anywhere! 活活~~
Visual Studio 2010 Beta1 is available for download
You can download it by two ways below:
WebInstaller:http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID;=75cbcbcd-b0e8-40ea-adae-85714e8984e3
The new feature of VS2010:
Enhanced user experience, Parallel programming,support for Cloud development and support more databases,such as DB2 and oracle.
小黑降温记
夏日临近,天气一天比一天热,无意中用工具看了看CPU温度,竟然也上了70度。要是天气再热一点,估计小黑撑不过这个夏天了。
本打算去电脑城打开清理一下,但是又考虑到没那样的闲心跑电脑城,本着DIY的精神,打算自己来给小黑降降温,一个字:拆!。先在网上看相关的拆机教程,又在淘宝上找了一圈,发现一个卖家的东西还不错:电脑工具套装,包括N合一的螺丝刀,润滑油,导热硅脂,电脑清洁套装,一整套东西,60多来块,感觉还算便宜,于是拍下了。下班回家,便开始了拆机的历程。
首先需要拆下背面的螺丝,包括键盘、手托、U型框的固定螺丝,N颗。
取下固定CPU风扇的螺丝,准备拆下风扇
拿下风扇,CPU露出来了…
今天的主角:导热硅脂和润滑脂 淘宝货
取下CPU风扇,把风扇打开
取下扇叶,把润滑脂弄到那个小电动机的小孔里面
给CPU和显卡芯片抹上导热硅脂,装好风扇和键盘,开机裸奔测试效果
把机器还原,然后再跑一段时间,发现温度在60度左右,不错. 打完收工~~
Windows 7 新特性体验
要说本年度最值得期待的事,估计就是等待Windows 7的正式版发布了。或许是经历了Vista的失败,微软在痛定思痛过后,决心以Windows 7的推出挽回更多因为Vista而丢失的用户。而我也不例外,虽然我也用着Vista,其实也迫不及待的等待着Windows 7正式版的发布。自从Windows 7 Beta版推出以来,我就很贪婪的在网上关注着每个Win7 Build版本的出现。终于,微软官方发话了,说Windows 7 正式版将在今年圣诞之前发布。在期待正式版的同时,我也迫不及待的在虚拟机上装上了Beta版。体验之余,发现有很多很好的,激动人心的改进,截图分享下。
1.任务栏改进
采用了大图标,看起来更加直观,也更加方便带触摸屏的电脑进行触摸操作,并且这些图标对应的程序都有对应的快捷键,方便用户快捷操作。比如图中的浏览器图标,对应Win+1组合键,Media Player对应Win+3键。你也试试看?对应的数字,和图标的排序有关。(其实这功能Vista里面也有,不知道你发现没有,呵呵)
增加了”图钉”功能,你能把常用的程序用图钉”钉”在任务栏上。还可以使用鼠标右键,拖动你常用的文件夹到任务栏上,这样,文件夹会被钉在Explorer的弹出菜单上。
任务栏通知区域也有了改进,多个程序提醒图标被放到了一个弹出的List里面,更加节约空间和美观。
2.UAC提示的改进
这个用过Vista的人都知道,频繁的UAC提示让人心烦,也让人反感。微软也宣布,Windows 7的UAC提示会比Vista减少三分之一左右。并且,Windows 7也提供了方便关闭UAC提示的功能。整个UAC控制被分成四级,供用户调整。
• 当用户在安装软件或修改Windows系统设置时总是提醒用户(与Vista系统相同)。
• 当用户在安装软件时提醒用户,在修改Windows设置时不提醒用户(当前默认设置)。
• 在用户安装软件时提醒用户,但是关闭UAC安全桌面,即提示用户时桌面其它区域不会失效。
• 从来不提醒用户(不推荐这种方式)
- Action Center
你也许会疑惑,好像在Windows 7里面没看到那个著名的”安全中心”的影子。其实Windows 7有了个新的功能:Action Center,而以前的安全中心也被融入到了其中。Action Center中除了包括原先的安全设置,还包含了其它管理任务所需的选项,如Backup, Troubleshooting And Diagnostics以及 Windows Update等功能。
- XP模式
为兼容一些老的程序,XP模式能在Windows 7中模拟XP系统环境,此”XP模式”不会内置于Windows 7,而是用户在购买Windows 7专业版、企业版或最终版后,通过免费下载获得。XP模式,由Virtual PC虚拟环境和完整Windows XP SP3授权共同组成,并将免费提供给Windows 7 Professional、Enterprise和Ultimate版本用户。
其实还有很多令人激动的特性,就不一一列举了,非常期待Windows 7正式版能早日发布。
如果你也下载了Windows 7的Beta版,你可以免费在微软的官方网页上申请试用的CDKEY: http://www.microsoft.com/windows/windows-7/beta-download.aspx
Unity 学习笔记(3) — 生命周期管理
换了新鼠标
Unity 学习笔记(2) — 配置文件的使用
Unity 学习笔记(1) -- Unity简介及简单使用
Unity是微软Patterns & Practices团队所开发的一个轻量级的,并且可扩展的依赖注入(Dependency Injection)容器,它支持常用的三种依赖注入方式:构造器注入(Constructor Injection)、属性注入(Property Injection),以及方法调用注入(Method Call Injection).现在Unity最新的版本的1.2版,可以在微软的开源站点http://unity.codeplex.com下载最新的发布版本和文档。通过使用Unity,我们能轻松构建松耦合结构的程序,从而让整个程序框架变得清晰和易于维护。
在平常的软件编码过程中,程序的逻辑往往很复杂,尤其是大型项目的开发中,一个模块常常会去引用其他的模块,假设我们有一个监控器类,用来监控CPU的温度,当温度达到预警的范围时,监控器有一个报警的方法,方法里面通过短信提醒器,以发送短信的方式通知维护人员。于是就出现了下面这样一段最为常见的代码:
<span class="lnum"> 1: </span><span class="kwrd">public</span> <span class="kwrd">class</span> Monitor
<span class="lnum"> 2: </span>{
<span class="lnum"> 3: </span> <span class="kwrd">public</span> <span class="kwrd">void</span> Alarm()
<span class="lnum"> 4: </span> {
<span class="lnum"> 5: </span> SMSNotify notify = <span class="kwrd">new</span> SMSNotify();
<span class="lnum"> 6: </span> notify.Send();
<span class="lnum"> 7: </span> }
<span class="lnum"> 8: </span>}
在Monitor类中,直接引用到了一个短信提醒器的类,这是最为不灵活和最不易于扩展的一种方式。或许我们想到了面向接口编程,利用多态的好处,可以提供灵活的不同子类的实现,增加代码扩展性等等。但是说到底,接口一定是需要实现的,也就是如下语句迟早要执行:
<span class="lnum"> 1: </span><span class="kwrd">public</span> <span class="kwrd">void</span> Alarm()
<span class="lnum"> 2: </span>{
<span class="lnum"> 3: </span> INotify notify = <span class="kwrd">new</span> SMSNotify();
<span class="lnum"> 4: </span> notify.Send();
<span class="lnum"> 5: </span>}
这样看来,在实现INotify这个接口的时候,仍然需要具体的类来实现,而这样的代码在程序编译的时候就已经固定下来,如果以后需要使用新的提醒器,仍旧需要修改源代码并重新编译。并且在我们的Monitor类中,明显依赖SMSNotify类,二者之间的耦合度非常紧密。因此Ioc(控制反转)模式被提出用来解决这种问题,也即把接口的具体实现延缓到运行时,接口的实现类是在运行时被装载的。这样,就算有了新的实现类,也不需要更改调用者的代码(可以在Unity中使用配置文件的方式实现)。这种Ioc模式可以被形象的比喻为:接口就像一个空壳,而在具体实现时,向这个空壳注入内容,而让它成为一个真正的实体。这种模式也被形象的称为:依赖注入。通过使用Unity,我们能构建松耦合的软件,并且对象之间相互关联的细节,我们也不必关心,可以交由依赖注入容器全权负责。
前面也提到了依赖注入常用的三种形式:构造器注入、属性注入和方法调用注入,我们可以通过例子来实现这三种形式的注入。还是以上面的场景为例,我们的几个类和接口如下图:
1.Constructor Injection
IMonitor接口定义:
<span class="lnum"> 1: </span><span class="kwrd">public</span> <span class="kwrd">interface</span> IMonitor
<span class="lnum"> 2: </span>{
<span class="lnum"> 3: </span> <span class="kwrd">void</span> Alarm();
<span class="lnum"> 4: </span>}
Monitor类:
<span class="lnum"> 1: </span><span class="kwrd">public</span> <span class="kwrd">class</span> Monitor : IMonitor
<span class="lnum"> 2: </span>{
<span class="lnum"> 3: </span> <span class="kwrd">private</span> INotify notify;
<span class="lnum"> 4: </span>
<span class="lnum"> 5: </span> <span class="kwrd">public</span> Monitor(INotify n)
<span class="lnum"> 6: </span> {
<span class="lnum"> 7: </span> notify = n;
<span class="lnum"> 8: </span> }
<span class="lnum"> 9: </span>
<span class="lnum"> 10: </span> <span class="kwrd">public</span> <span class="kwrd">void</span> Alarm()
<span class="lnum"> 11: </span> {
<span class="lnum"> 12: </span> notify.Send();
<span class="lnum"> 13: </span> }
<span class="lnum"> 14: </span>}
INotify接口定义:
<span class="lnum"> 1: </span><span class="kwrd">public</span> <span class="kwrd">interface</span> INotify
<span class="lnum"> 2: </span>{
<span class="lnum"> 3: </span> <span class="kwrd">void</span> Send();
<span class="lnum"> 4: </span>}
EmailNotify类:
<span class="lnum"> 1: </span><span class="kwrd">public</span> <span class="kwrd">class</span> EmailNotify : INotify
<span class="lnum"> 2: </span>{
<span class="lnum"> 3: </span> <span class="kwrd">public</span> <span class="kwrd">void</span> Send()
<span class="lnum"> 4: </span> {
<span class="lnum"> 5: </span> Console.WriteLine(<span class="str">"Send Email Notify..."</span>);
<span class="lnum"> 6: </span> }
<span class="lnum"> 7: </span>}
SMSNotify类:
<span class="lnum"> 1: </span><span class="kwrd">public</span> <span class="kwrd">class</span> SMSNotify : INotify
<span class="lnum"> 2: </span>{
<span class="lnum"> 3: </span> <span class="kwrd">public</span> <span class="kwrd">void</span> Send()
<span class="lnum"> 4: </span> {
<span class="lnum"> 5: </span> Console.WriteLine(<span class="str">"Send SMS Notify..."</span>);
<span class="lnum"> 6: </span> }
<span class="lnum"> 7: </span>}
可以看到,在Monitor类的构造函数里面,传入的参数是一个INotify接口类型,Alarm方法,调用了实现类的Send方法,但具体调用哪一个实现类的Send方法,只有在注入实体后才知道。Unity容器中,通常使用RegisterType和Resolve方法来分别注册和获取实例,并且这两个方法有很多泛型和非泛型的重载,具体的类型和参数,可以参考Unity的官方帮助文档。
现在我们向Monitor的构造函数注入实现INotify接口的实例:
<span class="lnum"> 1: </span><span class="kwrd">static</span> <span class="kwrd">void</span> Main(<span class="kwrd">string</span>[] args)
<span class="lnum"> 2: </span>{
<span class="lnum"> 3: </span> IUnityContainer container = <span class="kwrd">new</span> UnityContainer();
<span class="lnum"> 4: </span> container.RegisterType<IMonitor, Monitor>().RegisterType<INotify, SMSNotify>();
<span class="lnum"> 5: </span>
<span class="lnum"> 6: </span> IMonitor monitor = container.Resolve<IMonitor>();
<span class="lnum"> 7: </span> monitor.Alarm();
<span class="lnum"> 8: </span>
<span class="lnum"> 9: </span> Console.ReadLine();
<span class="lnum"> 10: </span>}
代码中我们注入的INotify实例是SMSNotify类的实例,然后调用monitor.Alrarm(),里面会调用notify.Send().
运行查看结果:
上面是针对单个构造函数的情况,如果有多个构造函数,需要指明哪个构造函数是需要被注入的,也即需要在指定被注入的构造函数加上attribute:InjectionConstructor
<span class="lnum"> 1: </span><span class="kwrd">public</span> Monitor(INotify n, <span class="kwrd">string</span> name)
<span class="lnum"> 2: </span>{
<span class="lnum"> 3: </span> notify = n;
<span class="lnum"> 4: </span>}
<span class="lnum"> 5: </span>
<span class="lnum"> 6: </span>[InjectionConstructor]
<span class="lnum"> 7: </span><span class="kwrd">public</span> Monitor(INotify n)
<span class="lnum"> 8: </span>{
<span class="lnum"> 9: </span> notify = n;
<span class="lnum"> 10: </span>}
运行后可得到一样的结果.
2.Property Injection
通过属性注入,我们需要加上attribute: Dependency,使得Unity容器在获取类对象实例时,自动实例化该属性所依赖的对象,并注入到属性中。
修改Monitor类,实现下面的代码:
<span class="lnum"> 1: </span><span class="kwrd">public</span> <span class="kwrd">class</span> Monitor : IMonitor
<span class="lnum"> 2: </span>{
<span class="lnum"> 3: </span> [Dependency]
<span class="lnum"> 4: </span> <span class="kwrd">public</span> INotify Notify { get; set; }
<span class="lnum"> 5: </span>
<span class="lnum"> 6: </span> <span class="kwrd">public</span> <span class="kwrd">void</span> Alarm()
<span class="lnum"> 7: </span> {
<span class="lnum"> 8: </span> Notify.Send();
<span class="lnum"> 9: </span> }
<span class="lnum"> 10: </span>}
再在Main函数里面,修改原有的代码,这次我们让容器注入EmailNotify实例:
<span class="lnum"> 1: </span>container.RegisterType<INotify, EmailNotify>();
运行查看结果:
还有一个比较方便的地方,可以为Dependency特性指定名称,这样,在注入时,会将RegisterType所指定的对应名称的实体进行注入,例如:
<span class="lnum"> 1: </span> <span class="kwrd">public</span> <span class="kwrd">class</span> Monitor : IMonitor
<span class="lnum"> 2: </span> {
<span class="lnum"> 3: </span> [Dependency(<span class="str">"SMS"</span>)]
<span class="lnum"> 4: </span> <span class="kwrd">public</span> INotify Notify { get; set; }
<span class="lnum"> 5: </span>
<span class="lnum"> 6: </span> <span class="kwrd">public</span> <span class="kwrd">void</span> Alarm()
<span class="lnum"> 7: </span> {
<span class="lnum"> 8: </span> Notify.Send();
<span class="lnum"> 9: </span> }
<span class="lnum"> 10: </span> }
修改Main函数,在RegisterType函数中指定注入名称:
<span class="lnum"> 1: </span> container.RegisterType<INotify, EmailNotify>(<span class="str">"Email"</span>);
<span class="lnum"> 2: </span> container.RegisterType<INotify, SMSNotify>(<span class="str">"SMS"</span>);
3.Method Call Injection
Method Call Injection注入的时机和Constructor Injection有一定的区别,构造函数注入,是在容器创建实例的时候,而方法调用注入,是在方法被调用的时候。实现方法调用注入,需要在指定注入的方法前加上attribute: InjectionMethod
修改Monitor类的代码如下:
<span class="lnum"> 1: </span> <span class="kwrd">public</span> <span class="kwrd">class</span> Monitor : IMonitor
<span class="lnum"> 2: </span> {
<span class="lnum"> 3: </span> <span class="kwrd">private</span> INotify notify;
<span class="lnum"> 4: </span>
<span class="lnum"> 5: </span> [InjectionMethod]
<span class="lnum"> 6: </span> <span class="kwrd">public</span> <span class="kwrd">void</span> GetNotify(INotify n)
<span class="lnum"> 7: </span> {
<span class="lnum"> 8: </span> notify = n;
<span class="lnum"> 9: </span> }
<span class="lnum"> 10: </span>
<span class="lnum"> 11: </span> <span class="kwrd">public</span> <span class="kwrd">void</span> Alarm()
<span class="lnum"> 12: </span> {
<span class="lnum"> 13: </span> notify.Send();
<span class="lnum"> 14: </span> }
<span class="lnum"> 15: </span> }
在程序运行时,容器会自动实例化GetNotify方法所依赖的对象,并自动调用该方法,将其注入到方法中。
Main函数如下:
<span class="lnum"> 1: </span> <span class="kwrd">static</span> <span class="kwrd">void</span> Main(<span class="kwrd">string</span>[] args)
<span class="lnum"> 2: </span> {
<span class="lnum"> 3: </span> IUnityContainer container = <span class="kwrd">new</span> UnityContainer();
<span class="lnum"> 4: </span> container.RegisterType<IMonitor, Monitor>();
<span class="lnum"> 5: </span> container.RegisterType<INotify, EmailNotify>();
<span class="lnum"> 6: </span>
<span class="lnum"> 7: </span> IMonitor monitor = container.Resolve<IMonitor>();
<span class="lnum"> 8: </span> monitor.Alarm();
<span class="lnum"> 9: </span>
<span class="lnum"> 10: </span> Console.ReadLine();
<span class="lnum"> 11: </span> }
运行查看结果:
WAP Access is available!
此博客的WAP访问地址已经开启,现在你可以使用手机随时随地的通过以下地址进行访问:
点击下载此文件