使用反射验证模板模式的代码

Rah*_*han 0 .net c# reflection unit-testing standards-compliance

我正在开发一个大型项目,其中一个基类有数千个派生自它的类(多个开发人员正在研究它们).期望每个类重写一组方法.我首先使用符合可接受模式的代码模板生成了数千个类文件.我现在正在编写单元测试,以确保开发人员没有偏离这种模式.以下是生成的示例类:

// Base class.
public abstract partial class BaseClass
{
    protected abstract bool OnTest ();
}

// Derived class. DO NOT CHANGE THE CLASS NAME!
public sealed partial class DerivedClass_00000001: BaseClass
{
    /// <summary>
    /// Do not modify the code template in any way.
    /// Write code only in the try and finally blocks in this method.
    /// </summary>
    protected override void OnTest ()
    {
        bool result = false;
        ComObject com = null;
        // Declare ALL value and reference type variables here. NOWHERE ELSE!
        // Variables that would otherwise be narrowly scoped should also be declared here.
        // Initialize all reference types to [null]. [object o;] does not conform. [object o = null;] conforms.
        // Initialize all value types to their default values. [int x;] does not conform. [int x = 0;] conforms.

        try
        {
            com = new ComObject();

            // Process COM objects here.
            // Do NOT return out of this function yourself!
        }
        finally
        {
            // Release all COM objects.
            System.Runtime.InteropServices.Marshal.ReleaseComObject(com);

            // Set all COM objects to [null].
            // The base class will take care of explicit garbage collection.
            com = null;
        }

        return (result);
    }
}
Run Code Online (Sandbox Code Playgroud)

在单元测试中,我已经能够通过反射验证以下内容:

  • 该类派生自[BaseClass]并且不实现任何接口.
  • 类名符合模式.
  • catch块尚未过滤.
  • 没有添加其他捕获块.
  • 没有声明类级别字段或属性.
  • 声明时手动初始化所​​有方法值类型变量.
  • 没有其他方法添加到派生类.

以上很容易通过反思实现,但我正在努力断言以下列表:

  • catch块重新抛出捕获的异常,而不是包装它或抛出一些其他异常.
  • 最后[return (result);]一行未被修改,也没有[return (whatever);]添加其他呼叫.不知道如何实现这一目标.
  • 验证是否已处置实现IDisposable的所有引用类型.
  • 验证[System .__ ComObject]类型的所有引用类型是否已手动取消引用,并在finally块中设置为[null].

我考虑过解析源代码,但除非绝对必要,否则我不喜欢这个解决方案.这是凌乱的,除非我有表达树,几乎不可能保证成功.

任何提示将不胜感激.

Dan*_*rth 6

一些想法:

  1. 如果方法需要重写,为什么它们virtual代替abstract
  2. 不应更改的代码不属于派生类.它属于基类.
  3. catch { throw; }没用.去掉它.
  4. void方法返回布尔值会导致编译器错误.
  5. 将局部变量设置null为无用.
  6. 并非所有引用类型都实现IDisposable.

通常:您的大多数要求似乎没有商业价值.

  • 为什么禁止实现接口?
  • 为什么禁止宣布其他方法?
  • 为什么要禁止catch条款?
  • 等等

您应该考虑实际的业务需求,并在其后对类进行建模.如果类需要履行某个合同,那么合同的模型.将实现保留给实现者.


关于提出的实际问题:
你不能在这里使用反射.您可以分析原始源代码或已编译程序集的IL代码.
这两个选项都相当棘手,很可能无法在有限的时间内完成.我很肯定修复架构比实现其中一个选项花费的时间更少.