首页 > 解决方案 > 是否可以在调试时声明 C# 方法/函数?

问题描述

假设您设想了一些扩展方法,它将以某种方式将对象转换为对调试有用的东西。一个例子是一个sqlCommand.ToScript() 扩展方法,它将返回一个关于执行的 T-SQL 脚本版本的字符串(它会在脚本的顶部声明参数等)。你想要那个扩展方法(或者至少一些函数/方法)在调试时可用,但你不想在你的代码库中实际定义它,因为它会让团队感觉很混乱。

我不认为即时窗口可以定义函数,可以吗?有 C# 交互窗口,但是在我遇到断点后,它可以与当前执行的堆栈交互吗?

我听说 Reflection.Emit() 可以在运行时添加新代码。我可以以某种方式使用它吗?

标签: c#.netdebuggingreflection.emit

解决方案


除了扩展 Immediate Window 或为 VS 创建新的扩展外,我可以想到以下解决方案,让您有一些调试方法:

  • 使用#if DEBUG + 部分类或扩展方法
  • 使用条件引用 + 扩展方法
  • 在即时窗口中使用 Assembly.Load + 扩展方法

我将分享上述每个解决方案的示例。

使用#if DEBUG + 部分类或扩展方法

您可以使用#if DEBUG。对于代码库中的类型,您可以使用部分类将调试方法分组到类的其他部分,如下所示:

public partial class MyClass
{
#if DEBUG
    public string SaySomething()
    {
        return "Something!";
    }
#endif 
}

对于不属于您的类型,您可以使用这样的扩展方法(您也可以将此解决方案用于属于您的类型):

public static class SqlCommandExtensions
{
#if DEBUG
    public static string SaySomething(this SqlCommand command)
    {
        return "Something!";
    }
#endif
}

使用条件引用 + 扩展方法

如果您想将所有这些代码放在不同的库中,您可以创建一个类库并将扩展类放在全局命名空间(无命名空间)中,然后添加条件引用:

<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
  <Reference Include="GlobalExtensions">
    <HintPath>..\Somewhere\GlobalExtensions.dll</HintPath>
  </Reference>
</ItemGroup>

在此解决方案中,您不需要 if 调试。

public static class SqlCommandExtensions
{
    public static string SaySomething(this SqlCommand command)
    {
        return "Something!";
    }
}

在即时窗口中使用 Assembly.Load + 扩展方法

作为另一种选择,您可以创建另一个程序集,然后将这些扩展方法放在该程序集中的全局命名空间(无命名空间)中。然后在不添加引用的情况下,仅在调试时,在即时窗口中您可以使用它们:

Assembly.LoadFile(@"C:\Somewhere\GlobalExtensions.dll")
yourSqlCommand.SaySomething()

在此解决方案中,您不需要调试,也不需要任何添加引用,它仅在调试时和即时窗口可用:

public static class SqlCommandExtensions
{
    public static string SaySomething(this SqlCommand command)
    {
        return "Something!";
    }
}

您不会在即时窗口中获得智能感知,但它可以工作。


推荐阅读