字符串的反射类型在IDE和代码中有所不同



我有一个记录器,它抽象了对NLog的调用。我希望每个日志行都有它的调用者来源。一些带有泛型的代码会导致奇怪的调用方名称:

代理服务`1[MyNameSpace.IController]

在IDE中,当我将鼠标悬停在变量调用程序上时,它会弹出正确的名称:

MyNameSpace.ProxyService

如何获得与IDE弹出的值相同的值?

代码样本:

private void SetLogEventInfo(object caller, ILogger logger)
        {
            string callerOrigin = null;
            if (caller != null)
            {
                callerOrigin = caller.ToString();
            }
            <code removed>
        }

您可以通过连接来获得类似于IDE的结果

Type type = value.GetType();
return type.Namespace + "." + type.Name;

通过这种方式可以获得MyNameSpace.ProxyService`1`1位指的是泛型类型中类型参数的数量。没有它,这个名字就是ambigus。如果您坚持要删除它,可以使用常用的字符串操作(IndexOfRemove)。

首先,我们的IDE以C#表示法向您显示类名,System.Reflection与语言无关,因此存在差异。

其次,不要依赖ToString()。只有在未重写的情况下,它才会显示类型名称(因此使用默认的Object实现)。在多个有效的场景中,您希望覆盖ToString(),这会破坏您的代码。

模拟C#代码格式是AFAIK不可用的开箱即用,但有一些技巧可以做到这一点,例如:

var cSharpProvider = CodeDomProvider.CreateProvider("C#");
var variableDecl = new CodeVariableDeclarationStatement(caller.GetType(), "_");
var sb = new StringBuilder();
using (var sw = new StringWriter(sb))
{
   cSharpProvider.GenerateCodeFromStatement(variableDecl,
                                            sw,
                                            new CodeGeneratorOptions());
}
sb.Replace("_;", String.Empty);
var callerOrigin = sb.ToString().Trim();

正在调用对象的ToString方法,如果不重写该方法,它将简单地返回类型名称,相当于:

public string ToString() {
    return this.GetType().ToString();
}

如果您愿意,可以重写ToString,但这显然不适用于您无法控制的类型。例如,如果List<string>的一个实例被传递到该方法中,那么您最终会得到:

System.Collections.Generic.List`1[System.String]

这可能对你没有好处。因此,最好的办法是修改上面的代码以格式化类型:

callerOrigin = FormatObjectForLog(caller);

该方法可能会做一些类似的事情(你可以填空,因为我对你的需求了解不够,无法决定如何处理ProxyService`1以外的情况):

string FormatObjectForLog(object obj) {
    if (obj is IFormattable)
        return obj.ToString();
    if (obj.GetType().IsGenericType) {
        // Get rid of `1 and other crud...
    }
    ...
}

一个版本的净化类型格式化程序可以消除反勾号,如下所示:

public string FormatType(Type t) {
    if (t.IsGenericType) {
        return string.Format(
            "{0}.{1}<{2}>",
            t.Namespace,
            t.Name.Substring(0, t.Name.IndexOf('`')),
            string.Join(", ", t.GetGenericArguments().Select(FormatType))
        );
    }
    return t.ToString();
}

相关内容

  • 没有找到相关文章

最新更新