C#中的编译时反射

本文关键字:反射 编译 | 更新日期: 2023-09-27 18:25:11

我经常编写C#代码,这些代码必须使用魔术字符串来表示属性名称。每个人都知道魔术串的问题。它们很难重构,没有编译时检查,而且通常会导致难以诊断的问题。然而,C#/.NET到处都使用它们来表示属性/类/方法名。

这个问题已经存在多年了,目前唯一可行的解决方案是使用表达式树,然后在运行时解析属性名称。这可以获得令人满意的编译时检查,但会使代码复杂化(需要Expression类型的参数),会导致运行时开销。

有人知道C#/.NET是否考虑过添加编译时反射来克服这个普遍存在的问题吗?

这似乎是一个很容易添加的内容,这将是一个不间断的更改,它将极大地造福于许多开发人员。typeof()操作符已经执行了某种形式的编译时反射,所以看起来操作符名称of(或类似的东西)是非常好的。

此外,有人知道这样一个功能可能存在的问题吗?

谢谢你的帮助。

C#中的编译时反射

来源直接-这是一篇由C#语言设计师撰写的博客文章,文章中的"用户"提出了与您相同的问题,并得到了回答。作者说,需要为你想要的每个元数据项指定一个语法,这并不是一件小事——比如,如果你想要"info of"方法,而该方法被重载了,你想要哪个重载?如果涉及泛型和显式接口实现,该怎么办?等等。事实证明,尽管由于这些原因,它在2009年被认为不值得实施,但我们将在2015年在C#中实现它——参见2014年7月9日的C#语言设计说明。

在C#6.0中,添加了一个新的运算符nameof,它将允许您在编译时获得属性、类、字段、事件和变量的名称。

设计说明链接

不再反映编译器在设计时已经知道的信息!

我也遇到了类似的问题。最近才发现.NET Framework 4.5具有一个名为"呼叫者信息"属性的功能。通过使用这些,您可以在编译时获得有关方法调用方的信息。您可以获取源代码的文件路径、源代码中的行号以及调用方的成员名称。

public void DoProcessing()
{
    TraceMessage("Something happened.");
}
public void TraceMessage(string message,
        [CallerMemberName] string memberName = "",
        [CallerFilePath] string sourceFilePath = "",
        [CallerLineNumber] int sourceLineNumber = 0)
{
    Trace.WriteLine("message: " + message);
    Trace.WriteLine("member name: " + memberName);
    Trace.WriteLine("source file path: " + sourceFilePath);
    Trace.WriteLine("source line number: " + sourceLineNumber);
}

然而,C#/.NET在所有地方都使用它们来表示属性/类/方法名。

首先:我不同意。有些框架(例如WebForms)到处都在使用魔术串,但C#和.NET的基本库往往很好地避免了这种情况。

第二:在许多使用魔术串的情况下,ReSharper能够识别错误。这会有很大帮助。

最后:您的要求可以通过Roslyn编译器实现,该编译器承诺提供"编译即服务"。