Reflection(反射)是深入学习.Net必须掌握的技能之一。最初学Reflection的时候,的确是被惊住了,原来还可以这样。只要给你一个Assembly, 你就能获取到其中所有的类型,根据类型,你能够创建和操作对象的属性和方法,甚至是私有的。但是,每次使用Reflection,看着那些丑陋难懂的代码,都让人不敢直视。下面就介绍一些在特定场景下可以替换Reflection的方法。
1. 使用Reflection完成的简单Demo
我们首先创建一个Person类,这个类非常简单,一个Name的public属性,一个_age的私有变量。完整代码如下:
{
private readonly int _age;
public Person(int age)
{
_age = age;
}
public string Name { get; set; }
public bool GuessAge(int age)
{
return _age == age;
}
}
接下来,看看常规的使用reflection获取一个person对象公开属性,私有变量同时调用对象的方法:
var property = type.GetProperty("Name");//根据名称获取类型属性
Console.WriteLine(property.GetValue(p).ToString());//获取对象的属性值
var field = type.GetField("_age", BindingFlags.NonPublic | BindingFlags.Instance);//获取私有变量_age, 后面的BindingFlags非常重要,否则默认是不能够取到private的东西
Console.WriteLine(field.GetValue(p));
var guessResult = type.InvokeMember("GuessAge", BindingFlags.InvokeMethod, null, p, new object[] { 20 });//调用对象的方法
Console.WriteLine(guessResult);
来看看输出结果:
2. 使用PrivateObject
什么是PrivateObject, PrivateObject是微软在单元测试中引入的,本意是方便我们写单元测试的时候,对于私有变量,方法,能够非常简单方便的调用。但是这也不妨碍我们在开发代码中使用。使用PrivateObject只需要引用Microft.VisualStudio.QualityTools.UnitTestFramework
接下来看看,如何使用PrivateObject来实现:
Console.WriteLine(privateObject.GetProperty("Name"));
Console.WriteLine(privateObject.GetField("_age"));
Console.WriteLine(privateObject.Invoke("GuessAge", new object[] { 20 }));
上面的代码和使用Reflection的效果完全一样。是不是觉得整个世界都情景许多。在代码的可读性上面,比Reflection好不少。
3. 使用dynamic
使用动态类型,可以非常简单方便的访问对象的属性的方法,比如上面的代码,如果我用dynamic实现:
Console.WriteLine(person.Name);
//Console.WriteLine(person._age);
Console.WriteLine(person.GuessAge(20));
使用dynamic的前提是,你在写代码的时候,就需要知道该对象的确切的属性名字和方法名,不能作为参数传递。而上面的Refelction和PrivateObject是可以的。
使用dynamic还有一个缺点,就是无法访问到对象的私有成员。这也是注释掉_age输出的原因。
真实的使用场景是,可以在不需要定义接口的情况下,实现通用的代码。比如Person有个Start属性, Car也有个Start属性,有个功能是需要为由Start的东西,显示的时候,都要带个星星的图标,这个时候,使用dynamic,就能够写出同时支持Person和Car的方法。
4. 使用Exposed
使用dynamic不能访问私有成员的问题,在Exposed里得到完全解决,从名字(翻译成暴露)也能看出来,它就是干这个的。
Console.WriteLine(exposedObj.Name);
Console.WriteLine(exposedObj._age);
Console.WriteLine(exposedObj.GuessAge(20));
Exposed是第三方开源的,项目地址是https://github.com/Cognifide/ExposedObject,也可以在nuget中下载到。
5. 大杀器Clay
看到上面的“废话”,动态语言的爱好者只会冷笑一下,丑陋的静态编译语言,这些东西在动态语言里面,“这都不是事”。好吧,我承认,但是看完了Clay,也许能改变你的看法。
var person = New.Person().Name("Louis")._age(30);
person.GuessAge = new Func<int, bool>(x => x == person._age);
Console.WriteLine(person.Name);
Console.WriteLine(person._age);
Console.WriteLine(person.GuessAge()(20));
跟多的了解Clay,可以看这篇http://www.cnblogs.com/JustRun1983/p/3529157.html
本文链接:代替Reflection(反射)的一些方法,转载请注明。
目的:
1. 通过网页读取watchdog的信息
2. 通过网页设置watchdog
准备工作:
1. 选择一个web框架,选用 cherrypy
$ sudo apt-get install python-cherrypy3
2. 熟悉 RESTFUL , 参考redhat REST API 指导
步骤:
我们选择了一个cherrypy作为web框架。 cherrypy的部署简单。
这只是个demo,没有实现MVC,大家自己练习。
此外也没有实现模板,距离一个正式的网站还差的很远。
界面实现如下:
代码如下:
代码中,喂狗代码采用了一个线程。需要改进。
发现不是很好,因为每个wsgi的请求都是一个线程。
最好是采用cherrypy提供的background, 或者将该逻辑独立为一个单例模式。
watchdog.py
2 import json
3 import time
4 import threading
5
6
7 index_html = """
8 <html>
9 <head>
10 <style type="text/css">
11 .watchdog-state {
12 display: inline-block;
13 height: 16px;
14 width: 16px;
15 border-radius: 8px;
16 margin-left: 10px;
17 margin-right: 10px;
18 }
19 .up {
20 background: linear-gradient(to bottom, #BFD255 0%%, #8EB92A 50%%,
21 #72AA00 51%%, #9ECB2D 100%%) repeat scroll 0 0 transparent;
22 }
23
24 .down {
25 background: linear-gradient(to bottom, #AFAFAF 0%%, #AFAFAF 50%%,
26 #AFAFAF 51%%, #AFAFAF 100%%) repeat scroll 0 0 transparent;
27 }
28 </style>
29 </head>
30
31 <body>
32 <script type="text/javascript">
33 function requestJSON(url, suc, done, err) {
34 var xmlhttp;
35 xmlhttp = new XMLHttpRequest();
36 xmlhttp.open("POST", url, true);
37 xmlhttp.setRequestHeader("Content-type", "application/json");
38 xmlhttp.setRequestHeader("dataType", "application/json");
39 xmlhttp.onreadystatechange=function(){
40 if (xmlhttp.readyState==4 && xmlhttp.status==200) {
41 var responseContext = xmlhttp.responseText;
42 var jsonobj=eval('('+responseContext+')');
43 suc(jsonobj);
44 } else{
45 // alert("readyState: " + xmlhttp.readyState + "status" + xmlhttp.status);
46 }
47 }
48 xmlhttp.send();
49 }
50
51 function operationWatchdog()
52 {
53 // alert("operationWatchdog");
54 var url = "watchdog/deactivate";
55 var action = document.getElementById("watchdog-action");
56 if (action.innerHTML == "Activate"){
57 url = "watchdog/activate";
58 }
59 requestJSON(url, function(data){
60 // alert(data.value);
61 });
62 if (action.innerHTML == "Activate"){
63 action.innerHTML = "Deactivate";
64 } else {
65 action.innerHTML = "Activate";
66 }
67 var status = document.getElementById("watch-status");
68 if (status.className.match("up$")){
69 status.className = "watchdog-state down";
70 } else{
71 status.className = "watchdog-sta
没有评论:
发表评论