Skip navigation.

自一个人默默走

从 C 的角度使用 C++,而不是反切入 C——这样会简化很多的问题

Posts tagged with "reflect"

TestHelper

, , , ...

我估计这个类在 VS2005 已经实现了,重新造个轮子,但是在 VS2003 上非常重要:
1. 它可以让单元测试不依赖于直接在 VS 中使用对项目的引用。换句话说,VS2003 是不允许引用非 .dll 后缀的项目的,它只须通过目标文件的全路径就可以反射项目。
2. 前一点也说过,它是通过反射来调用方法属性的,也就是说它可以任意地调用 private, protected 成员,在 C# 语言的框架内要从外部调用私有成员是不可能的。
3. 有了其帮助,我可以任意地对各种目标 .NET Assembly 进行单元测试,甚至没有源码都可以进行。

Policy-based & C#

, , , ...

早晨实现了一个基于 policy 的 class,在有 GC 机制的前提下实现 Policy Pattern 是可行的。问题是用了非常多的动态类型机制,这个东西如果是大应用的话,消耗很大。
因为考虑到在实际的测试中对于创建一个对象的实例可能存在两种情况:直接调用 new 或者通过反射以及类型路径来创建,所以我写了 DirectNewPolicyReflectCreatePolicy,第二个策略即使不对目标项目进行引用,仍然可以创建目标 Assembly 中的类型,这样可以实现目标项目对测试无知,并且我可以使用同样的方法对 public, protected, private 成员进行同样的测试。

C# 反射

, , , ...

很难吗?NO! 下午一直在编写 C# 反射的代码——如果不能引用非 .dll 后缀的 .NET 项目,另一个办法就是利用反射直接从 .NET assembly 中读取元素进行测试。
C# meta 级对象真是多:type(enum, class, delegate, ...), method, property, ...从 System.Reflection 中就可以获得许多关于 C# meta 的信息。
要实现 C++ 的反射,两个 meta 是:method 和 type。注意是 type 不是 class,C++ 不是 class-based 的语言。还一个要探讨的问题是:在 C++ 实现对 property 的反射意义大不。
C++ 通过静态的 template 技巧进行反射,在一些方面非常强大,但是动态方面却十分不足,不可以通过 C++ 生成 .NET assembly (当然你要是觉得 C++/CLI 是 C++ 的话是可以的),要进行通过动态反射的单元测试是很难的。

C# 单元测试

, ,

在实践中,使用类自己测试自己,当没有创建自身实例时可行,但是如果创建了,会进入死循环中。不知道别人是不是都碰到了,反正我的程序在 csUnit 中是这样的。

为了保证一致性,我不采用继承的办法来测试 protected 的成员,而是同 private 一样,使用 reflect 方法来测试。在 C# 中,没想到 reflect 异常简单,直接 InvokeMember(...) 就搞定了。

从单元测试的角度出发,我重新写了一个 IPAddress 类。原来的那个是测试在后,而现在这个是测试在前,没想到效果完全不同,产生的代码也基本不同——在完成相同功能的前提下,测试在前的代码相对之更快、更稳定、更简洁……好处太多了!

单元测试和 C++

, , , ...

突然想到个事情:C# 是通过继承来测试 protected 的成员,是通过 assembly reflection 来测试 private 成员。那么在 C++ 中,即没有 attributed 的方法,更没有完备的 runtim reflect 机制,那么 C++ 程序怎样才能实现使目标代码完全不知晓的测试呢?

C++ 的悲哀

, , , ...

今天都在使用单元测试,发现集成在 IDE 中的 Test Runner 非常地方便,于是想,如果 C++ 也提供这样的集成测试就好了。
后来分析了下,觉得不太可能:C# Source -compile-> Assembly, Test Runnter -reflect-> Assembly,可以用独立的 Runner 测试 Assembly;而 C++ Source -comipled-> binary,C++ 编译成 binary 的过程中几乎不留下任何 runtime information,程序只有可能自己感知自己,如 CxxTest 的工作原理:CxxTest + C++ Source -generate-> TestUnit.cpp,生成的过程是由一个 perl 脚本完成的,然后使用某种编译器编译 TestUnit.cpp 生成 .exe 并运行,才最终给出测试结果。
CxxTest for eclipse 的插件只是隐藏了生成测试代码、编译、运行等步骤,事实上,它们还是要经历的。

Unit Test & C#

, , ,

为了避免麻烦,我把测试代码和目标代码混在一块。这么做,虽然违反了目标项目对测试代码的无知性,但是却带来了一些好处:
1. 对于 privateprotected 的代码,不再需要用 reflect 或继承的办法进行测试;
2. 不需要对一个非 .dll 的项目进行引用,事实上这在 VS2003 我没有成功实现过;
3. 快速地测试。不需要通过一大堆的手法、adapter 进行测试,我的目标很明确。
虽然这种写法,在代码上交的时候,会连同测试代码也上交了,但我用宏做了条件编译。这在编译成 binary 的时候是没有影响的。

C++ Development

, , , ...

看了些关于 Vim 的文章,心情不能平静。关于 Vim 我现在面临着两大问题:
1. 不能集成 GDB 调试;更几乎没听说过集成 DDD;
2. 不能进行 C++ 重构;连最基本的 Java/C# 重构都没找到资料。
关于集成调试器的,Emacs 做得很好,但是我不觉得 Emacs 会比 Vim 更快捷。但是如果 Emacs 也支持 C++ 重构,那么我可能花精力去学习 Emacs。

Generic Reflect

, , , ...

在 GP 的概念中,有两种 meta:基于时间的 method;基于状态的 data。究竟是 method 创建了 data 还是倒过来,这是个“鸡生蛋,蛋生鸡”的问题,所以不用去追究了。解决的办法就是同时创建 method 和 data。
在 Java 和 C# 中,一味地认为 method 只是某个 class 的附属品,实际它们是在逃避某一些设计上的复杂度。
现在我面临的问题是:如何实现一个 C++ 的反射?用 template 的技巧可以比较容易获得类型的某一些信息;但是另外一些,诸如方法的名称、类型成员等等信息都非常难获得——没有编译器的支持,这些信息只可能通过宏间接实现。

Windows & Ubuntu

, , , ...

非常遗憾,从 Ubuntu 上运行 Windows 失败!一方面是 Xen 对 Windows 并不完全支持;另外则是我现在机器的配置不行——用 Wine 跑 IE 就惨不忍睹了。没法,最终还是要装上 Windows XP。

现在的打算是:用 .NET Framework 开发程序,但同时进行 C++ 的研究,计划是开发一个基于 native code 的 managed C++,享有 GC 等高级功能,但是不失 native C++ 本身的速度。研究 C# 的 reflect 机制,估计会让我在 C++ 的反射方面有所突破吧。

现在头疼的是选择一个 C++ IDE。用 Visual C++ 或许不错,但是我想基于 GCC 进行开发,这个问题还要思考一下。