调试.NET动态方法

Iha*_*ury 5 .net c# linq debugging dynamic-method

我们在系统中使用LINQ非常广泛.特别是LINQ到对象.所以在某些地方我们最终会在内存中使用一些巨大的表达式构建LINQ查询.当表达式中存在一些错误时,就会出现问题.所以我们得到NullReferenceException并且堆栈跟踪导致我们无处可去(到[Lightweight Function]).该异常被抛出在LINQ生成的动态方法中.

有没有简单的方法来调试这样的动态方法?或者我是否必须牺牲自己来学习WinDBG?:-)

Mar*_*ell 4

如果您正在构建自己的表达式并编译它们,或者使用 AsQueryable,那么是的;LINQ 生成的方法调试起来会非常痛苦。

您可以通过使用实际方法的小片段来节省一些痛苦 - 至少在堆栈跟踪中会显示一些有用的内容......

另一个考虑因素是:与其使用一个巨大的表达式,如果您可以将事物以菊花链方式连接得更多,您可能会(从堆栈跟踪)更多地了解它失败的地方。缺点是性能 -Where(foo).Where(bar) 是两个委托调用,where-asWhere(foo && bar) 可以是一个。

一种选择可能是交换扩展方法的调试版本;不幸的是,这有点不方便,因为IQueryable<T>Queryable位于同一个命名空间中......但这可行......

先输出:

>Where: x => ((x % 2) = 0)
<Where: x => ((x % 2) = 0)
>Count
'WindowsFormsApplication2.vshost.exe' (Managed): Loaded 'Anonymously Hosted DynamicMethods Assembly'
<Count
Run Code Online (Sandbox Code Playgroud)

代码:

using System;
using System.Diagnostics;
using System.Linq.Expressions;

namespace Demo
{
    using DebugLinq;
    static class Program
    {
        static void Main()
        {
            var data = System.Linq.Queryable.AsQueryable(new[] { 1, 2, 3, 4, 5 });
            data.Where(x => x % 2 == 0).Count(); 
        }
    }
}
namespace DebugLinq
{
    public static class DebugQueryable
    {
        public static int Count<T>(this System.Linq.IQueryable<T> source)
        {
            return Wrap(() => System.Linq.Queryable.Count(source), "Count");
        }

        public static System.Linq.IQueryable<T> Where<T>(this System.Linq.IQueryable<T> source, Expression<Func<T, bool>> predicate)
        {
            return Wrap(() => System.Linq.Queryable.Where(source, predicate), "Where: " + predicate);
        }
        static TResult Wrap<TResult>(Func<TResult> func, string caption)
        {
            Debug.WriteLine(">" + caption);
            try
            {
                TResult result = func();
                Debug.WriteLine("<" + caption);
                return result;
            }
            catch
            {
                Debug.WriteLine("!" + caption);
                throw;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)