如何使用反射或类似方法动态提取方法的代码?

问题描述

我已经编写了一个模块化的沙箱,旨在作为各种各样的生活组合使用,到目前为止,它的运行情况很好,但是我有一个想法,似乎无法弄清楚该怎么做。作为快速概述,当我有一个新想法或想要测试一个新概念时,我为它编写一个模块。每个模块都从SandBoxModule派生而来,该模块包含一个称为Execute的抽象方法。当我创建一个模块时,它看起来像这样:

public class DemoModule : SandBoxModule {
    protected override void Execute() {
        // Do something super cool and new.
    }
}

没有什么可以阻止我创建其他方法来从Execute方法调用的,就像在其他任何自定义对象中一样:

public class DemoModule : SandBoxModule {
    protected override void Execute() {
        int x = 3;
        SomethingSuperCoolAndNew(x);
    }
    private void SomethingSuperCoolAndNew(int someArg) {
        // Do something super cool and new.
    }
}

我如何以动态方式(例如,使用反射)捕获Execute方法代码内容以及它可能调用的任何方法,它们可能调用的任何方法,等等string


注意:如果有必要,我不反对使用第三方库。尽管如果没有它们也可以做到,但就沙盒的性质而言,我更愿意采用这种方式。

我已经研究过使用MethodBas.GetMethodBody(),它不会返回我想要显示内容

一个可行的想法是从我的GitHub存储库加载源文件。在此期间,我会尝试一下,但我仍然想知道是否有一种方法可以避免跳过那一圈?

解决方法

Reflection使您可以发现类成员,例如属性或方法,但仅提供有关其签名的信息(参数名称和类型以及返回类型等),而没有有关其实现的信息。


如果您有权访问源代码,则可以使用C#编译器为您进行语法分析。

请参阅:Get started with syntax analysis (The .NET Compiler Platform SDK)

特别是Traversing trees一章说明了如何发现代码的结构。


但是记录代码的更好方法是使用XML注释(也称为Documentation comments)。

Build页的项目选项中,选中XML documentation file复选框,然后编写如下注释:

/// <summary>
/// Base module for sandboxed operations.
/// </summary>
public abstract class SandboxModule
{
    /// <summary>
    /// Implementing modues must override this method.
    /// </summary>
    protected abstract void Execute();
}

/// <summary>
/// This is my super cool demo module.
/// </summary>
public class DemoModule : SandboxModule
{
    /// <summary>
    /// Does something super cool and new.
    /// </summary>
    /// <remarks>It does so by calling the private method <c>SomethingSuperCoolAndNew</c>.</remarks>
    protected override void Execute()
    {
        int x = 3;
        SomethingSuperCoolAndNew(x);
    }

    /// <summary>
    /// Important things happen here.
    /// </summary>
    /// <param name="someArg">Magic parameter.</param>
    private void SomethingSuperCoolAndNew(int someArg)
    {
        // Do something super cool and new.
    }
}

在输出目录(bin \ Debug)中,编译器将创建一个如下所示的XML文件:

<?xml version="1.0"?>
<doc>
    <assembly>
        <name>StackOverflowTests3</name>
    </assembly>
    <members>
        <member name="T:StackOverflowTests3.SandboxModule">
            <summary>
            Base module for sandboxed operations.
            </summary>
        </member>
        <member name="M:StackOverflowTests3.SandboxModule.Execute">
            <summary>
            Implementing modues must override this method.
            </summary>
        </member>
        <member name="T:StackOverflowTests3.DemoModule">
            <summary>
            This is my super cool demo module.
            </summary>
        </member>
        <member name="M:StackOverflowTests3.DemoModule.Execute">
            <summary>
            Does something super cool and new.
            </summary>
            <remarks>It does so by calling the private method <c>SomethingSuperCoolAndNew</c>.</remarks>
        </member>
        <member name="M:StackOverflowTests3.DemoModule.SomethingSuperCoolAndNew(System.Int32)">
            <summary>
            Important things happen here.
            </summary>
            <param name="someArg">Magic parameter.</param>
        </member>
    </members>
</doc>

此《 Visual Studio杂志》文章介绍了如何将这些XML文件转换为帮助文件:Doing Visual Studio and .NET Code Documentation Right

甚至在Visual Studio的IntelliSense工具提示中也可以看到文档注释。