使用反射根据模板模式验证代码 [英] Verifying code against template patterns using reflection

查看:42
本文介绍了使用反射根据模板模式验证代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am working on a large project where a base class has thousands of classes derived from it (multiple developers are working on them). Each class is expected to override a set of methods. I first generated these thousands of class files with a code template that conforms to an acceptable pattern. I am now writing unit tests to ensure that developers have not deviated from this pattern. Here is a sample generated class:

// 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);
    }
}

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

In the unit tests, I have been able to verify the following via reflection:

  • 该类派生自 [BaseClass],不实现任何接口.
  • 类名符合某种模式.
  • 未过滤 catch 块.
  • 未添加其他 catch 块.
  • 没有声明类级别的字段或属性.
  • 所有方法值类型变量都在声明时手动初始化.
  • 未向派生类添加其他方法.

上述内容很容易通过反射实现,但我正在努力声明以下列表:

The above is easily achieved via reflection but I am struggling with asserting the following list:

  • catch 块重新抛出捕获的异常,而不是包装它或抛出其他一些异常.
  • 末尾的 [return (result);] 行没有被修改,也没有添加其他 [return (whatever);] 调用.不知道如何实现这一点.
  • 验证所有实现 IDisposable 的引用类型都已被释放.
  • 验证所有类型为 [System.__ComObject] 的引用类型都已被手动取消引用并在 finally 块中设置为 [null].
  • The catch block re-throws the caught exception rather than wrapping it or throwing some other exception.
  • The [return (result);] line at the end has not been modified and no other [return (whatever);] calls have been added. No idea how to achieve this.
  • Verify that all reference types implementing IDisposable have been disposed.
  • Verify that all reference types of type [System.__ComObject] have been manually de-referenced and set to [null] in the finally block.

我曾考虑过解析源代码,但除非绝对必要,否则我不喜欢该解决方案.它很混乱,除非我有表达式树,否则几乎不可能保证成功.

I have thought about parsing the source code but I don't like that solution unless absolutely necessary. It is messy and unless I have expression trees, almost impossible to guarantee success.

任何提示将不胜感激.

推荐答案

一些想法:

  1. 如果方法需要被覆盖,为什么它们是virtual而不是abstract?
  2. 不应更改的代码不属于派生类.它属于基类.
  3. catch { throw;} 没用.删除它.
  4. void 方法返回布尔值会导致编译器错误.
  5. 将局部变量设置为 null 是没有用的.
  6. 并非所有引用类型都实现 IDisposable.
  1. If the methods need to be overriden, why are they virtual instead of abstract?
  2. Code that should not be changed doesn't belong in the derived class. It belongs in the base class.
  3. catch { throw; } is useless. Remove it.
  4. Returning a boolean value from a void method causes a compiler error.
  5. Setting local variables to null is useless.
  6. Not all reference types implement IDisposable.

一般来说:您的大部分需求似乎都没有商业价值.

Generally: Most of your requirements seem to have no business value.

  • 为什么禁止实现接口?
  • 为什么禁止声明其他方法?
  • 为什么禁止 catch 子句?

您应该真正考虑您的实际业务需求并根据它们为您的类建模.如果类需要履行某个合同,请对该合同建模.将实现留给实现者.

You should really think about what your actual business requirements are and model your classes after them. If the classes need to fulfill a certain contract, model that contract. Leave the implementation to the implementor.

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

About the actual questions raised:
You can't use reflection here. You can either analyze the original source code or the IL code of the compiled assembly.
Both options are pretty tricky and most likely impossible to achieve within your limited time. I am positive that fixing the architecture would take less time than implementing one of those options.

这篇关于使用反射根据模板模式验证代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆