如何将DNode.Dump()作为具有LINQPad中属性的常规对象?

时间:2018-09-28 17:29:21

标签: linqpad

通常,LINQPad中的.Dump()扩展方法将XNode及其派生类实例显示为呈现的XML片段。有时,在开发代码时,我希望以转储其他类型的表形式查看对象的实际属性,例如显示节点及其{{1的Name,Value,FirstAttribute和whatsnot属性的表}}值,或子对象的交互式可扩展集合。简而言之,好像根本没有对XNode进行特殊处理。

我正在通过转储单个属性来解决此问题,但这很繁琐。

This answer建议编写一个自定义扩展代码,以实现另一种类型(即IEnumerable)的类似效果,但这种情况似乎比我正在处理的情况更狭窄,更罕见。

是否有一种开箱即用的方式来做我想做的事?

2 个答案:

答案 0 :(得分:0)

LINQPad支持为类型自定义Dump。使用某些扩展方法,您可以将类型转换为ExpandoObject,然后将它们与属性一起输出。

在“我的扩展”中,在MyExtensions类之后,添加一个顶级方法:

static object ToDump(object obj) {
    if (obj is XObject x)
        return x.ToExpando();
    else
        return obj;
}

MyExtensions类中,添加以下扩展方法。我已经有了object-> Dictionary方法来转换为匿名对象,所以我使用了这些方法,但是您可以将它们结合起来在ToExpando上创建单个object:< / p>

public static ExpandoObject ToExpando(this object obj) => obj.ToDictionary().ToExpando();

public static IDictionary<string, object> ToDictionary(this object obj) {
    if (obj is IDictionary<string, object> id)
        return id;
    else {
        var dictAnsObj = new Dictionary<string, object>();

        foreach (var prop in obj.GetType().GetPropertiesOrFields()) {
            try {
                dictAnsObj.Add(prop.Name, prop.GetValue(obj));
            }
            catch (Exception ex) {
                dictAnsObj.Add(prop.Name, ex);
            }
        }

        return dictAnsObj;
    }
}

public static ExpandoObject ToExpando(this IDictionary<string, object> objDict) {
    var e = new ExpandoObject();
    var di = (IDictionary<string, object>)e;

    foreach (var kvp in objDict)
        di.Add(kvp);

    return e;
}

您还将需要此Type扩展名:

// ***
// *** Type Extensions
// ***
public static List<MemberInfo> GetPropertiesOrFields(this Type t, BindingFlags bf = BindingFlags.Public | BindingFlags.Instance) =>
    t.GetMembers(bf).Where(mi => mi.MemberType == MemberTypes.Field | mi.MemberType == MemberTypes.Property).ToList();

如果可以只以类格式显示顶级对象,则可以在需要时使用此扩展方法:

public static T DumpAs<T, NewT>(this T obj, Func<T, NewT> castFn, string description = null) {
    if (description != null)
        castFn(obj).Dump(description);
    else
        castFn(obj).Dump();

    return obj;
}

例如,

XElement xn;
xn.DumpAs(x => x.ToExpando());

否则,您将必须注释掉ToDump方法或使用流利的方法进行一些棘手的操作才能将其打开和关闭。

答案 1 :(得分:0)

此答案取决于先前的答案,但需要时,可以使用其他扩展方法和XObject方法将其扩展为将转储ToDump作为类处理。否则,它使用与我以前的答案相同的扩展名。

MyExtensions类中,添加新的转储类型和bool来跟踪状态:

public static bool bDumpAsClass = false;

public static object DumpAsClass(this object input, string descr = null) {
    bDumpAsClass = true;
    if (descr != null)
        input.Dump(descr);
    else
        input.Dump();
    bDumpAsClass = false;
    return input;
}

MyExtensions类之外,添加使用ToDump的{​​{1}}方法:

bool

然后,当您要将static object ToDump(object obj) { if (MyExtensions.bDumpAsClass) { if (obj is XObject x) return x.ToExpando(); } return obj; } 或后代作为类转储时,只要扩展任何成员,就可以只使用DumpAsClass而不是Dump

很明显,您可以扩展XObject为true时处理的类型。