You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Roslyn项目SymbolFinder空异常及方法引用获取技术咨询

Why methodToSearchFor Throws a NullReferenceException & How to Use SymbolFinder Correctly

Reasons for the Null Exception

Let’s walk through why you’re hitting that null error when trying to get methodToSearchFor:

  • Case-sensitive metadata names: Roslyn’s GetTypeByMetadataName is strict about casing. Double-check that "ConsoleApp6.Person" matches your actual class’s full name exactly—namespace included, no typos in capitalization.
  • Failed project compilation: If your project has build errors, GetCompilationAsync().Result will return a compilation that can’t resolve symbols properly. Always verify if classWithMethodToSearchFor is null first; if it is, your compilation likely failed.
  • Empty member result: GetMembers("Add") might return an empty sequence if no matching member exists. Calling First() on an empty sequence throws an exception—use FirstOrDefault() instead to handle this gracefully.
  • Entry point typo: Your main method is lowercase, but C# requires the entry point to be static void Main() (uppercase M). While this doesn’t directly cause the symbol issue, it can prevent your program from running as expected.

Proper Usage of SymbolFinder to Get Method References

Here’s a revised, robust version of your code that fixes the null issue and uses SymbolFinder correctly:

namespace consoleApp6
{
    public class Person
    {
        public int Add()
        {
            return 400;
        }

        // Corrected entry point casing
        static void Main()
        {
            string solutionPath = @"C:\Users\sslindia\source\repos\ConsoleApp6\ConsoleApp6.sln";
            var msWorkspace = MSBuildWorkspace.Create();
            
            // Check for solution load errors
            var solution = msWorkspace.OpenSolutionAsync(solutionPath).Result;
            if (msWorkspace.Diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error))
            {
                Console.WriteLine("Failed to load solution: " + string.Join("\n", msWorkspace.Diagnostics));
                return;
            }

            var targetProject = solution.Projects.FirstOrDefault(x => x.Name == "ConsoleApp6");
            if (targetProject == null)
            {
                Console.WriteLine("Target project 'ConsoleApp6' not found");
                return;
            }

            var compilation = targetProject.GetCompilationAsync().Result;
            // Validate compilation succeeded
            var compilationErrors = compilation.GetDiagnostics().Where(d => d.Severity == DiagnosticSeverity.Error);
            if (compilationErrors.Any())
            {
                Console.WriteLine("Compilation failed with errors:\n" + string.Join("\n", compilationErrors.Select(e => e.GetMessage())));
                return;
            }

            var personClass = compilation.GetTypeByMetadataName("consoleApp6.Person"); // Match namespace casing exactly
            if (personClass == null)
            {
                Console.WriteLine("Person class not found in compilation");
                return;
            }

            // Filter to only method symbols to avoid non-method matches
            var addMethod = personClass.GetMembers("Add").OfType<IMethodSymbol>().FirstOrDefault();
            if (addMethod == null)
            {
                Console.WriteLine("Add method not found in Person class");
                return;
            }

            // Retrieve method references and callers
            var references = SymbolFinder.FindReferencesAsync(addMethod, solution).Result;
            var callers = SymbolFinder.FindCallersAsync(addMethod, solution).Result;

            int totalReferences = references.Sum(r => r.Locations.Count());
            Console.WriteLine($"Total references found: {totalReferences}");

            // Optional: Print detailed caller info
            Console.WriteLine("\nCaller details:");
            foreach (var caller in callers)
            {
                var firstLocation = caller.Locations.First();
                Console.WriteLine($"- Caller: {caller.CallerSymbol.Name} | File: {firstLocation.Document.FilePath} | Line: {firstLocation.GetLineSpan().StartLinePosition.Line + 1}");
            }
        }
    }
}

Key Improvements:

  • Step-by-step error checking: We validate every intermediate result (solution load, project existence, compilation success, etc.) to catch issues early and provide clear feedback.
  • Targeted symbol filtering: Using OfType<IMethodSymbol>() ensures we only retrieve method symbols, avoiding accidental matches with fields/properties that share the same name.
  • Safer LINQ operations: FirstOrDefault() replaces First() to prevent exceptions when no matching elements are found.
  • Diagnostic checks: We surface solution and compilation errors, which are often the root cause of symbol resolution failures.

Quick Tips for SymbolFinder:

  • FindReferencesAsync returns all usages (declarations, calls, references), while FindCallersAsync focuses specifically on places where the method is invoked.
  • For large solutions, use await instead of .Result to avoid blocking the main thread (better async practice, even in console apps).
  • Always ensure your solution builds cleanly—Roslyn can’t resolve symbols correctly if there are unresolved errors.

内容的提问来源于stack exchange,提问作者Kabilan Kannan8

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:12:40